]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/pathconf.c
Update copyright notices with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / pathconf.c
1 /* Get file-specific information about a file. Linux version.
2 Copyright (C) 1991-2013 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #include <errno.h>
20 #include <mntent.h>
21 #include <stdio_ext.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/sysmacros.h>
25
26 #include "pathconf.h"
27 #include "linux_fsinfo.h"
28 #include <not-cancel.h>
29
30 static long int posix_pathconf (const char *file, int name);
31
32 /* Define this first, so it can be inlined. */
33 #define __pathconf static posix_pathconf
34 #include <sysdeps/posix/pathconf.c>
35
36
37 /* Get file-specific information about FILE. */
38 long int
39 __pathconf (const char *file, int name)
40 {
41 struct statfs fsbuf;
42 int fd;
43 int flags;
44
45 switch (name)
46 {
47 case _PC_LINK_MAX:
48 return __statfs_link_max (__statfs (file, &fsbuf), &fsbuf, file, -1);
49
50 case _PC_FILESIZEBITS:
51 return __statfs_filesize_max (__statfs (file, &fsbuf), &fsbuf);
52
53 case _PC_2_SYMLINKS:
54 return __statfs_symlinks (__statfs (file, &fsbuf), &fsbuf);
55
56 case _PC_CHOWN_RESTRICTED:
57 return __statfs_chown_restricted (__statfs (file, &fsbuf), &fsbuf);
58
59 case _PC_PIPE_BUF:
60 flags = O_RDONLY|O_NONBLOCK|O_NOCTTY;
61 #ifdef O_CLOEXEC
62 flags |= O_CLOEXEC;
63 #endif
64 fd = open_not_cancel_2 (file, flags);
65 if (fd >= 0)
66 {
67 long int r = __fcntl (fd, F_GETPIPE_SZ);
68 close_not_cancel_no_status (fd);
69 if (r > 0)
70 return r;
71 }
72 /* FALLTHROUGH */
73
74 default:
75 return posix_pathconf (file, name);
76 }
77 }
78
79
80 static long int
81 distinguish_extX (const struct statfs *fsbuf, const char *file, int fd)
82 {
83 char buf[64];
84 char path[PATH_MAX];
85 struct stat64 st;
86
87 if ((file == NULL ? fstat64 (fd, &st) : stat64 (file, &st)) != 0)
88 /* Strange. The statfd call worked, but stat fails. Default to
89 the more pessimistic value. */
90 return EXT2_LINK_MAX;
91
92 __snprintf (buf, sizeof (buf), "/sys/dev/block/%u:%u",
93 gnu_dev_major (st.st_dev), gnu_dev_minor (st.st_dev));
94
95 ssize_t n = __readlink (buf, path, sizeof (path));
96 if (n != -1 && n < sizeof (path))
97 {
98 path[n] = '\0';
99 char *base = strdupa (basename (path));
100 __snprintf (path, sizeof (path), "/sys/fs/ext4/%s", base);
101
102 return __access (path, F_OK) == 0 ? EXT4_LINK_MAX : EXT2_LINK_MAX;
103 }
104
105 /* XXX Is there a better way to distinguish ext2/3 from ext4 than
106 iterating over the mounted filesystems and compare the device
107 numbers? */
108 FILE *mtab = __setmntent ("/proc/mounts", "r");
109 if (mtab == NULL)
110 mtab = __setmntent (_PATH_MOUNTED, "r");
111
112 /* By default be conservative. */
113 long int result = EXT2_LINK_MAX;
114 if (mtab != NULL)
115 {
116 struct mntent mntbuf;
117 char tmpbuf[1024];
118
119 /* No locking needed. */
120 (void) __fsetlocking (mtab, FSETLOCKING_BYCALLER);
121
122 while (__getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf)))
123 {
124 if (strcmp (mntbuf.mnt_type, "ext2") != 0
125 && strcmp (mntbuf.mnt_type, "ext3") != 0
126 && strcmp (mntbuf.mnt_type, "ext4") != 0)
127 continue;
128
129 struct stat64 fsst;
130 if (stat64 (mntbuf.mnt_dir, &fsst) >= 0
131 && st.st_dev == fsst.st_dev)
132 {
133 if (strcmp (mntbuf.mnt_type, "ext4") == 0)
134 result = EXT4_LINK_MAX;
135 break;
136 }
137 }
138
139 /* Close the file. */
140 __endmntent (mtab);
141 }
142
143 return result;
144 }
145
146
147 /* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
148 long int
149 __statfs_link_max (int result, const struct statfs *fsbuf, const char *file,
150 int fd)
151 {
152 if (result < 0)
153 {
154 if (errno == ENOSYS)
155 /* Not possible, return the default value. */
156 return LINUX_LINK_MAX;
157
158 /* Some error occured. */
159 return -1;
160 }
161
162 switch (fsbuf->f_type)
163 {
164 case EXT2_SUPER_MAGIC:
165 /* Unfortunately the kernel does not return a different magic number
166 for ext4. This would be necessary to easily detect etx4 since it
167 has a different LINK_MAX value. Therefore we have to find it out
168 the hard way. */
169 return distinguish_extX (fsbuf, file, fd);
170
171 case MINIX_SUPER_MAGIC:
172 case MINIX_SUPER_MAGIC2:
173 return MINIX_LINK_MAX;
174
175 case MINIX2_SUPER_MAGIC:
176 case MINIX2_SUPER_MAGIC2:
177 return MINIX2_LINK_MAX;
178
179 case XENIX_SUPER_MAGIC:
180 return XENIX_LINK_MAX;
181
182 case SYSV4_SUPER_MAGIC:
183 case SYSV2_SUPER_MAGIC:
184 return SYSV_LINK_MAX;
185
186 case COH_SUPER_MAGIC:
187 return COH_LINK_MAX;
188
189 case UFS_MAGIC:
190 case UFS_CIGAM:
191 return UFS_LINK_MAX;
192
193 case REISERFS_SUPER_MAGIC:
194 return REISERFS_LINK_MAX;
195
196 case XFS_SUPER_MAGIC:
197 return XFS_LINK_MAX;
198
199 case LUSTRE_SUPER_MAGIC:
200 return LUSTRE_LINK_MAX;
201
202 default:
203 return LINUX_LINK_MAX;
204 }
205 }
206
207
208 /* Used like: return statfs_filesize_max (__statfs (name, &buf), &buf); */
209 long int
210 __statfs_filesize_max (int result, const struct statfs *fsbuf)
211 {
212 if (result < 0)
213 {
214 if (errno == ENOSYS)
215 /* Not possible, return the default value. */
216 return 32;
217
218 /* Some error occured. */
219 return -1;
220 }
221
222 switch (fsbuf->f_type)
223 {
224 case BTRFS_SUPER_MAGIC:
225 return 255;
226
227 case EXT2_SUPER_MAGIC:
228 case UFS_MAGIC:
229 case UFS_CIGAM:
230 case REISERFS_SUPER_MAGIC:
231 case XFS_SUPER_MAGIC:
232 case SMB_SUPER_MAGIC:
233 case NTFS_SUPER_MAGIC:
234 case UDF_SUPER_MAGIC:
235 case JFS_SUPER_MAGIC:
236 case VXFS_SUPER_MAGIC:
237 case CGROUP_SUPER_MAGIC:
238 case LUSTRE_SUPER_MAGIC:
239 return 64;
240
241 case MSDOS_SUPER_MAGIC:
242 case JFFS_SUPER_MAGIC:
243 case JFFS2_SUPER_MAGIC:
244 case NCP_SUPER_MAGIC:
245 case ROMFS_SUPER_MAGIC:
246 return 32;
247
248 default:
249 return 32;
250 }
251 }
252
253
254 /* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
255 long int
256 __statfs_symlinks (int result, const struct statfs *fsbuf)
257 {
258 if (result < 0)
259 {
260 if (errno == ENOSYS)
261 /* Not possible, return the default value. */
262 return 1;
263
264 /* Some error occured. */
265 return -1;
266 }
267
268 switch (fsbuf->f_type)
269 {
270 case ADFS_SUPER_MAGIC:
271 case BFS_MAGIC:
272 case CRAMFS_MAGIC:
273 case DEVPTS_SUPER_MAGIC:
274 case EFS_SUPER_MAGIC:
275 case EFS_MAGIC:
276 case MSDOS_SUPER_MAGIC:
277 case NTFS_SUPER_MAGIC:
278 case QNX4_SUPER_MAGIC:
279 case ROMFS_SUPER_MAGIC:
280 /* No symlink support. */
281 return 0;
282
283 default:
284 return 1;
285 }
286 }
287
288
289 /* Used like: return __statfs_chown_restricted (__statfs (name, &buf), &buf);*/
290 long int
291 __statfs_chown_restricted (int result, const struct statfs *fsbuf)
292 {
293 if (result < 0)
294 {
295 if (errno == ENOSYS)
296 /* Not possible, return the default value. */
297 return 1;
298
299 /* Some error occured. */
300 return -1;
301 }
302
303 int fd;
304 long int retval = 1;
305 switch (fsbuf->f_type)
306 {
307 case XFS_SUPER_MAGIC:
308 /* Read the value from /proc/sys/fs/xfs/restrict_chown. If we cannot
309 read it default to assume the restriction is in place. */
310 fd = open_not_cancel_2 ("/proc/sys/fs/xfs/restrict_chown", O_RDONLY);
311 if (fd != -1)
312 {
313 char buf[2];
314 if (TEMP_FAILURE_RETRY (read_not_cancel (fd, buf, 2)) == 2
315 && buf[0] >= '0' && buf[0] <= '1')
316 retval = buf[0] - '0';
317
318 close_not_cancel_no_status (fd);
319 }
320 break;
321
322 default:
323 break;
324 }
325
326 return retval;
327 }