NEWS.stable: log cherry-pick [ae006b4]->[4a9738e] strtoimax: Avoid link error on...
[gnulib.git] / lib / mountlist.c
index ccb08dd..23437bc 100644 (file)
@@ -1,6 +1,6 @@
 /* mountlist.c -- return a list of mounted file systems
 
-   Copyright (C) 1991-1992, 1997-2010 Free Software Foundation, Inc.
+   Copyright (C) 1991-1992, 1997-2011 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 # include <sys/vfs.h>
 #endif
 
+#ifdef MOUNTED_INTERIX_STATVFS  /* Interix. */
+# include <sys/statvfs.h>
+# include <dirent.h>
+#endif
+
 #ifdef DOLPHIN
 /* So special that it's not worth putting this in autoconf.  */
 # undef MOUNTED_FREAD_FSTYP
 
 #undef MNT_IGNORE
 #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
-# define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
+# define MNT_IGNORE(M) hasmntopt (M, MNTOPT_IGNORE)
 #else
 # define MNT_IGNORE(M) 0
 #endif
      || strcmp (Fs_type, "ignore") == 0)
 #endif
 
+#ifdef __CYGWIN__
+# include <windows.h>
+# define ME_REMOTE me_remote
+/* All cygwin mount points include `:' or start with `//'; so it
+   requires a native Windows call to determine remote disks.  */
+static bool
+me_remote (char const *fs_name, char const *fs_type _GL_UNUSED)
+{
+  if (fs_name[0] && fs_name[1] == ':')
+    {
+      char drive[4];
+      sprintf (drive, "%c:\\", fs_name[0]);
+      switch (GetDriveType (drive))
+        {
+        case DRIVE_REMOVABLE:
+        case DRIVE_FIXED:
+        case DRIVE_CDROM:
+        case DRIVE_RAMDISK:
+          return false;
+        }
+    }
+  return true;
+}
+#endif
+
 #ifndef ME_REMOTE
 /* A file system is `remote' if its Fs_name contains a `:'
    or if (it is of type (smbfs or cifs) and its Fs_name starts with `//').  */
@@ -354,19 +384,20 @@ read_file_system_list (bool need_fs_type)
 
     if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
       return NULL;
-    for (p = mntlist; p; p = p->next) {
-      mnt = p->ment;
-      me = xmalloc (sizeof *me);
-      me->me_devname = xstrdup (mnt->mnt_fsname);
-      me->me_mountdir = xstrdup (mnt->mnt_dir);
-      me->me_type = xstrdup (mnt->mnt_type);
-      me->me_type_malloced = 1;
-      me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
-      me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
-      me->me_dev = -1;
-      *mtail = me;
-      mtail = &me->me_next;
-    }
+    for (p = mntlist; p; p = p->next)
+      {
+        mnt = p->ment;
+        me = xmalloc (sizeof *me);
+        me->me_devname = xstrdup (mnt->mnt_fsname);
+        me->me_mountdir = xstrdup (mnt->mnt_dir);
+        me->me_type = xstrdup (mnt->mnt_type);
+        me->me_type_malloced = 1;
+        me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
+        me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
+        me->me_dev = -1;
+        *mtail = me;
+        mtail = &me->me_next;
+      }
     freemntlist (mntlist);
   }
 #endif
@@ -564,7 +595,8 @@ read_file_system_list (bool need_fs_type)
               break;
 
           me = xmalloc (sizeof *me);
-          me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
+          me->me_devname = xstrdup (fi.device_name[0] != '\0'
+                                    ? fi.device_name : fi.fsh_name);
           me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
           me->me_type = xstrdup (fi.fsh_name);
           me->me_type_malloced = 1;
@@ -594,9 +626,9 @@ read_file_system_list (bool need_fs_type)
     size_t bufsize;
     struct statfs *stats;
 
-    numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
+    numsys = getfsstat (NULL, 0L, MNT_NOWAIT);
     if (numsys < 0)
-      return (NULL);
+      return NULL;
     if (SIZE_MAX / sizeof *stats <= numsys)
       xalloc_die ();
 
@@ -607,7 +639,7 @@ read_file_system_list (bool need_fs_type)
     if (numsys < 0)
       {
         free (stats);
-        return (NULL);
+        return NULL;
       }
 
     for (counter = 0; counter < numsys; counter++)
@@ -693,11 +725,11 @@ read_file_system_list (bool need_fs_type)
 #ifdef MOUNTED_GETMNTTBL        /* DolphinOS goes its own way.  */
   {
     struct mntent **mnttbl = getmnttbl (), **ent;
-    for (ent=mnttbl;*ent;ent++)
+    for (ent = mnttbl; *ent; ent++)
       {
         me = xmalloc (sizeof *me);
-        me->me_devname = xstrdup ( (*ent)->mt_resource);
-        me->me_mountdir = xstrdup ( (*ent)->mt_directory);
+        me->me_devname = xstrdup ((*ent)->mt_resource);
+        me->me_mountdir = xstrdup ((*ent)->mt_directory);
         me->me_type = xstrdup ((*ent)->mt_fstype);
         me->me_type_malloced = 1;
         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
@@ -854,6 +886,45 @@ read_file_system_list (bool need_fs_type)
   }
 #endif /* MOUNTED_VMOUNT. */
 
+#ifdef MOUNTED_INTERIX_STATVFS
+  {
+    DIR *dirp = opendir ("/dev/fs");
+    char node[9 + NAME_MAX];
+
+    if (!dirp)
+      goto free_then_fail;
+
+    while (1)
+      {
+        struct statvfs dev;
+        struct dirent entry;
+        struct dirent *result;
+
+        if (readdir_r (dirp, &entry, &result) || result == NULL)
+          break;
+
+        strcpy (node, "/dev/fs/");
+        strcat (node, entry.d_name);
+
+        if (statvfs (node, &dev) == 0)
+          {
+            me = xmalloc (sizeof *me);
+            me->me_devname = xstrdup (dev.f_mntfromname);
+            me->me_mountdir = xstrdup (dev.f_mntonname);
+            me->me_type = xstrdup (dev.f_fstypename);
+            me->me_type_malloced = 1;
+            me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
+            me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
+            me->me_dev = (dev_t) -1;        /* Magic; means not known yet. */
+
+            /* Add to the linked list. */
+            *mtail = me;
+            mtail = &me->me_next;
+          }
+      }
+  }
+#endif /* MOUNTED_INTERIX_STATVFS */
+
   *mtail = NULL;
   return mount_list;