Handle nodiratime option.
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / fstatvfs.c
1 /* Copyright (C) 1998 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    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    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <errno.h>
21 #include <mntent.h>
22 #include <paths.h>
23 #include <string.h>
24 #include <sys/mount.h>
25 #include <sys/stat.h>
26 #include <sys/statfs.h>
27 #include <sys/statvfs.h>
28
29 /* These definitions come from the kernel headers.  But we cannot
30    include the headers here because of type clashes.  If new
31    filesystem types will become available we have to add the
32    appropriate definitions here.*/
33 #define ADFS_SUPER_MAGIC        0xadf5
34 #define AFFS_SUPER_MAGIC        0xadff
35 #define CODA_SUPER_MAGIC        0x73757245
36 #define EXT2_SUPER_MAGIC        0xef53
37 #define HPFS_SUPER_MAGIC        0xf995e849
38 #define ISOFS_SUPER_MAGIC       0x9660
39 #define MINIX_SUPER_MAGIC       0x137f
40 #define MINIX_SUPER_MAGIC2      0x138F
41 #define MINIX2_SUPER_MAGIC      0x2468
42 #define MINIX2_SUPER_MAGIC2     0x2478
43 #define MSDOS_SUPER_MAGIC       0x4d44
44 #define NCP_SUPER_MAGIC         0x564c
45 #define NFS_SUPER_MAGIC         0x6969
46 #define PROC_SUPER_MAGIC        0x9fa0
47 #define SMB_SUPER_MAGIC         0x517b
48 #define XENIX_SUPER_MAGIC       0x012ff7b4
49 #define SYSV4_SUPER_MAGIC       0x012ff7b5
50 #define SYSV2_SUPER_MAGIC       0x012ff7b6
51 #define COH_SUPER_MAGIC         0x012ff7b7
52
53
54 int
55 fstatvfs (int fd, struct statvfs *buf)
56 {
57   struct statfs fsbuf;
58   struct stat st;
59
60   /* Get as much information as possible from the system.  */
61   if (__fstatfs (fd, &fsbuf) < 0)
62     return -1;
63
64   /* Now fill in the fields we have information for.  */
65   buf->f_bsize = fsbuf.f_bsize;
66   buf->f_blocks = fsbuf.f_blocks;
67   buf->f_bfree = fsbuf.f_bfree;
68   buf->f_bavail = fsbuf.f_bavail;
69   buf->f_files = fsbuf.f_files;
70   buf->f_ffree = fsbuf.f_ffree;
71   buf->f_fsid = fsbuf.f_fsid;
72   buf->f_namemax = fsbuf.f_namelen;
73   memset (buf->f_spare, '\0', 6 * sizeof (int));
74
75   /* What remains to do is to fill the fields f_frsize, f_favail,
76      and f_flag.  */
77   switch (fsbuf.f_type)
78     {
79     case EXT2_SUPER_MAGIC:
80       /* This is not really correct since the fragment size can vary.  */
81       buf->f_frsize = 1024;
82       break;
83
84     case ADFS_SUPER_MAGIC:
85     case AFFS_SUPER_MAGIC:
86     case CODA_SUPER_MAGIC:
87     case HPFS_SUPER_MAGIC:
88     case ISOFS_SUPER_MAGIC:
89     case MINIX_SUPER_MAGIC:
90     case MINIX_SUPER_MAGIC2:
91     case MINIX2_SUPER_MAGIC:
92     case MINIX2_SUPER_MAGIC2:
93     case MSDOS_SUPER_MAGIC:
94     case NCP_SUPER_MAGIC:
95     case NFS_SUPER_MAGIC:
96     case PROC_SUPER_MAGIC:
97     case SMB_SUPER_MAGIC:
98     case XENIX_SUPER_MAGIC:
99     case SYSV4_SUPER_MAGIC:
100     case SYSV2_SUPER_MAGIC:
101     case COH_SUPER_MAGIC:
102     default:
103       /* I hope it's safe to assume no fragmentation.  */
104       buf->f_frsize = buf->f_bsize;
105       break;
106     }
107
108   /* XXX I have no idea how to compute f_favail.  Any idea???  */
109   buf->f_favail = buf->f_ffree;
110
111   /* Determining the flags is tricky.  We have to read /proc/mounts or
112      the /etc/mtab file and search for the entry which matches the given
113      file.  The way we can test for matching filesystem is using the
114      device number.  */
115   buf->f_flag = 0;
116   if (fstat (fd, &st) >= 0)
117     {
118       int save_errno = errno;
119       struct mntent mntbuf;
120       FILE *mtab;
121
122       mtab = __setmntent ("/proc/mounts", "r");
123       if (mtab == NULL)
124         mtab = __setmntent (_PATH_MOUNTED, "r");
125
126       if (mtab != NULL)
127         {
128           char tmpbuf[1024];
129
130           while (__getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf)))
131             {
132               struct stat fsst;
133
134               /* Find out about the device the current entry is for.  */
135               if (stat (mntbuf.mnt_dir, &fsst) >= 0
136                   && st.st_dev == fsst.st_dev)
137                 {
138                   /* Bingo, we found the entry for the device FD is on.
139                      Now interpret the option string.  */
140                   char *cp = mntbuf.mnt_opts;
141                   char *opt;
142
143                   while ((opt = strsep (&cp, ",")) != NULL)
144                     if (strcmp (opt, "ro") == 0)
145                       buf->f_flag |= ST_RDONLY;
146                     else if (strcmp (opt, "nosuid") == 0)
147                       buf->f_flag |= ST_NOSUID;
148                     else if (strcmp (opt, "noexec") == 0)
149                       buf->f_flag |= ST_NOEXEC;
150                     else if (strcmp (opt, "nodev") == 0)
151                       buf->f_flag |= ST_NODEV;
152                     else if (strcmp (opt, "sync") == 0)
153                       buf->f_flag |= ST_SYNCHRONOUS;
154                     else if (strcmp (opt, "mand") == 0)
155                       buf->f_flag |= ST_MANDLOCK;
156                     else if (strcmp (opt, "noatime") == 0)
157                       buf->f_flag |= ST_NOATIME;
158                     else if (strcmp (opt, "nodiratime") == 0)
159                       buf->f_flag |= ST_NODIRATIME;
160
161                   /* We can stop looking for more entries.  */
162                   break;
163                 }
164             }
165
166           /* Close the file.  */
167           __endmntent (mtab);
168         }
169
170       __set_errno (save_errno);
171     }
172
173   /* We signal success if the statfs call succeeded.  */
174   return 0;
175 }