/*
 * Copyright (C) 2008 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#include <pathconf.h>
#include <sys/vfs.h>
#include <sys/limits.h>
#include <linux/ext2_fs.h>
#include <linux/ext3_fs.h>
#include <errno.h>

/* these may not be defined yet by our headers */
#ifndef _POSIX_VDISABLE
#define _POSIX_VDISABLE  -1
#endif

#ifndef _POSIX_SYNC_IO
#define _POSIX_SYNC_IO  -1
#endif

#ifndef _POSIX_PRIO_IO
#define _POSIX_PRIO_IO  -1
#endif

#ifndef _POSIX_ASYNC_IO
#define _POSIX_ASYNC_IO  -1
#endif


static long
__filesizebits( struct statfs*  s )
{
#define   EOL_MAGIC   0x0000U

    /* list of known 64-bit aware filesystems */
    static const uint32_t  known64[] = {
        EXT2_SUPER_MAGIC,
        UFS_MAGIC,
        REISERFS_SUPER_MAGIC,
        XFS_SUPER_MAGIC,
        SMB_SUPER_MAGIC,
        UDF_SUPER_MAGIC,
        JFS_SUPER_MAGIC,
        NTFS_SB_MAGIC,
        VXFS_SUPER_MAGIC,
        EOL_MAGIC
    };
    int  nn = 0;

    for (; known64[nn] != EOL_MAGIC; ++nn) {
        if (known64[nn] == s->f_type) {
            return 64;
        }
    }
    return 32;
}


static long
__link_max( struct statfs*  s )
{
   /* constant values were taken from official kernel headers.
    * I don't think this justified bringing in <linux/minix_fs.h> et al
    * into our cleaned-up kernel three
    */
    static const struct { uint32_t  type; int  max; }  knownMax[] =
    {
        { EXT2_SUPER_MAGIC, EXT2_LINK_MAX },
        { EXT3_SUPER_MAGIC, EXT3_LINK_MAX },
        { MINIX_SUPER_MAGIC, 250 },
        { MINIX2_SUPER_MAGIC, 65530 },
        { REISERFS_SUPER_MAGIC, 0xffff - 1000 },
        { UFS_MAGIC, 32000 },
        { EOL_MAGIC, 0 }
    };
    int   nn = 0;

    for (; knownMax[nn].type != EOL_MAGIC; ++nn) {
        if (knownMax[nn].type == s->f_type) {
            return knownMax[nn].max;
        }
    }
    return LINK_MAX;
}

static long
__2_symlinks( struct statfs*  s )
{
    /* list of know filesystems that don't support symlinks */
    static const uint32_t  knownNoSymlinks[] = {
        ADFS_SUPER_MAGIC, BFS_MAGIC, CRAMFS_MAGIC,
        EFS_SUPER_MAGIC, MSDOS_SUPER_MAGIC, NTFS_SB_MAGIC,
        QNX4_SUPER_MAGIC,
        EOL_MAGIC
    };
    int  nn = 0;

    for (; knownNoSymlinks[nn] != EOL_MAGIC; ++nn) {
        if (knownNoSymlinks[nn] == s->f_type) {
            return 0;
        }
    }
    return 1;
}

static long
__name_max( struct statfs*  s )
{
    return s->f_namelen;
}

long
pathconf(const char *path, int name)
{
    struct statfs  buf;
    int            ret = statfs( path, &buf );

    if (ret < 0)
        return -1;

    switch (name) {
    case _PC_FILESIZEBITS:
        return __filesizebits(&buf);

    case _PC_LINK_MAX:
        return __link_max(&buf);

    case _PC_MAX_CANON:
        return MAX_CANON;

    case _PC_MAX_INPUT:
        return MAX_INPUT;

    case _PC_NAME_MAX:
        return __name_max(&buf);

    case _PC_PATH_MAX:
        return PATH_MAX;

    case _PC_PIPE_BUF:
        return PIPE_BUF;

    case _PC_2_SYMLINKS:
        return __2_symlinks(&buf);

#if 0  /* don't know what to do there, the specs are really weird */
    case _PC_ALLOC_SIZE_MIN:
    case _PC_REC_INCR_XFER_SIZE:
    case _PC_REC_MAX_XFER_SIZE:
    case _PC_REC_MIN_XFER_SIZE:
    case _PC_REC_XFER_ALIGN:
#endif

    case _PC_SYMLINK_MAX:
        return -1;  /* no limit */

    case _PC_CHOWN_RESTRICTED:
        return _POSIX_CHOWN_RESTRICTED;

    case _PC_NO_TRUNC:
        return _POSIX_NO_TRUNC;

    case _PC_VDISABLE:
        return _POSIX_VDISABLE;

    case _PC_ASYNC_IO:
        return _POSIX_ASYNC_IO;

    case _PC_PRIO_IO:
        return _POSIX_PRIO_IO;

    case _PC_SYNC_IO:
        return _POSIX_SYNC_IO;

    default:
        errno = EINVAL;
        return -1;
    }
}

long fpathconf(int fildes, int name)
{
    struct statfs  buf;
    int            ret = fstatfs(fildes, &buf);

    if (ret < 0)
        return -1;

    switch (name) {
    case _PC_FILESIZEBITS:
        return __filesizebits(&buf);

    case _PC_LINK_MAX:
        return __link_max(&buf);

    case _PC_MAX_CANON:
        return MAX_CANON;

    case _PC_MAX_INPUT:
        return MAX_INPUT;

    case _PC_NAME_MAX:
        return __name_max(&buf);

    case _PC_PATH_MAX:
        return PATH_MAX;

    case _PC_PIPE_BUF:
        return PIPE_BUF;

    case _PC_2_SYMLINKS:
        return __2_symlinks(&buf);

#if 0  /* don't know what to do there, the specs are really weird */
    case _PC_ALLOC_SIZE_MIN:
    case _PC_REC_INCR_XFER_SIZE:
    case _PC_REC_MAX_XFER_SIZE:
    case _PC_REC_MIN_XFER_SIZE:
    case _PC_REC_XFER_ALIGN:
#endif

    case _PC_SYMLINK_MAX:
        return -1;  /* no limit */

    case _PC_CHOWN_RESTRICTED:
        return _POSIX_CHOWN_RESTRICTED;

    case _PC_NO_TRUNC:
        return _POSIX_NO_TRUNC;

    case _PC_VDISABLE:
        return _POSIX_VDISABLE;

    case _PC_ASYNC_IO:
        return _POSIX_ASYNC_IO;

    case _PC_PRIO_IO:
        return _POSIX_PRIO_IO;

    case _PC_SYNC_IO:
        return _POSIX_SYNC_IO;

    default:
        errno = EINVAL;
        return -1;
    }
}
