about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/unix/sysv/linux/Dist1
-rw-r--r--sysdeps/unix/sysv/linux/Makefile2
-rw-r--r--sysdeps/unix/sysv/linux/fstatvfs.c16
-rw-r--r--sysdeps/unix/sysv/linux/internal_statvfs.c114
-rw-r--r--sysdeps/unix/sysv/linux/linux_fsinfo.h6
-rw-r--r--sysdeps/unix/sysv/linux/statvfs.c17
6 files changed, 120 insertions, 36 deletions
diff --git a/sysdeps/unix/sysv/linux/Dist b/sysdeps/unix/sysv/linux/Dist
index 1cd482c1ff..219b3d80f9 100644
--- a/sysdeps/unix/sysv/linux/Dist
+++ b/sysdeps/unix/sysv/linux/Dist
@@ -11,7 +11,6 @@ kernel-features.h
 kernel_sigaction.h
 kernel_stat.h
 kernel_termios.h
-internal_statvfs.c
 ldd-rewrite.sed
 lddlibc4.c
 linux_fsinfo.h
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 2d781d2f74..c67376d1f8 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -137,7 +137,7 @@ CFLAGS-ypclnt.c = -DUSE_BINDINGDIR=1
 endif
 
 ifeq ($(subdir),io)
-sysdep_routines += xstatconv
+sysdep_routines += xstatconv internal_statvfs
 endif
 
 ifeq ($(subdir),elf)
diff --git a/sysdeps/unix/sysv/linux/fstatvfs.c b/sysdeps/unix/sysv/linux/fstatvfs.c
index 0bfce16309..0dd56c1046 100644
--- a/sysdeps/unix/sysv/linux/fstatvfs.c
+++ b/sysdeps/unix/sysv/linux/fstatvfs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -17,16 +17,14 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <errno.h>
-#include <mntent.h>
-#include <paths.h>
-#include <stdio_ext.h>
-#include <string.h>
-#include <sys/mount.h>
+#include <stddef.h>
 #include <sys/stat.h>
 #include <sys/statfs.h>
 #include <sys/statvfs.h>
 
+extern void __internal_statvfs (const char *name, struct statvfs *buf,
+				struct statfs *fsbuf, struct stat64 *st);
+
 
 int
 fstatvfs (int fd, struct statvfs *buf)
@@ -38,8 +36,8 @@ fstatvfs (int fd, struct statvfs *buf)
   if (__fstatfs (fd, &fsbuf) < 0)
     return -1;
 
-#define STAT(st) fstat64 (fd, st)
-#include "internal_statvfs.c"
+  /* Convert the result.  */
+  __internal_statvfs (NULL, buf, &fsbuf, fstat64 (fd, &st) == -1 ? NULL : &st);
 
   /* We signal success if the statfs call succeeded.  */
   return 0;
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);
+
 	}
     }
+}
diff --git a/sysdeps/unix/sysv/linux/linux_fsinfo.h b/sysdeps/unix/sysv/linux/linux_fsinfo.h
index 41dbbde55c..13c3856266 100644
--- a/sysdeps/unix/sysv/linux/linux_fsinfo.h
+++ b/sysdeps/unix/sysv/linux/linux_fsinfo.h
@@ -31,6 +31,9 @@
 /* Constants that identify the `affs' filesystem.  */
 #define AFFS_SUPER_MAGIC	0xadff
 
+/* Constants that identify the `autofs' filesystem.  */
+#define AUTOFS_SUPER_MAGIC	0x187
+
 /* Constants that identify the `bfs' filesystem.  */
 #define BFS_MAGIC		0x1BADFACE
 
@@ -94,6 +97,9 @@
 /* Constants that identify the `proc' filesystem.  */
 #define PROC_SUPER_MAGIC	0x9fa0
 
+/* Constant that identifies the `usbdevfs' filesystem.  */
+#define USBDEVFS_SUPER_MAGIC	0x9fa2
+
 /* Constants that identify the `qnx4' filesystem.  */
 #define QNX4_SUPER_MAGIC	0x002f
 
diff --git a/sysdeps/unix/sysv/linux/statvfs.c b/sysdeps/unix/sysv/linux/statvfs.c
index 5eef62c5f6..51d4f4fd0c 100644
--- a/sysdeps/unix/sysv/linux/statvfs.c
+++ b/sysdeps/unix/sysv/linux/statvfs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -17,16 +17,14 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <errno.h>
-#include <mntent.h>
-#include <paths.h>
-#include <stdio_ext.h>
-#include <string.h>
-#include <sys/mount.h>
+#include <stddef.h>
 #include <sys/stat.h>
 #include <sys/statfs.h>
 #include <sys/statvfs.h>
 
+extern void __internal_statvfs (const char *name, struct statvfs *buf,
+				struct statfs *fsbuf, struct stat64 *st);
+
 
 int
 statvfs (const char *file, struct statvfs *buf)
@@ -38,8 +36,9 @@ statvfs (const char *file, struct statvfs *buf)
   if (__statfs (file, &fsbuf) < 0)
     return -1;
 
-#define STAT(st) stat64 (file, st)
-#include "internal_statvfs.c"
+  /* Convert the result.  */
+  __internal_statvfs (file, buf, &fsbuf,
+		      stat64 (file, &st) == -1 ? NULL : &st);
 
   /* We signal success if the statfs call succeeded.  */
   return 0;