LCOV - code coverage report
Current view: top level - lib - mountlist.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 21 36 58.3 %
Date: 2018-01-30 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* mountlist.c -- return a list of mounted file systems
       2             : 
       3             :    Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
       4             :    2004, 2005, 2006, 2007 Free Software Foundation, Inc.
       5             : 
       6             :    This program is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      18             : 
      19             : #include <config.h>
      20             : 
      21             : #include "mountlist.h"
      22             : 
      23             : #include <limits.h>
      24             : #include <stdio.h>
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : 
      28             : #include "xalloc.h"
      29             : 
      30             : #include <errno.h>
      31             : 
      32             : #include <fcntl.h>
      33             : 
      34             : #include <unistd.h>
      35             : 
      36             : #if HAVE_SYS_PARAM_H
      37             : # include <sys/param.h>
      38             : #endif
      39             : 
      40             : #if defined MOUNTED_GETFSSTAT   /* OSF_1 and Darwin1.3.x */
      41             : # if HAVE_SYS_UCRED_H
      42             : #  include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
      43             :                       NGROUPS is used as an array dimension in ucred.h */
      44             : #  include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
      45             : # endif
      46             : # if HAVE_SYS_MOUNT_H
      47             : #  include <sys/mount.h>
      48             : # endif
      49             : # if HAVE_SYS_FS_TYPES_H
      50             : #  include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
      51             : # endif
      52             : # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
      53             : #  define FS_TYPE(Ent) ((Ent).f_fstypename)
      54             : # else
      55             : #  define FS_TYPE(Ent) mnt_names[(Ent).f_type]
      56             : # endif
      57             : #endif /* MOUNTED_GETFSSTAT */
      58             : 
      59             : #ifdef MOUNTED_GETMNTENT1       /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
      60             : # include <mntent.h>
      61             : # if !defined MOUNTED
      62             : #  if defined _PATH_MOUNTED     /* GNU libc  */
      63             : #   define MOUNTED _PATH_MOUNTED
      64             : #  endif
      65             : #  if defined MNT_MNTTAB        /* HP-UX.  */
      66             : #   define MOUNTED MNT_MNTTAB
      67             : #  endif
      68             : #  if defined MNTTABNAME        /* Dynix.  */
      69             : #   define MOUNTED MNTTABNAME
      70             : #  endif
      71             : # endif
      72             : #endif
      73             : 
      74             : #ifdef MOUNTED_GETMNTINFO       /* 4.4BSD.  */
      75             : # include <sys/mount.h>
      76             : #endif
      77             : 
      78             : #ifdef MOUNTED_GETMNTINFO2      /* NetBSD 3.0.  */
      79             : # include <sys/statvfs.h>
      80             : #endif
      81             : 
      82             : #ifdef MOUNTED_GETMNT           /* Ultrix.  */
      83             : # include <sys/mount.h>
      84             : # include <sys/fs_types.h>
      85             : #endif
      86             : 
      87             : #ifdef MOUNTED_FS_STAT_DEV      /* BeOS.  */
      88             : # include <fs_info.h>
      89             : # include <dirent.h>
      90             : #endif
      91             : 
      92             : #ifdef MOUNTED_FREAD            /* SVR2.  */
      93             : # include <mnttab.h>
      94             : #endif
      95             : 
      96             : #ifdef MOUNTED_FREAD_FSTYP      /* SVR3.  */
      97             : # include <mnttab.h>
      98             : # include <sys/fstyp.h>
      99             : # include <sys/statfs.h>
     100             : #endif
     101             : 
     102             : #ifdef MOUNTED_LISTMNTENT
     103             : # include <mntent.h>
     104             : #endif
     105             : 
     106             : #ifdef MOUNTED_GETMNTENT2       /* SVR4.  */
     107             : # include <sys/mnttab.h>
     108             : #endif
     109             : 
     110             : #ifdef MOUNTED_VMOUNT           /* AIX.  */
     111             : # include <fshelp.h>
     112             : # include <sys/vfs.h>
     113             : #endif
     114             : 
     115             : #ifdef DOLPHIN
     116             : /* So special that it's not worth putting this in autoconf.  */
     117             : # undef MOUNTED_FREAD_FSTYP
     118             : # define MOUNTED_GETMNTTBL
     119             : #endif
     120             : 
     121             : #if HAVE_SYS_MNTENT_H
     122             : /* This is to get MNTOPT_IGNORE on e.g. SVR4.  */
     123             : # include <sys/mntent.h>
     124             : #endif
     125             : 
     126             : #undef MNT_IGNORE
     127             : #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
     128             : # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
     129             : #else
     130             : # define MNT_IGNORE(M) 0
     131             : #endif
     132             : 
     133             : #if USE_UNLOCKED_IO
     134             : # include "unlocked-io.h"
     135             : #endif
     136             : 
     137             : #ifndef SIZE_MAX
     138             : # define SIZE_MAX ((size_t) -1)
     139             : #endif
     140             : 
     141             : /* The results of open() in this file are not used with fchdir,
     142             :    therefore save some unnecessary work in fchdir.c.  */
     143             : #undef open
     144             : #undef close
     145             : 
     146             : /* The results of opendir() in this file are not used with dirfd and fchdir,
     147             :    therefore save some unnecessary work in fchdir.c.  */
     148             : #undef opendir
     149             : #undef closedir
     150             : 
     151             : #ifndef ME_DUMMY
     152             : # define ME_DUMMY(Fs_name, Fs_type)             \
     153             :     (strcmp (Fs_type, "autofs") == 0          \
     154             :      || strcmp (Fs_type, "none") == 0         \
     155             :      || strcmp (Fs_type, "proc") == 0         \
     156             :      || strcmp (Fs_type, "subfs") == 0                \
     157             :      /* for NetBSD 3.0 */                       \
     158             :      || strcmp (Fs_type, "kernfs") == 0               \
     159             :      /* for Irix 6.5 */                         \
     160             :      || strcmp (Fs_type, "ignore") == 0)
     161             : #endif
     162             : 
     163             : #ifndef ME_REMOTE
     164             : /* A file system is `remote' if its Fs_name contains a `:'
     165             :    or if (it is of type (smbfs or cifs) and its Fs_name starts with `//').  */
     166             : # define ME_REMOTE(Fs_name, Fs_type)            \
     167             :     (strchr (Fs_name, ':') != NULL              \
     168             :      || ((Fs_name)[0] == '/'                    \
     169             :          && (Fs_name)[1] == '/'                 \
     170             :          && (strcmp (Fs_type, "smbfs") == 0   \
     171             :              || strcmp (Fs_type, "cifs") == 0)))
     172             : #endif
     173             : 
     174             : #if MOUNTED_GETMNTINFO
     175             : 
     176             : # if ! HAVE_STRUCT_STATFS_F_FSTYPENAME
     177             : static char *
     178             : fstype_to_string (short int t)
     179             : {
     180             :   switch (t)
     181             :     {
     182             : #  ifdef MOUNT_PC
     183             :     case MOUNT_PC:
     184             :       return "pc";
     185             : #  endif
     186             : #  ifdef MOUNT_MFS
     187             :     case MOUNT_MFS:
     188             :       return "mfs";
     189             : #  endif
     190             : #  ifdef MOUNT_LO
     191             :     case MOUNT_LO:
     192             :       return "lo";
     193             : #  endif
     194             : #  ifdef MOUNT_TFS
     195             :     case MOUNT_TFS:
     196             :       return "tfs";
     197             : #  endif
     198             : #  ifdef MOUNT_TMP
     199             :     case MOUNT_TMP:
     200             :       return "tmp";
     201             : #  endif
     202             : #  ifdef MOUNT_UFS
     203             :    case MOUNT_UFS:
     204             :      return "ufs" ;
     205             : #  endif
     206             : #  ifdef MOUNT_NFS
     207             :    case MOUNT_NFS:
     208             :      return "nfs" ;
     209             : #  endif
     210             : #  ifdef MOUNT_MSDOS
     211             :    case MOUNT_MSDOS:
     212             :      return "msdos" ;
     213             : #  endif
     214             : #  ifdef MOUNT_LFS
     215             :    case MOUNT_LFS:
     216             :      return "lfs" ;
     217             : #  endif
     218             : #  ifdef MOUNT_LOFS
     219             :    case MOUNT_LOFS:
     220             :      return "lofs" ;
     221             : #  endif
     222             : #  ifdef MOUNT_FDESC
     223             :    case MOUNT_FDESC:
     224             :      return "fdesc" ;
     225             : #  endif
     226             : #  ifdef MOUNT_PORTAL
     227             :    case MOUNT_PORTAL:
     228             :      return "portal" ;
     229             : #  endif
     230             : #  ifdef MOUNT_NULL
     231             :    case MOUNT_NULL:
     232             :      return "null" ;
     233             : #  endif
     234             : #  ifdef MOUNT_UMAP
     235             :    case MOUNT_UMAP:
     236             :      return "umap" ;
     237             : #  endif
     238             : #  ifdef MOUNT_KERNFS
     239             :    case MOUNT_KERNFS:
     240             :      return "kernfs" ;
     241             : #  endif
     242             : #  ifdef MOUNT_PROCFS
     243             :    case MOUNT_PROCFS:
     244             :      return "procfs" ;
     245             : #  endif
     246             : #  ifdef MOUNT_AFS
     247             :    case MOUNT_AFS:
     248             :      return "afs" ;
     249             : #  endif
     250             : #  ifdef MOUNT_CD9660
     251             :    case MOUNT_CD9660:
     252             :      return "cd9660" ;
     253             : #  endif
     254             : #  ifdef MOUNT_UNION
     255             :    case MOUNT_UNION:
     256             :      return "union" ;
     257             : #  endif
     258             : #  ifdef MOUNT_DEVFS
     259             :    case MOUNT_DEVFS:
     260             :      return "devfs" ;
     261             : #  endif
     262             : #  ifdef MOUNT_EXT2FS
     263             :    case MOUNT_EXT2FS:
     264             :      return "ext2fs" ;
     265             : #  endif
     266             :     default:
     267             :       return "?";
     268             :     }
     269             : }
     270             : # endif
     271             : 
     272             : static char *
     273             : fsp_to_string (const struct statfs *fsp)
     274             : {
     275             : # if HAVE_STRUCT_STATFS_F_FSTYPENAME
     276             :   return (char *) (fsp->f_fstypename);
     277             : # else
     278             :   return fstype_to_string (fsp->f_type);
     279             : # endif
     280             : }
     281             : 
     282             : #endif /* MOUNTED_GETMNTINFO */
     283             : 
     284             : #ifdef MOUNTED_VMOUNT           /* AIX.  */
     285             : static char *
     286             : fstype_to_string (int t)
     287             : {
     288             :   struct vfs_ent *e;
     289             : 
     290             :   e = getvfsbytype (t);
     291             :   if (!e || !e->vfsent_name)
     292             :     return "none";
     293             :   else
     294             :     return e->vfsent_name;
     295             : }
     296             : #endif /* MOUNTED_VMOUNT */
     297             : 
     298             : 
     299             : #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
     300             : 
     301             : /* Return the device number from MOUNT_OPTIONS, if possible.
     302             :    Otherwise return (dev_t) -1.  */
     303             : 
     304             : static dev_t
     305        1530 : dev_from_mount_options (char const *mount_options)
     306             : {
     307             :   /* GNU/Linux allows file system implementations to define their own
     308             :      meaning for "dev=" mount options, so don't trust the meaning
     309             :      here.  */
     310             : # ifndef __linux__
     311             : 
     312             :   static char const dev_pattern[] = ",dev=";
     313             :   char const *devopt = strstr (mount_options, dev_pattern);
     314             : 
     315             :   if (devopt)
     316             :     {
     317             :       char const *optval = devopt + sizeof dev_pattern - 1;
     318             :       char *optvalend;
     319             :       unsigned long int dev;
     320             :       errno = 0;
     321             :       dev = strtoul (optval, &optvalend, 16);
     322             :       if (optval != optvalend
     323             :           && (*optvalend == '\0' || *optvalend == ',')
     324             :           && ! (dev == ULONG_MAX && errno == ERANGE)
     325             :           && dev == (dev_t) dev)
     326             :         return dev;
     327             :     }
     328             : 
     329             : # endif
     330             : 
     331        1530 :   return -1;
     332             : }
     333             : 
     334             : #endif
     335             : 
     336             : /* Return a list of the currently mounted file systems, or NULL on error.
     337             :    Add each entry to the tail of the list so that they stay in order.
     338             :    If NEED_FS_TYPE is true, ensure that the file system type fields in
     339             :    the returned list are valid.  Otherwise, they might not be.  */
     340             : 
     341             : struct mount_entry *
     342          45 : read_file_system_list (bool need_fs_type)
     343             : {
     344             :   struct mount_entry *mount_list;
     345             :   struct mount_entry *me;
     346          45 :   struct mount_entry **mtail = &mount_list;
     347             : 
     348             : #ifdef MOUNTED_LISTMNTENT
     349             :   {
     350             :     struct tabmntent *mntlist, *p;
     351             :     struct mntent *mnt;
     352             :     struct mount_entry *me;
     353             : 
     354             :     /* the third and fourth arguments could be used to filter mounts,
     355             :        but Crays doesn't seem to have any mounts that we want to
     356             :        remove. Specifically, automount create normal NFS mounts.
     357             :        */
     358             : 
     359             :     if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
     360             :       return NULL;
     361             :     for (p = mntlist; p; p = p->next) {
     362             :       mnt = p->ment;
     363             :       me = xmalloc (sizeof *me);
     364             :       me->me_devname = xstrdup (mnt->mnt_fsname);
     365             :       me->me_mountdir = xstrdup (mnt->mnt_dir);
     366             :       me->me_type = xstrdup (mnt->mnt_type);
     367             :       me->me_type_malloced = 1;
     368             :       me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     369             :       me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     370             :       me->me_dev = -1;
     371             :       *mtail = me;
     372             :       mtail = &me->me_next;
     373             :     }
     374             :     freemntlist (mntlist);
     375             :   }
     376             : #endif
     377             : 
     378             : #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
     379             :   {
     380             :     struct mntent *mnt;
     381          45 :     char *table = MOUNTED;
     382             :     FILE *fp;
     383             : 
     384          45 :     fp = setmntent (table, "r");
     385          45 :     if (fp == NULL)
     386           0 :       return NULL;
     387             : 
     388        1620 :     while ((mnt = getmntent (fp)))
     389             :       {
     390        1530 :         me = xmalloc (sizeof *me);
     391        1530 :         me->me_devname = xstrdup (mnt->mnt_fsname);
     392        1530 :         me->me_mountdir = xstrdup (mnt->mnt_dir);
     393        1530 :         me->me_type = xstrdup (mnt->mnt_type);
     394        1530 :         me->me_type_malloced = 1;
     395        1530 :         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     396        1530 :         me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     397        1530 :         me->me_dev = dev_from_mount_options (mnt->mnt_opts);
     398             : 
     399             :         /* Add to the linked list. */
     400        1530 :         *mtail = me;
     401        1530 :         mtail = &me->me_next;
     402             :       }
     403             : 
     404          45 :     if (endmntent (fp) == 0)
     405           0 :       goto free_then_fail;
     406             :   }
     407             : #endif /* MOUNTED_GETMNTENT1. */
     408             : 
     409             : #ifdef MOUNTED_GETMNTINFO       /* 4.4BSD.  */
     410             :   {
     411             :     struct statfs *fsp;
     412             :     int entries;
     413             : 
     414             :     entries = getmntinfo (&fsp, MNT_NOWAIT);
     415             :     if (entries < 0)
     416             :       return NULL;
     417             :     for (; entries-- > 0; fsp++)
     418             :       {
     419             :         char *fs_type = fsp_to_string (fsp);
     420             : 
     421             :         me = xmalloc (sizeof *me);
     422             :         me->me_devname = xstrdup (fsp->f_mntfromname);
     423             :         me->me_mountdir = xstrdup (fsp->f_mntonname);
     424             :         me->me_type = fs_type;
     425             :         me->me_type_malloced = 0;
     426             :         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     427             :         me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     428             :         me->me_dev = (dev_t) -1;     /* Magic; means not known yet. */
     429             : 
     430             :         /* Add to the linked list. */
     431             :         *mtail = me;
     432             :         mtail = &me->me_next;
     433             :       }
     434             :   }
     435             : #endif /* MOUNTED_GETMNTINFO */
     436             : 
     437             : #ifdef MOUNTED_GETMNTINFO2      /* NetBSD 3.0.  */
     438             :   {
     439             :     struct statvfs *fsp;
     440             :     int entries;
     441             : 
     442             :     entries = getmntinfo (&fsp, MNT_NOWAIT);
     443             :     if (entries < 0)
     444             :       return NULL;
     445             :     for (; entries-- > 0; fsp++)
     446             :       {
     447             :         me = xmalloc (sizeof *me);
     448             :         me->me_devname = xstrdup (fsp->f_mntfromname);
     449             :         me->me_mountdir = xstrdup (fsp->f_mntonname);
     450             :         me->me_type = xstrdup (fsp->f_fstypename);
     451             :         me->me_type_malloced = 1;
     452             :         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     453             :         me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     454             :         me->me_dev = (dev_t) -1;     /* Magic; means not known yet. */
     455             : 
     456             :         /* Add to the linked list. */
     457             :         *mtail = me;
     458             :         mtail = &me->me_next;
     459             :       }
     460             :   }
     461             : #endif /* MOUNTED_GETMNTINFO2 */
     462             : 
     463             : #ifdef MOUNTED_GETMNT           /* Ultrix.  */
     464             :   {
     465             :     int offset = 0;
     466             :     int val;
     467             :     struct fs_data fsd;
     468             : 
     469             :     while (errno = 0,
     470             :            0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
     471             :                               (char *) 0)))
     472             :       {
     473             :         me = xmalloc (sizeof *me);
     474             :         me->me_devname = xstrdup (fsd.fd_req.devname);
     475             :         me->me_mountdir = xstrdup (fsd.fd_req.path);
     476             :         me->me_type = gt_names[fsd.fd_req.fstype];
     477             :         me->me_type_malloced = 0;
     478             :         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     479             :         me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     480             :         me->me_dev = fsd.fd_req.dev;
     481             : 
     482             :         /* Add to the linked list. */
     483             :         *mtail = me;
     484             :         mtail = &me->me_next;
     485             :       }
     486             :     if (val < 0)
     487             :       goto free_then_fail;
     488             :   }
     489             : #endif /* MOUNTED_GETMNT. */
     490             : 
     491             : #if defined MOUNTED_FS_STAT_DEV /* BeOS */
     492             :   {
     493             :     /* The next_dev() and fs_stat_dev() system calls give the list of
     494             :        all file systems, including the information returned by statvfs()
     495             :        (fs type, total blocks, free blocks etc.), but without the mount
     496             :        point. But on BeOS all file systems except / are mounted in the
     497             :        rootfs, directly under /.
     498             :        The directory name of the mount point is often, but not always,
     499             :        identical to the volume name of the device.
     500             :        We therefore get the list of subdirectories of /, and the list
     501             :        of all file systems, and match the two lists.  */
     502             : 
     503             :     DIR *dirp;
     504             :     struct rootdir_entry
     505             :       {
     506             :         char *name;
     507             :         dev_t dev;
     508             :         ino_t ino;
     509             :         struct rootdir_entry *next;
     510             :       };
     511             :     struct rootdir_entry *rootdir_list;
     512             :     struct rootdir_entry **rootdir_tail;
     513             :     int32 pos;
     514             :     dev_t dev;
     515             :     fs_info fi;
     516             : 
     517             :     /* All volumes are mounted in the rootfs, directly under /. */
     518             :     rootdir_list = NULL;
     519             :     rootdir_tail = &rootdir_list;
     520             :     dirp = opendir ("/");
     521             :     if (dirp)
     522             :       {
     523             :         struct dirent *d;
     524             : 
     525             :         while ((d = readdir (dirp)) != NULL)
     526             :           {
     527             :             char *name;
     528             :             struct stat statbuf;
     529             : 
     530             :             if (strcmp (d->d_name, "..") == 0)
     531             :               continue;
     532             : 
     533             :             if (strcmp (d->d_name, ".") == 0)
     534             :               name = xstrdup ("/");
     535             :             else
     536             :               {
     537             :                 name = xmalloc (1 + strlen (d->d_name) + 1);
     538             :                 name[0] = '/';
     539             :                 strcpy (name + 1, d->d_name);
     540             :               }
     541             : 
     542             :             if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
     543             :               {
     544             :                 struct rootdir_entry *re = xmalloc (sizeof *re);
     545             :                 re->name = name;
     546             :                 re->dev = statbuf.st_dev;
     547             :                 re->ino = statbuf.st_ino;
     548             : 
     549             :                 /* Add to the linked list.  */
     550             :                 *rootdir_tail = re;
     551             :                 rootdir_tail = &re->next;
     552             :               }
     553             :             else
     554             :               free (name);
     555             :           }
     556             :         closedir (dirp);
     557             :       }
     558             :     *rootdir_tail = NULL;
     559             : 
     560             :     for (pos = 0; (dev = next_dev (&pos)) >= 0; )
     561             :       if (fs_stat_dev (dev, &fi) >= 0)
     562             :         {
     563             :           /* Note: fi.dev == dev. */
     564             :           struct rootdir_entry *re;
     565             : 
     566             :           for (re = rootdir_list; re; re = re->next)
     567             :             if (re->dev == fi.dev && re->ino == fi.root)
     568             :               break;
     569             : 
     570             :           me = xmalloc (sizeof *me);
     571             :           me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
     572             :           me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
     573             :           me->me_type = xstrdup (fi.fsh_name);
     574             :           me->me_type_malloced = 1;
     575             :           me->me_dev = fi.dev;
     576             :           me->me_dummy = 0;
     577             :           me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
     578             : 
     579             :           /* Add to the linked list. */
     580             :           *mtail = me;
     581             :           mtail = &me->me_next;
     582             :         }
     583             :     *mtail = NULL;
     584             : 
     585             :     while (rootdir_list != NULL)
     586             :       {
     587             :         struct rootdir_entry *re = rootdir_list;
     588             :         rootdir_list = re->next;
     589             :         free (re->name);
     590             :         free (re);
     591             :       }
     592             :   }
     593             : #endif /* MOUNTED_FS_STAT_DEV */
     594             : 
     595             : #if defined MOUNTED_GETFSSTAT   /* __alpha running OSF_1 */
     596             :   {
     597             :     int numsys, counter;
     598             :     size_t bufsize;
     599             :     struct statfs *stats;
     600             : 
     601             :     numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
     602             :     if (numsys < 0)
     603             :       return (NULL);
     604             :     if (SIZE_MAX / sizeof *stats <= numsys)
     605             :       xalloc_die ();
     606             : 
     607             :     bufsize = (1 + numsys) * sizeof *stats;
     608             :     stats = xmalloc (bufsize);
     609             :     numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
     610             : 
     611             :     if (numsys < 0)
     612             :       {
     613             :         free (stats);
     614             :         return (NULL);
     615             :       }
     616             : 
     617             :     for (counter = 0; counter < numsys; counter++)
     618             :       {
     619             :         me = xmalloc (sizeof *me);
     620             :         me->me_devname = xstrdup (stats[counter].f_mntfromname);
     621             :         me->me_mountdir = xstrdup (stats[counter].f_mntonname);
     622             :         me->me_type = xstrdup (FS_TYPE (stats[counter]));
     623             :         me->me_type_malloced = 1;
     624             :         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     625             :         me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     626             :         me->me_dev = (dev_t) -1;     /* Magic; means not known yet. */
     627             : 
     628             :         /* Add to the linked list. */
     629             :         *mtail = me;
     630             :         mtail = &me->me_next;
     631             :       }
     632             : 
     633             :     free (stats);
     634             :   }
     635             : #endif /* MOUNTED_GETFSSTAT */
     636             : 
     637             : #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23].  */
     638             :   {
     639             :     struct mnttab mnt;
     640             :     char *table = "/etc/mnttab";
     641             :     FILE *fp;
     642             : 
     643             :     fp = fopen (table, "r");
     644             :     if (fp == NULL)
     645             :       return NULL;
     646             : 
     647             :     while (fread (&mnt, sizeof mnt, 1, fp) > 0)
     648             :       {
     649             :         me = xmalloc (sizeof *me);
     650             : # ifdef GETFSTYP                        /* SVR3.  */
     651             :         me->me_devname = xstrdup (mnt.mt_dev);
     652             : # else
     653             :         me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
     654             :         strcpy (me->me_devname, "/dev/");
     655             :         strcpy (me->me_devname + 5, mnt.mt_dev);
     656             : # endif
     657             :         me->me_mountdir = xstrdup (mnt.mt_filsys);
     658             :         me->me_dev = (dev_t) -1;     /* Magic; means not known yet. */
     659             :         me->me_type = "";
     660             :         me->me_type_malloced = 0;
     661             : # ifdef GETFSTYP                        /* SVR3.  */
     662             :         if (need_fs_type)
     663             :           {
     664             :             struct statfs fsd;
     665             :             char typebuf[FSTYPSZ];
     666             : 
     667             :             if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
     668             :                 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
     669             :               {
     670             :                 me->me_type = xstrdup (typebuf);
     671             :                 me->me_type_malloced = 1;
     672             :               }
     673             :           }
     674             : # endif
     675             :         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     676             :         me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     677             : 
     678             :         /* Add to the linked list. */
     679             :         *mtail = me;
     680             :         mtail = &me->me_next;
     681             :       }
     682             : 
     683             :     if (ferror (fp))
     684             :       {
     685             :         /* The last fread() call must have failed.  */
     686             :         int saved_errno = errno;
     687             :         fclose (fp);
     688             :         errno = saved_errno;
     689             :         goto free_then_fail;
     690             :       }
     691             : 
     692             :     if (fclose (fp) == EOF)
     693             :       goto free_then_fail;
     694             :   }
     695             : #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP.  */
     696             : 
     697             : #ifdef MOUNTED_GETMNTTBL        /* DolphinOS goes its own way.  */
     698             :   {
     699             :     struct mntent **mnttbl = getmnttbl (), **ent;
     700             :     for (ent=mnttbl;*ent;ent++)
     701             :       {
     702             :         me = xmalloc (sizeof *me);
     703             :         me->me_devname = xstrdup ( (*ent)->mt_resource);
     704             :         me->me_mountdir = xstrdup ( (*ent)->mt_directory);
     705             :         me->me_type = xstrdup ((*ent)->mt_fstype);
     706             :         me->me_type_malloced = 1;
     707             :         me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
     708             :         me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     709             :         me->me_dev = (dev_t) -1;     /* Magic; means not known yet. */
     710             : 
     711             :         /* Add to the linked list. */
     712             :         *mtail = me;
     713             :         mtail = &me->me_next;
     714             :       }
     715             :     endmnttbl ();
     716             :   }
     717             : #endif
     718             : 
     719             : #ifdef MOUNTED_GETMNTENT2       /* SVR4.  */
     720             :   {
     721             :     struct mnttab mnt;
     722             :     char *table = MNTTAB;
     723             :     FILE *fp;
     724             :     int ret;
     725             :     int lockfd = -1;
     726             : 
     727             : # if defined F_RDLCK && defined F_SETLKW
     728             :     /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
     729             :        e.g. Solaris 2.6.  If the SVR4 folks ever define a macro
     730             :        for this file name, we should use their macro name instead.
     731             :        (Why not just lock MNTTAB directly?  We don't know.)  */
     732             : #  ifndef MNTTAB_LOCK
     733             : #   define MNTTAB_LOCK "/etc/.mnttab.lock"
     734             : #  endif
     735             :     lockfd = open (MNTTAB_LOCK, O_RDONLY);
     736             :     if (0 <= lockfd)
     737             :       {
     738             :         struct flock flock;
     739             :         flock.l_type = F_RDLCK;
     740             :         flock.l_whence = SEEK_SET;
     741             :         flock.l_start = 0;
     742             :         flock.l_len = 0;
     743             :         while (fcntl (lockfd, F_SETLKW, &flock) == -1)
     744             :           if (errno != EINTR)
     745             :             {
     746             :               int saved_errno = errno;
     747             :               close (lockfd);
     748             :               errno = saved_errno;
     749             :               return NULL;
     750             :             }
     751             :       }
     752             :     else if (errno != ENOENT)
     753             :       return NULL;
     754             : # endif
     755             : 
     756             :     errno = 0;
     757             :     fp = fopen (table, "r");
     758             :     if (fp == NULL)
     759             :       ret = errno;
     760             :     else
     761             :       {
     762             :         while ((ret = getmntent (fp, &mnt)) == 0)
     763             :           {
     764             :             me = xmalloc (sizeof *me);
     765             :             me->me_devname = xstrdup (mnt.mnt_special);
     766             :             me->me_mountdir = xstrdup (mnt.mnt_mountp);
     767             :             me->me_type = xstrdup (mnt.mnt_fstype);
     768             :             me->me_type_malloced = 1;
     769             :             me->me_dummy = MNT_IGNORE (&mnt) != 0;
     770             :             me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
     771             :             me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
     772             : 
     773             :             /* Add to the linked list. */
     774             :             *mtail = me;
     775             :             mtail = &me->me_next;
     776             :           }
     777             : 
     778             :         ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
     779             :       }
     780             : 
     781             :     if (0 <= lockfd && close (lockfd) != 0)
     782             :       ret = errno;
     783             : 
     784             :     if (0 <= ret)
     785             :       {
     786             :         errno = ret;
     787             :         goto free_then_fail;
     788             :       }
     789             :   }
     790             : #endif /* MOUNTED_GETMNTENT2.  */
     791             : 
     792             : #ifdef MOUNTED_VMOUNT           /* AIX.  */
     793             :   {
     794             :     int bufsize;
     795             :     char *entries, *thisent;
     796             :     struct vmount *vmp;
     797             :     int n_entries;
     798             :     int i;
     799             : 
     800             :     /* Ask how many bytes to allocate for the mounted file system info.  */
     801             :     if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0)
     802             :       return NULL;
     803             :     entries = xmalloc (bufsize);
     804             : 
     805             :     /* Get the list of mounted file systems.  */
     806             :     n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
     807             :     if (n_entries < 0)
     808             :       {
     809             :         int saved_errno = errno;
     810             :         free (entries);
     811             :         errno = saved_errno;
     812             :         return NULL;
     813             :       }
     814             : 
     815             :     for (i = 0, thisent = entries;
     816             :          i < n_entries;
     817             :          i++, thisent += vmp->vmt_length)
     818             :       {
     819             :         char *options, *ignore;
     820             : 
     821             :         vmp = (struct vmount *) thisent;
     822             :         me = xmalloc (sizeof *me);
     823             :         if (vmp->vmt_flags & MNT_REMOTE)
     824             :           {
     825             :             char *host, *dir;
     826             : 
     827             :             me->me_remote = 1;
     828             :             /* Prepend the remote dirname.  */
     829             :             host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
     830             :             dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
     831             :             me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2);
     832             :             strcpy (me->me_devname, host);
     833             :             strcat (me->me_devname, ":");
     834             :             strcat (me->me_devname, dir);
     835             :           }
     836             :         else
     837             :           {
     838             :             me->me_remote = 0;
     839             :             me->me_devname = xstrdup (thisent +
     840             :                                       vmp->vmt_data[VMT_OBJECT].vmt_off);
     841             :           }
     842             :         me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
     843             :         me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
     844             :         me->me_type_malloced = 1;
     845             :         options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
     846             :         ignore = strstr (options, "ignore");
     847             :         me->me_dummy = (ignore
     848             :                         && (ignore == options || ignore[-1] == ',')
     849             :                         && (ignore[sizeof "ignore" - 1] == ','
     850             :                             || ignore[sizeof "ignore" - 1] == '\0'));
     851             :         me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want.  */
     852             : 
     853             :         /* Add to the linked list. */
     854             :         *mtail = me;
     855             :         mtail = &me->me_next;
     856             :       }
     857             :     free (entries);
     858             :   }
     859             : #endif /* MOUNTED_VMOUNT. */
     860             : 
     861          45 :   *mtail = NULL;
     862          45 :   return mount_list;
     863             : 
     864             : 
     865           0 :  free_then_fail:
     866             :   {
     867           0 :     int saved_errno = errno;
     868           0 :     *mtail = NULL;
     869             : 
     870           0 :     while (mount_list)
     871             :       {
     872           0 :         me = mount_list->me_next;
     873           0 :         free (mount_list->me_devname);
     874           0 :         free (mount_list->me_mountdir);
     875           0 :         if (mount_list->me_type_malloced)
     876           0 :           free (mount_list->me_type);
     877           0 :         free (mount_list);
     878           0 :         mount_list = me;
     879             :       }
     880             : 
     881           0 :     errno = saved_errno;
     882           0 :     return NULL;
     883             :   }
     884             : }

Generated by: LCOV version 1.10