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