diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-09-17 00:49:19 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-09-17 00:49:19 +0000 |
commit | d0501a245c7f6c8bf399594d9b331d915580d36f (patch) | |
tree | 9b9ca38e5ae1663919fa0071b35ebb9db73da17d /sysdeps/unix/sysv/linux/internal_statvfs.c | |
parent | e07bb02a4f9e7d98f79f428a661c5b982286869d (diff) | |
download | glibc-d0501a245c7f6c8bf399594d9b331d915580d36f.tar glibc-d0501a245c7f6c8bf399594d9b331d915580d36f.tar.gz glibc-d0501a245c7f6c8bf399594d9b331d915580d36f.tar.bz2 glibc-d0501a245c7f6c8bf399594d9b331d915580d36f.zip |
Update.
2003-09-16 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/sysv/linux/Dist: Remove internal_statvfs.c.
* sysdeps/unix/sysv/linux/Makefile [subdir=io] (sysdep_routines):
Add internal_statvfs.
* sysdeps/unix/sysv/linux/fstatvfs.c: Call __internal_statvfs
instead of including "internal_statvfs.c".
* sysdeps/unix/sysv/linux/statvfs.c: Likewise.
* sysdeps/unix/sysv/linux/internal_statvfs.c: Make it a real function.
Add code to avoid the stat calls on all the reported mount points
when we can determine mismatch in advance.
* sysdeps/unix/sysv/linux/linux_fsinfo.h: Add AUTOFS_SUPER_MAGIC and
USBDEVFS_SUPER_MAGIC.
2003-09-16 Jakub Jelinek <jakub@redhat.com>
* posix/Versions (sched_getaffinity, sched_setaffinity): Change
from GLIBC_2.3.2 to GLIBC_2.3.3 symbol version.
2003-09-16 Bruno Haible <bruno@clisp.org>
* intl/tst-gettext2.sh: Set GCONV_PATH and LOCPATH only after
invoking msgfmt, not before.
Diffstat (limited to 'sysdeps/unix/sysv/linux/internal_statvfs.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/internal_statvfs.c | 114 |
1 files changed, 98 insertions, 16 deletions
diff --git a/sysdeps/unix/sysv/linux/internal_statvfs.c b/sysdeps/unix/sysv/linux/internal_statvfs.c index 9317cef90d..172113d496 100644 --- a/sysdeps/unix/sysv/linux/internal_statvfs.c +++ b/sysdeps/unix/sysv/linux/internal_statvfs.c @@ -17,29 +17,46 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <errno.h> +#include <mntent.h> +#include <paths.h> +#include <stdbool.h> +#include <stdio_ext.h> +#include <string.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/statfs.h> +#include <sys/statvfs.h> +#include "linux_fsinfo.h" + + +void +__internal_statvfs (const char *name, struct statvfs *buf, + struct statfs *fsbuf, struct stat64 *st) +{ /* Now fill in the fields we have information for. */ - buf->f_bsize = fsbuf.f_bsize; + buf->f_bsize = fsbuf->f_bsize; /* Linux has the f_frsize size only in later version of the kernel. If the value is not filled in use f_bsize. */ - buf->f_frsize = fsbuf.f_frsize ?: fsbuf.f_bsize; - buf->f_blocks = fsbuf.f_blocks; - buf->f_bfree = fsbuf.f_bfree; - buf->f_bavail = fsbuf.f_bavail; - buf->f_files = fsbuf.f_files; - buf->f_ffree = fsbuf.f_ffree; - if (sizeof (buf->f_fsid) == sizeof (fsbuf.f_fsid)) - buf->f_fsid = (fsbuf.f_fsid.__val[0] - | ((unsigned long int) fsbuf.f_fsid.__val[1] + buf->f_frsize = fsbuf->f_frsize ?: fsbuf->f_bsize; + buf->f_blocks = fsbuf->f_blocks; + buf->f_bfree = fsbuf->f_bfree; + buf->f_bavail = fsbuf->f_bavail; + buf->f_files = fsbuf->f_files; + buf->f_ffree = fsbuf->f_ffree; + if (sizeof (buf->f_fsid) == sizeof (fsbuf->f_fsid)) + buf->f_fsid = (fsbuf->f_fsid.__val[0] + | ((unsigned long int) fsbuf->f_fsid.__val[1] << (8 * (sizeof (buf->f_fsid) - - sizeof (fsbuf.f_fsid.__val[0]))))); + - sizeof (fsbuf->f_fsid.__val[0]))))); else /* We cannot help here. The statvfs element is not large enough to contain both words of the statfs f_fsid field. */ - buf->f_fsid = fsbuf.f_fsid.__val[0]; + buf->f_fsid = fsbuf->f_fsid.__val[0]; #ifdef _STATVFSBUF_F_UNUSED buf->__f_unused = 0; #endif - buf->f_namemax = fsbuf.f_namelen; + buf->f_namemax = fsbuf->f_namelen; memset (buf->__f_spare, '\0', 6 * sizeof (int)); /* What remains to do is to fill the fields f_favail and f_flag. */ @@ -52,10 +69,40 @@ file. The way we can test for matching filesystem is using the device number. */ buf->f_flag = 0; - if (STAT (&st) >= 0) + if (st != NULL) { struct mntent mntbuf; FILE *mtab; + const char *fsname = NULL; + const char *fsname2 = NULL; + bool success = false; + + /* Map the filesystem type we got from the statfs call to a string. */ + switch (fsbuf->f_type) + { + case EXT2_SUPER_MAGIC: + fsname = "ext3"; + fsname2 = "ext2"; + break; + case DEVPTS_SUPER_MAGIC: + fsname= "devpts"; + break; + case SHMFS_SUPER_MAGIC: + fsname = "tmpfs"; + break; + case PROC_SUPER_MAGIC: + fsname = "proc"; + break; + case USBDEVFS_SUPER_MAGIC: + fsname = "usbdevfs"; + break; + case AUTOFS_SUPER_MAGIC: + fsname = "autofs"; + break; + case NFS_SUPER_MAGIC: + fsname = "nfs"; + break; + } mtab = __setmntent ("/proc/mounts", "r"); if (mtab == NULL) @@ -68,13 +115,25 @@ /* No locking needed. */ (void) __fsetlocking (mtab, FSETLOCKING_BYCALLER); + again: while (__getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf))) { - struct stat64 fsst; + /* In a first round we look for a given mount point, if + we have a name. */ + if (name != NULL && strcmp (name, mntbuf.mnt_dir) != 0) + continue; + /* We need to look at the entry only if the filesystem + name matches. If we have a filesystem name. */ + else if (fsname != NULL + && strcmp (fsname, mntbuf.mnt_type) != 0 + && (fsname2 == NULL + || strcmp (fsname2, mntbuf.mnt_type) != 0)) + continue; /* Find out about the device the current entry is for. */ + struct stat64 fsst; if (stat64 (mntbuf.mnt_dir, &fsst) >= 0 - && st.st_dev == fsst.st_dev) + && st->st_dev == fsst.st_dev) { /* Bingo, we found the entry for the device FD is on. Now interpret the option string. */ @@ -100,11 +159,34 @@ buf->f_flag |= ST_NODIRATIME; /* We can stop looking for more entries. */ + success = true; break; } } + /* Maybe the kernel names for the filesystems changed or the + statvfs call got a name which was not the mount point. + Check again, this time without checking for name matches + first. */ + if (! success) + { + if (name != NULL) + /* Try without a mount point name. */ + name = NULL; + else if (fsname != NULL) + /* Try without a filesystem name. */ + fsname = fsname2 = NULL; + + /* It is not strictly allowed to use rewind here. But + this code is part of the implementation so it is + acceptable. */ + rewind (mtab); + + goto again; + } /* Close the file. */ __endmntent (mtab); + } } +} |