Home | History | Annotate | Download | only in bionic
      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 (; known64[nn] != EOL_MAGIC; ++nn) {
     74         if (known64[nn] == s->f_type) {
     75             return 64;
     76         }
     77     }
     78     return 32;
     79 }
     80 
     81 
     82 static long
     83 __link_max( struct statfs*  s )
     84 {
     85    /* constant values were taken from official kernel headers.
     86     * I don't think this justified bringing in <linux/minix_fs.h> et al
     87     * into our cleaned-up kernel three
     88     */
     89     static const struct { uint32_t  type; int  max; }  knownMax[] =
     90     {
     91         { EXT2_SUPER_MAGIC, EXT2_LINK_MAX },
     92         { EXT3_SUPER_MAGIC, EXT3_LINK_MAX },
     93         { MINIX_SUPER_MAGIC, 250 },
     94         { MINIX2_SUPER_MAGIC, 65530 },
     95         { REISERFS_SUPER_MAGIC, 0xffff - 1000 },
     96         { UFS_MAGIC, 32000 },
     97         { EOL_MAGIC, 0 }
     98     };
     99     int   nn = 0;
    100 
    101     for (; knownMax[nn].type != EOL_MAGIC; ++nn) {
    102         if (knownMax[nn].type == s->f_type) {
    103             return knownMax[nn].max;
    104         }
    105     }
    106     return LINK_MAX;
    107 }
    108 
    109 static long
    110 __2_symlinks( struct statfs*  s )
    111 {
    112     /* list of know filesystems that don't support symlinks */
    113     static const uint32_t  knownNoSymlinks[] = {
    114         ADFS_SUPER_MAGIC, BFS_MAGIC, CRAMFS_MAGIC,
    115         EFS_SUPER_MAGIC, MSDOS_SUPER_MAGIC, NTFS_SB_MAGIC,
    116         QNX4_SUPER_MAGIC,
    117         EOL_MAGIC
    118     };
    119     int  nn = 0;
    120 
    121     for (; knownNoSymlinks[nn] != EOL_MAGIC; ++nn) {
    122         if (knownNoSymlinks[nn] == s->f_type) {
    123             return 0;
    124         }
    125     }
    126     return 1;
    127 }
    128 
    129 static long
    130 __name_max( struct statfs*  s )
    131 {
    132     return s->f_namelen;
    133 }
    134 
    135 long
    136 pathconf(const char *path, int name)
    137 {
    138     struct statfs  buf;
    139     int            ret = statfs( path, &buf );
    140 
    141     if (ret < 0)
    142         return -1;
    143 
    144     switch (name) {
    145     case _PC_FILESIZEBITS:
    146         return __filesizebits(&buf);
    147 
    148     case _PC_LINK_MAX:
    149         return __link_max(&buf);
    150 
    151     case _PC_MAX_CANON:
    152         return MAX_CANON;
    153 
    154     case _PC_MAX_INPUT:
    155         return MAX_INPUT;
    156 
    157     case _PC_NAME_MAX:
    158         return __name_max(&buf);
    159 
    160     case _PC_PATH_MAX:
    161         return PATH_MAX;
    162 
    163     case _PC_PIPE_BUF:
    164         return PIPE_BUF;
    165 
    166     case _PC_2_SYMLINKS:
    167         return __2_symlinks(&buf);
    168 
    169 #if 0  /* don't know what to do there, the specs are really weird */
    170     case _PC_ALLOC_SIZE_MIN:
    171     case _PC_REC_INCR_XFER_SIZE:
    172     case _PC_REC_MAX_XFER_SIZE:
    173     case _PC_REC_MIN_XFER_SIZE:
    174     case _PC_REC_XFER_ALIGN:
    175 #endif
    176 
    177     case _PC_SYMLINK_MAX:
    178         return -1;  /* no limit */
    179 
    180     case _PC_CHOWN_RESTRICTED:
    181         return _POSIX_CHOWN_RESTRICTED;
    182 
    183     case _PC_NO_TRUNC:
    184         return _POSIX_NO_TRUNC;
    185 
    186     case _PC_VDISABLE:
    187         return _POSIX_VDISABLE;
    188 
    189     case _PC_ASYNC_IO:
    190         return _POSIX_ASYNC_IO;
    191 
    192     case _PC_PRIO_IO:
    193         return _POSIX_PRIO_IO;
    194 
    195     case _PC_SYNC_IO:
    196         return _POSIX_SYNC_IO;
    197 
    198     default:
    199         errno = EINVAL;
    200         return -1;
    201     }
    202 }
    203 
    204 long fpathconf(int fildes, int name)
    205 {
    206     struct statfs  buf;
    207     int            ret = fstatfs(fildes, &buf);
    208 
    209     if (ret < 0)
    210         return -1;
    211 
    212     switch (name) {
    213     case _PC_FILESIZEBITS:
    214         return __filesizebits(&buf);
    215 
    216     case _PC_LINK_MAX:
    217         return __link_max(&buf);
    218 
    219     case _PC_MAX_CANON:
    220         return MAX_CANON;
    221 
    222     case _PC_MAX_INPUT:
    223         return MAX_INPUT;
    224 
    225     case _PC_NAME_MAX:
    226         return __name_max(&buf);
    227 
    228     case _PC_PATH_MAX:
    229         return PATH_MAX;
    230 
    231     case _PC_PIPE_BUF:
    232         return PIPE_BUF;
    233 
    234     case _PC_2_SYMLINKS:
    235         return __2_symlinks(&buf);
    236 
    237 #if 0  /* don't know what to do there, the specs are really weird */
    238     case _PC_ALLOC_SIZE_MIN:
    239     case _PC_REC_INCR_XFER_SIZE:
    240     case _PC_REC_MAX_XFER_SIZE:
    241     case _PC_REC_MIN_XFER_SIZE:
    242     case _PC_REC_XFER_ALIGN:
    243 #endif
    244 
    245     case _PC_SYMLINK_MAX:
    246         return -1;  /* no limit */
    247 
    248     case _PC_CHOWN_RESTRICTED:
    249         return _POSIX_CHOWN_RESTRICTED;
    250 
    251     case _PC_NO_TRUNC:
    252         return _POSIX_NO_TRUNC;
    253 
    254     case _PC_VDISABLE:
    255         return _POSIX_VDISABLE;
    256 
    257     case _PC_ASYNC_IO:
    258         return _POSIX_ASYNC_IO;
    259 
    260     case _PC_PRIO_IO:
    261         return _POSIX_PRIO_IO;
    262 
    263     case _PC_SYNC_IO:
    264         return _POSIX_SYNC_IO;
    265 
    266     default:
    267         errno = EINVAL;
    268         return -1;
    269     }
    270 }
    271