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