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 
     29 #include <pathconf.h>
     30 #include <sys/vfs.h>
     31 #include <sys/limits.h>
     32 #include <errno.h>
     33 
     34 /* these may not be defined yet by our headers */
     35 #ifndef _POSIX_VDISABLE
     36 #define _POSIX_VDISABLE  -1
     37 #endif
     38 
     39 #ifndef _POSIX_SYNC_IO
     40 #define _POSIX_SYNC_IO  -1
     41 #endif
     42 
     43 #ifndef _POSIX_PRIO_IO
     44 #define _POSIX_PRIO_IO  -1
     45 #endif
     46 
     47 #ifndef _POSIX_ASYNC_IO
     48 #define _POSIX_ASYNC_IO  -1
     49 #endif
     50 
     51 
     52 static long
     53 __filesizebits( struct statfs*  s )
     54 {
     55 #define   EOL_MAGIC   0x0000U
     56 
     57     /* list of known 64-bit aware filesystems */
     58     static const uint32_t  known64[] = {
     59         EXT2_SUPER_MAGIC,
     60         UFS_MAGIC,
     61         REISERFS_SUPER_MAGIC,
     62         XFS_SUPER_MAGIC,
     63         SMB_SUPER_MAGIC,
     64         UDF_SUPER_MAGIC,
     65         JFS_SUPER_MAGIC,
     66         NTFS_SB_MAGIC,
     67         VXFS_SUPER_MAGIC,
     68         EOL_MAGIC
     69     };
     70     int  nn = 0;
     71 
     72     for (; known64[nn] != EOL_MAGIC; ++nn) {
     73         if (known64[nn] == s->f_type) {
     74             return 64;
     75         }
     76     }
     77     return 32;
     78 }
     79 
     80 
     81 static long
     82 __link_max( struct statfs*  s )
     83 {
     84     // These constant values were taken from kernel headers.
     85     // They're not available in uapi headers.
     86     static const struct { uint32_t  type; int  max; }  knownMax[] =
     87     {
     88         { EXT2_SUPER_MAGIC, 32000 },
     89         { EXT3_SUPER_MAGIC, 32000 },
     90         { MINIX_SUPER_MAGIC, 250 },
     91         { MINIX2_SUPER_MAGIC, 65530 },
     92         { REISERFS_SUPER_MAGIC, 0xffff - 1000 },
     93         { UFS_MAGIC, 32000 },
     94         { EOL_MAGIC, 0 }
     95     };
     96     int   nn = 0;
     97 
     98     for (; knownMax[nn].type != EOL_MAGIC; ++nn) {
     99         if (knownMax[nn].type == s->f_type) {
    100             return knownMax[nn].max;
    101         }
    102     }
    103     return LINK_MAX;
    104 }
    105 
    106 static long
    107 __2_symlinks( struct statfs*  s )
    108 {
    109     /* list of know filesystems that don't support symlinks */
    110     static const uint32_t  knownNoSymlinks[] = {
    111         ADFS_SUPER_MAGIC, BFS_MAGIC, CRAMFS_MAGIC,
    112         EFS_SUPER_MAGIC, MSDOS_SUPER_MAGIC, NTFS_SB_MAGIC,
    113         QNX4_SUPER_MAGIC,
    114         EOL_MAGIC
    115     };
    116     int  nn = 0;
    117 
    118     for (; knownNoSymlinks[nn] != EOL_MAGIC; ++nn) {
    119         if (knownNoSymlinks[nn] == s->f_type) {
    120             return 0;
    121         }
    122     }
    123     return 1;
    124 }
    125 
    126 static long
    127 __name_max( struct statfs*  s )
    128 {
    129     return s->f_namelen;
    130 }
    131 
    132 long
    133 pathconf(const char *path, int name)
    134 {
    135     struct statfs  buf;
    136     int            ret = statfs( path, &buf );
    137 
    138     if (ret < 0)
    139         return -1;
    140 
    141     switch (name) {
    142     case _PC_FILESIZEBITS:
    143         return __filesizebits(&buf);
    144 
    145     case _PC_LINK_MAX:
    146         return __link_max(&buf);
    147 
    148     case _PC_MAX_CANON:
    149         return MAX_CANON;
    150 
    151     case _PC_MAX_INPUT:
    152         return MAX_INPUT;
    153 
    154     case _PC_NAME_MAX:
    155         return __name_max(&buf);
    156 
    157     case _PC_PATH_MAX:
    158         return PATH_MAX;
    159 
    160     case _PC_PIPE_BUF:
    161         return PIPE_BUF;
    162 
    163     case _PC_2_SYMLINKS:
    164         return __2_symlinks(&buf);
    165 
    166 #if 0  /* don't know what to do there, the specs are really weird */
    167     case _PC_ALLOC_SIZE_MIN:
    168     case _PC_REC_INCR_XFER_SIZE:
    169     case _PC_REC_MAX_XFER_SIZE:
    170     case _PC_REC_MIN_XFER_SIZE:
    171     case _PC_REC_XFER_ALIGN:
    172 #endif
    173 
    174     case _PC_SYMLINK_MAX:
    175         return -1;  /* no limit */
    176 
    177     case _PC_CHOWN_RESTRICTED:
    178         return _POSIX_CHOWN_RESTRICTED;
    179 
    180     case _PC_NO_TRUNC:
    181         return _POSIX_NO_TRUNC;
    182 
    183     case _PC_VDISABLE:
    184         return _POSIX_VDISABLE;
    185 
    186     case _PC_ASYNC_IO:
    187         return _POSIX_ASYNC_IO;
    188 
    189     case _PC_PRIO_IO:
    190         return _POSIX_PRIO_IO;
    191 
    192     case _PC_SYNC_IO:
    193         return _POSIX_SYNC_IO;
    194 
    195     default:
    196         errno = EINVAL;
    197         return -1;
    198     }
    199 }
    200 
    201 long fpathconf(int fildes, int name)
    202 {
    203     struct statfs  buf;
    204     int            ret = fstatfs(fildes, &buf);
    205 
    206     if (ret < 0)
    207         return -1;
    208 
    209     switch (name) {
    210     case _PC_FILESIZEBITS:
    211         return __filesizebits(&buf);
    212 
    213     case _PC_LINK_MAX:
    214         return __link_max(&buf);
    215 
    216     case _PC_MAX_CANON:
    217         return MAX_CANON;
    218 
    219     case _PC_MAX_INPUT:
    220         return MAX_INPUT;
    221 
    222     case _PC_NAME_MAX:
    223         return __name_max(&buf);
    224 
    225     case _PC_PATH_MAX:
    226         return PATH_MAX;
    227 
    228     case _PC_PIPE_BUF:
    229         return PIPE_BUF;
    230 
    231     case _PC_2_SYMLINKS:
    232         return __2_symlinks(&buf);
    233 
    234 #if 0  /* don't know what to do there, the specs are really weird */
    235     case _PC_ALLOC_SIZE_MIN:
    236     case _PC_REC_INCR_XFER_SIZE:
    237     case _PC_REC_MAX_XFER_SIZE:
    238     case _PC_REC_MIN_XFER_SIZE:
    239     case _PC_REC_XFER_ALIGN:
    240 #endif
    241 
    242     case _PC_SYMLINK_MAX:
    243         return -1;  /* no limit */
    244 
    245     case _PC_CHOWN_RESTRICTED:
    246         return _POSIX_CHOWN_RESTRICTED;
    247 
    248     case _PC_NO_TRUNC:
    249         return _POSIX_NO_TRUNC;
    250 
    251     case _PC_VDISABLE:
    252         return _POSIX_VDISABLE;
    253 
    254     case _PC_ASYNC_IO:
    255         return _POSIX_ASYNC_IO;
    256 
    257     case _PC_PRIO_IO:
    258         return _POSIX_PRIO_IO;
    259 
    260     case _PC_SYNC_IO:
    261         return _POSIX_SYNC_IO;
    262 
    263     default:
    264         errno = EINVAL;
    265         return -1;
    266     }
    267 }
    268