Home | History | Annotate | Download | only in unistd
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 #include <pathconf.h>
     29 #include <sys/vfs.h>
     30 #include <sys/limits.h>
     31 #include <linux/ext2_fs.h>
     32 #include <linux/ext3_fs.h>
     33 #include <errno.h>
     34 
     35 /* these may not be defined yet by our headers */
     36 #ifndef _POSIX_VDISABLE
     37 #define _POSIX_VDISABLE  -1
     38 #endif
     39 
     40 #ifndef _POSIX_SYNC_IO
     41 #define _POSIX_SYNC_IO  -1
     42 #endif
     43 
     44 #ifndef _POSIX_PRIO_IO
     45 #define _POSIX_PRIO_IO  -1
     46 #endif
     47 
     48 #ifndef _POSIX_ASYNC_IO
     49 #define _POSIX_ASYNC_IO  -1
     50 #endif
     51 
     52 
     53 static long
     54 __filesizebits( struct statfs*  s )
     55 {
     56 #define   EOL_MAGIC   0x0000U
     57 
     58     /* list of known 64-bit aware filesystems */
     59     static const uint32_t  known64[] = {
     60         EXT2_SUPER_MAGIC,
     61         UFS_MAGIC,
     62         REISERFS_SUPER_MAGIC,
     63         XFS_SUPER_MAGIC,
     64         SMB_SUPER_MAGIC,
     65         UDF_SUPER_MAGIC,
     66         JFS_SUPER_MAGIC,
     67         NTFS_SB_MAGIC,
     68         VXFS_SUPER_MAGIC,
     69         EOL_MAGIC
     70     };
     71     int  nn = 0;
     72 
     73     for (;;) {
     74         if ( known64[nn] == EOL_MAGIC )
     75             return 32;
     76 
     77         if ( known64[nn] == s->f_type )
     78             return 64;
     79     }
     80 }
     81 
     82 
     83 static long
     84 __link_max( struct statfs*  s )
     85 {
     86    /* constant values were taken from official kernel headers.
     87     * I don't think this justified bringing in <linux/minix_fs.h> et al
     88     * into our cleaned-up kernel three
     89     */
     90     static const struct { uint32_t  type; int  max; }  knownMax[] =
     91     {
     92         { EXT2_SUPER_MAGIC, EXT2_LINK_MAX },
     93         { EXT3_SUPER_MAGIC, EXT3_LINK_MAX },
     94         { MINIX_SUPER_MAGIC, 250 },
     95         { MINIX2_SUPER_MAGIC, 65530 },
     96         { REISERFS_SUPER_MAGIC, 0xffff - 1000 },
     97         { UFS_MAGIC, 32000 },
     98         { EOL_MAGIC, 0 }
     99     };
    100     int   nn = 0;
    101 
    102     for (;;) {
    103         if ( knownMax[nn].type == EOL_MAGIC )
    104             return LINK_MAX;
    105 
    106         if ( knownMax[nn].type == s->f_type )
    107             return knownMax[nn].max;
    108     }
    109     return LINK_MAX;
    110 }
    111 
    112 static long
    113 __2_symlinks( struct statfs*  s )
    114 {
    115     /* list of know filesystems that don't support symlinks */
    116     static const uint32_t  knownNoSymlinks[] = {
    117         ADFS_SUPER_MAGIC, BFS_MAGIC, CRAMFS_MAGIC,
    118         EFS_SUPER_MAGIC, MSDOS_SUPER_MAGIC, NTFS_SB_MAGIC,
    119         QNX4_SUPER_MAGIC,
    120         EOL_MAGIC
    121     };
    122     int  nn = 0;
    123 
    124     for (;;) {
    125         if (knownNoSymlinks[nn] == 0)
    126             return 1;
    127         if (knownNoSymlinks[nn] == s->f_type)
    128             return 0;
    129     }
    130 }
    131 
    132 static long
    133 __name_max( struct statfs*  s )
    134 {
    135     return s->f_namelen;
    136 }
    137 
    138 long
    139 pathconf(const char *path, int name)
    140 {
    141     struct statfs  buf;
    142     int            ret = statfs( path, &buf );
    143 
    144     if (ret < 0)
    145         return -1;
    146 
    147     switch (name) {
    148     case _PC_FILESIZEBITS:
    149         return __filesizebits(&buf);
    150 
    151     case _PC_LINK_MAX:
    152         return __link_max(&buf);
    153 
    154     case _PC_MAX_CANON:
    155         return MAX_CANON;
    156 
    157     case _PC_MAX_INPUT:
    158         return MAX_INPUT;
    159 
    160     case _PC_NAME_MAX:
    161         return __name_max(&buf);
    162 
    163     case _PC_PATH_MAX:
    164         return PATH_MAX;
    165 
    166     case _PC_PIPE_BUF:
    167         return PIPE_BUF;
    168 
    169     case _PC_2_SYMLINKS:
    170         return __2_symlinks(&buf);
    171 
    172 #if 0  /* don't know what to do there, the specs are really weird */
    173     case _PC_ALLOC_SIZE_MIN:
    174     case _PC_REC_INCR_XFER_SIZE:
    175     case _PC_REC_MAX_XFER_SIZE:
    176     case _PC_REC_MIN_XFER_SIZE:
    177     case _PC_REC_XFER_ALIGN:
    178 #endif
    179 
    180     case _PC_SYMLINK_MAX:
    181         return -1;  /* no limit */
    182 
    183     case _PC_CHOWN_RESTRICTED:
    184         return _POSIX_CHOWN_RESTRICTED;
    185 
    186     case _PC_NO_TRUNC:
    187         return _POSIX_NO_TRUNC;
    188 
    189     case _PC_VDISABLE:
    190         return _POSIX_VDISABLE;
    191 
    192     case _PC_ASYNC_IO:
    193         return _POSIX_ASYNC_IO;
    194 
    195     case _PC_PRIO_IO:
    196         return _POSIX_PRIO_IO;
    197 
    198     case _PC_SYNC_IO:
    199         return _POSIX_SYNC_IO;
    200 
    201     default:
    202         errno = EINVAL;
    203         return -1;
    204     }
    205 }
    206 
    207 long fpathconf(int fildes, int name)
    208 {
    209     struct statfs  buf;
    210     int            ret = fstatfs(fildes, &buf);
    211 
    212     if (ret < 0)
    213         return -1;
    214 
    215     switch (name) {
    216     case _PC_FILESIZEBITS:
    217         return __filesizebits(&buf);
    218 
    219     case _PC_LINK_MAX:
    220         return __link_max(&buf);
    221 
    222     case _PC_MAX_CANON:
    223         return MAX_CANON;
    224 
    225     case _PC_MAX_INPUT:
    226         return MAX_INPUT;
    227 
    228     case _PC_NAME_MAX:
    229         return __name_max(&buf);
    230 
    231     case _PC_PATH_MAX:
    232         return PATH_MAX;
    233 
    234     case _PC_PIPE_BUF:
    235         return PIPE_BUF;
    236 
    237     case _PC_2_SYMLINKS:
    238         return __2_symlinks(&buf);
    239 
    240 #if 0  /* don't know what to do there, the specs are really weird */
    241     case _PC_ALLOC_SIZE_MIN:
    242     case _PC_REC_INCR_XFER_SIZE:
    243     case _PC_REC_MAX_XFER_SIZE:
    244     case _PC_REC_MIN_XFER_SIZE:
    245     case _PC_REC_XFER_ALIGN:
    246 #endif
    247 
    248     case _PC_SYMLINK_MAX:
    249         return -1;  /* no limit */
    250 
    251     case _PC_CHOWN_RESTRICTED:
    252         return _POSIX_CHOWN_RESTRICTED;
    253 
    254     case _PC_NO_TRUNC:
    255         return _POSIX_NO_TRUNC;
    256 
    257     case _PC_VDISABLE:
    258         return _POSIX_VDISABLE;
    259 
    260     case _PC_ASYNC_IO:
    261         return _POSIX_ASYNC_IO;
    262 
    263     case _PC_PRIO_IO:
    264         return _POSIX_PRIO_IO;
    265 
    266     case _PC_SYNC_IO:
    267         return _POSIX_SYNC_IO;
    268 
    269     default:
    270         errno = EINVAL;
    271         return -1;
    272     }
    273 }
    274