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