Remove PIPE_BUF Linux-specific code
[platform/upstream/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
43   switch (name)
44     {
45     case _PC_LINK_MAX:
46       return __statfs_link_max (__statfs (file, &fsbuf), &fsbuf, file, -1);
47
48     case _PC_FILESIZEBITS:
49       return __statfs_filesize_max (__statfs (file, &fsbuf), &fsbuf);
50
51     case _PC_2_SYMLINKS:
52       return __statfs_symlinks (__statfs (file, &fsbuf), &fsbuf);
53
54     case _PC_CHOWN_RESTRICTED:
55       return __statfs_chown_restricted (__statfs (file, &fsbuf), &fsbuf);
56
57     default:
58       return posix_pathconf (file, name);
59     }
60 }
61
62
63 static long int
64 distinguish_extX (const struct statfs *fsbuf, const char *file, int fd)
65 {
66   char buf[64];
67   char path[PATH_MAX];
68   struct stat64 st;
69
70   if ((file == NULL ? fstat64 (fd, &st) : stat64 (file, &st)) != 0)
71     /* Strange.  The statfd call worked, but stat fails.  Default to
72        the more pessimistic value.  */
73     return EXT2_LINK_MAX;
74
75   __snprintf (buf, sizeof (buf), "/sys/dev/block/%u:%u",
76               gnu_dev_major (st.st_dev), gnu_dev_minor (st.st_dev));
77
78   ssize_t n = __readlink (buf, path, sizeof (path));
79   if (n != -1 && n < sizeof (path))
80     {
81       path[n] = '\0';
82       char *base = strdupa (basename (path));
83       __snprintf (path, sizeof (path), "/sys/fs/ext4/%s", base);
84
85       return __access (path, F_OK) == 0 ? EXT4_LINK_MAX : EXT2_LINK_MAX;
86     }
87
88   /* XXX Is there a better way to distinguish ext2/3 from ext4 than
89      iterating over the mounted filesystems and compare the device
90      numbers?  */
91   FILE *mtab = __setmntent ("/proc/mounts", "r");
92   if (mtab == NULL)
93     mtab = __setmntent (_PATH_MOUNTED, "r");
94
95   /* By default be conservative.  */
96   long int result = EXT2_LINK_MAX;
97   if (mtab != NULL)
98     {
99       struct mntent mntbuf;
100       char tmpbuf[1024];
101
102       /* No locking needed.  */
103       (void) __fsetlocking (mtab, FSETLOCKING_BYCALLER);
104
105       while (__getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf)))
106         {
107           if (strcmp (mntbuf.mnt_type, "ext2") != 0
108               && strcmp (mntbuf.mnt_type, "ext3") != 0
109               && strcmp (mntbuf.mnt_type, "ext4") != 0)
110             continue;
111
112           struct stat64 fsst;
113           if (stat64 (mntbuf.mnt_dir, &fsst) >= 0
114               && st.st_dev == fsst.st_dev)
115             {
116               if (strcmp (mntbuf.mnt_type, "ext4") == 0)
117                 result = EXT4_LINK_MAX;
118               break;
119             }
120         }
121
122       /* Close the file.  */
123       __endmntent (mtab);
124     }
125
126   return result;
127 }
128
129
130 /* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
131 long int
132 __statfs_link_max (int result, const struct statfs *fsbuf, const char *file,
133                    int fd)
134 {
135   if (result < 0)
136     {
137       if (errno == ENOSYS)
138         /* Not possible, return the default value.  */
139         return LINUX_LINK_MAX;
140
141       /* Some error occured.  */
142       return -1;
143     }
144
145   switch (fsbuf->f_type)
146     {
147     case EXT2_SUPER_MAGIC:
148       /* Unfortunately the kernel does not return a different magic number
149          for ext4.  This would be necessary to easily detect etx4 since it
150          has a different LINK_MAX value.  Therefore we have to find it out
151          the hard way.  */
152       return distinguish_extX (fsbuf, file, fd);
153
154     case F2FS_SUPER_MAGIC:
155       return F2FS_LINK_MAX;
156
157     case MINIX_SUPER_MAGIC:
158     case MINIX_SUPER_MAGIC2:
159       return MINIX_LINK_MAX;
160
161     case MINIX2_SUPER_MAGIC:
162     case MINIX2_SUPER_MAGIC2:
163       return MINIX2_LINK_MAX;
164
165     case XENIX_SUPER_MAGIC:
166       return XENIX_LINK_MAX;
167
168     case SYSV4_SUPER_MAGIC:
169     case SYSV2_SUPER_MAGIC:
170       return SYSV_LINK_MAX;
171
172     case COH_SUPER_MAGIC:
173       return COH_LINK_MAX;
174
175     case UFS_MAGIC:
176     case UFS_CIGAM:
177       return UFS_LINK_MAX;
178
179     case REISERFS_SUPER_MAGIC:
180       return REISERFS_LINK_MAX;
181
182     case XFS_SUPER_MAGIC:
183       return XFS_LINK_MAX;
184
185     case LUSTRE_SUPER_MAGIC:
186       return LUSTRE_LINK_MAX;
187
188     default:
189       return LINUX_LINK_MAX;
190     }
191 }
192
193
194 /* Used like: return statfs_filesize_max (__statfs (name, &buf), &buf); */
195 long int
196 __statfs_filesize_max (int result, const struct statfs *fsbuf)
197 {
198   if (result < 0)
199     {
200       if (errno == ENOSYS)
201         /* Not possible, return the default value.  */
202         return 32;
203
204       /* Some error occured.  */
205       return -1;
206     }
207
208   switch (fsbuf->f_type)
209     {
210     case F2FS_SUPER_MAGIC:
211       return 256;
212
213     case BTRFS_SUPER_MAGIC:
214       return 255;
215
216     case EXT2_SUPER_MAGIC:
217     case UFS_MAGIC:
218     case UFS_CIGAM:
219     case REISERFS_SUPER_MAGIC:
220     case XFS_SUPER_MAGIC:
221     case SMB_SUPER_MAGIC:
222     case NTFS_SUPER_MAGIC:
223     case UDF_SUPER_MAGIC:
224     case JFS_SUPER_MAGIC:
225     case VXFS_SUPER_MAGIC:
226     case CGROUP_SUPER_MAGIC:
227     case LUSTRE_SUPER_MAGIC:
228       return 64;
229
230     case MSDOS_SUPER_MAGIC:
231     case JFFS_SUPER_MAGIC:
232     case JFFS2_SUPER_MAGIC:
233     case NCP_SUPER_MAGIC:
234     case ROMFS_SUPER_MAGIC:
235       return 32;
236
237     default:
238       return 32;
239     }
240 }
241
242
243 /* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
244 long int
245 __statfs_symlinks (int result, const struct statfs *fsbuf)
246 {
247   if (result < 0)
248     {
249       if (errno == ENOSYS)
250         /* Not possible, return the default value.  */
251         return 1;
252
253       /* Some error occured.  */
254       return -1;
255     }
256
257   switch (fsbuf->f_type)
258     {
259     case ADFS_SUPER_MAGIC:
260     case BFS_MAGIC:
261     case CRAMFS_MAGIC:
262     case DEVPTS_SUPER_MAGIC:
263     case EFS_SUPER_MAGIC:
264     case EFS_MAGIC:
265     case MSDOS_SUPER_MAGIC:
266     case NTFS_SUPER_MAGIC:
267     case QNX4_SUPER_MAGIC:
268     case ROMFS_SUPER_MAGIC:
269       /* No symlink support.  */
270       return 0;
271
272     default:
273       return 1;
274     }
275 }
276
277
278 /* Used like: return __statfs_chown_restricted (__statfs (name, &buf), &buf);*/
279 long int
280 __statfs_chown_restricted (int result, const struct statfs *fsbuf)
281 {
282   if (result < 0)
283     {
284       if (errno == ENOSYS)
285         /* Not possible, return the default value.  */
286         return 1;
287
288       /* Some error occured.  */
289       return -1;
290     }
291
292   int fd;
293   long int retval = 1;
294   switch (fsbuf->f_type)
295     {
296     case XFS_SUPER_MAGIC:
297       /* Read the value from /proc/sys/fs/xfs/restrict_chown.  If we cannot
298          read it default to assume the restriction is in place.  */
299       fd = open_not_cancel_2 ("/proc/sys/fs/xfs/restrict_chown", O_RDONLY);
300       if (fd != -1)
301         {
302           char buf[2];
303           if (TEMP_FAILURE_RETRY (read_not_cancel (fd, buf, 2)) == 2
304               && buf[0] >= '0' && buf[0] <= '1')
305             retval = buf[0] - '0';
306
307           close_not_cancel_no_status (fd);
308         }
309       break;
310
311     default:
312       break;
313     }
314
315   return retval;
316 }