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
__filesizebits(struct statfs * s)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
__link_max(struct statfs * s)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
__2_symlinks(struct statfs * s)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
__name_max(struct statfs * s)133 __name_max( struct statfs* s )
134 {
135 return s->f_namelen;
136 }
137
138 long
pathconf(const char * path,int name)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
fpathconf(int fildes,int name)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