X-Git-Url: https://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmountlist.c;h=76607245297f8b6b3be00e259dc51b05b9d4ddc5;hb=ea12546cdee0548bded92ecffcf257aa5b6a125f;hp=5a6d664c5946ad5f5ce27b17fe8e2589a6a897e6;hpb=6d8337bfc808cddc275899c03482eceb6aff8547;p=gnulib.git diff --git a/lib/mountlist.c b/lib/mountlist.c index 5a6d664c5..766072452 100644 --- a/lib/mountlist.c +++ b/lib/mountlist.c @@ -1,5 +1,5 @@ /* mountlist.c -- return a list of mounted filesystems - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1997, 1998 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 @@ -15,8 +15,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifdef HAVE_CONFIG_H -#include +#if HAVE_CONFIG_H +# include #endif #include @@ -24,89 +24,115 @@ #include "mountlist.h" #ifdef STDC_HEADERS -#include +# include #else void free (); #endif #if defined(STDC_HEADERS) || defined(HAVE_STRING_H) -#include +# include #else -#include +# include #endif +#ifndef strstr char *strstr (); +#endif char *xmalloc (); char *xrealloc (); char *xstrdup (); void error (); -#ifdef HAVE_SYS_PARAM_H -#include +#include +#ifndef errno +extern int errno; +#endif + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#if HAVE_SYS_PARAM_H +# include #endif #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */ -# include -# include +# include +# include #endif /* MOUNTED_GETFSSTAT */ #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ -#include -#if !defined(MOUNTED) +# include +# if !defined(MOUNTED) # if defined(MNT_MNTTAB) /* HP-UX. */ -# define MOUNTED MNT_MNTTAB +# define MOUNTED MNT_MNTTAB # endif # if defined(MNTTABNAME) /* Dynix. */ -# define MOUNTED MNTTABNAME +# define MOUNTED MNTTABNAME # endif -#endif +# endif #endif #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ -#include +# include #endif #ifdef MOUNTED_GETMNT /* Ultrix. */ -#include -#include +# include +# include #endif #ifdef MOUNTED_FREAD /* SVR2. */ -#include +# include #endif #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ -#include -#include -#include +# include +# include +# include #endif #ifdef MOUNTED_LISTMNTENT -#include +# include #endif #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ -#include +# include #endif #ifdef MOUNTED_VMOUNT /* AIX. */ -#include -#include +# include +# include #endif #ifdef DOLPHIN /* So special that it's not worth putting this in autoconf. */ -#undef MOUNTED_FREAD_FSTYP -#define MOUNTED_GETMNTTBL +# undef MOUNTED_FREAD_FSTYP +# define MOUNTED_GETMNTTBL +#endif + +#if HAVE_SYS_MNTENT_H +/* This is to get MNTOPT_IGNORE on e.g. SVR4. */ +# include +#endif + +#if defined (MNTOPT_IGNORE) && defined (HAVE_HASMNTOPT) +# define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE) +#else +# define MNT_IGNORE(M) 0 #endif #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ /* Return the value of the hexadecimal number represented by CP. No prefix (like '0x') or suffix (like 'h') is expected to be part of CP. */ +/* FIXME: this can overflow */ static int -xatoi (cp) - char *cp; +xatoi (char *cp) { int val; @@ -127,47 +153,120 @@ xatoi (cp) } #endif /* MOUNTED_GETMNTENT1. */ -#if defined (MOUNTED_GETMNTINFO) && !defined (__NetBSD__) +#if MOUNTED_GETMNTINFO + +# if ! HAVE_F_FSTYPENAME_IN_STATFS static char * -fstype_to_string (t) - short t; +fstype_to_string (short t) { switch (t) { - case MOUNT_UFS: - return "ufs"; - case MOUNT_NFS: - return "nfs"; -#ifdef MOUNT_PC +# ifdef MOUNT_PC case MOUNT_PC: return "pc"; -#endif -#ifdef MOUNT_MFS +# endif +# ifdef MOUNT_MFS case MOUNT_MFS: return "mfs"; -#endif -#ifdef MOUNT_LO +# endif +# ifdef MOUNT_LO case MOUNT_LO: return "lo"; -#endif -#ifdef MOUNT_TFS +# endif +# ifdef MOUNT_TFS case MOUNT_TFS: return "tfs"; -#endif -#ifdef MOUNT_TMP +# endif +# ifdef MOUNT_TMP case MOUNT_TMP: return "tmp"; -#endif +# endif +# ifdef MOUNT_UFS + case MOUNT_UFS: + return "ufs" ; +# endif +# ifdef MOUNT_NFS + case MOUNT_NFS: + return "nfs" ; +# endif +# ifdef MOUNT_MSDOS + case MOUNT_MSDOS: + return "msdos" ; +# endif +# ifdef MOUNT_LFS + case MOUNT_LFS: + return "lfs" ; +# endif +# ifdef MOUNT_LOFS + case MOUNT_LOFS: + return "lofs" ; +# endif +# ifdef MOUNT_FDESC + case MOUNT_FDESC: + return "fdesc" ; +# endif +# ifdef MOUNT_PORTAL + case MOUNT_PORTAL: + return "portal" ; +# endif +# ifdef MOUNT_NULL + case MOUNT_NULL: + return "null" ; +# endif +# ifdef MOUNT_UMAP + case MOUNT_UMAP: + return "umap" ; +# endif +# ifdef MOUNT_KERNFS + case MOUNT_KERNFS: + return "kernfs" ; +# endif +# ifdef MOUNT_PROCFS + case MOUNT_PROCFS: + return "procfs" ; +# endif +# ifdef MOUNT_AFS + case MOUNT_AFS: + return "afs" ; +# endif +# ifdef MOUNT_CD9660 + case MOUNT_CD9660: + return "cd9660" ; +# endif +# ifdef MOUNT_UNION + case MOUNT_UNION: + return "union" ; +# endif +# ifdef MOUNT_DEVFS + case MOUNT_DEVFS: + return "devfs" ; +# endif +# ifdef MOUNT_EXT2FS + case MOUNT_EXT2FS: + return "ext2fs" ; +# endif default: return "?"; } } +# endif /* ! HAVE_F_FSTYPENAME_IN_STATFS */ + +/* __NetBSD__ || BSD_NET2 || __OpenBSD__ */ +static char * +fsp_to_string (const struct statfs *fsp) +{ +# if defined HAVE_F_FSTYPENAME_IN_STATFS + return fsp->f_fstypename; +# else + return fstype_to_string (fsp->f_type); +# endif +} + #endif /* MOUNTED_GETMNTINFO */ #ifdef MOUNTED_VMOUNT /* AIX. */ static char * -fstype_to_string (t) - int t; +fstype_to_string (int t) { struct vfs_ent *e; @@ -182,29 +281,21 @@ fstype_to_string (t) /* Return a list of the currently mounted filesystems, or NULL on error. Add each entry to the tail of the list so that they stay in order. If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in - the returned list are valid. Otherwise, they might not be. - If ALL_FS is zero, do not return entries for filesystems that - are automounter (dummy) entries. */ + the returned list are valid. Otherwise, they might not be. */ struct mount_entry * -read_filesystem_list (need_fs_type, all_fs) - int need_fs_type, all_fs; +read_filesystem_list (int need_fs_type) { struct mount_entry *mount_list; struct mount_entry *me; - struct mount_entry *mtail; - - /* Start the list off with a dummy entry. */ - me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); - me->me_next = NULL; - mount_list = mtail = me; + struct mount_entry **mtail = &mount_list; #ifdef MOUNTED_LISTMNTENT { struct tabmntent *mntlist, *p; struct mntent *mnt; struct mount_entry *me; - + /* the third and fourth arguments could be used to filter mounts, but Crays doesn't seem to have any mounts that we want to remove. Specifically, automount create normal NFS mounts. @@ -212,18 +303,17 @@ read_filesystem_list (need_fs_type, all_fs) if(listmntent(&mntlist, KMTAB, NULL, NULL) < 0) return NULL; - p = mntlist; - while(p){ + for (p = mntlist; p; p = p->next) { mnt = p->ment; me = (struct mount_entry*) xmalloc(sizeof (struct mount_entry)); me->me_devname = xstrdup(mnt->mnt_fsname); me->me_mountdir = xstrdup(mnt->mnt_dir); me->me_type = xstrdup(mnt->mnt_type); + 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; - me->me_next = NULL; - mtail->me_next = me; - mtail = me; - p = p->next; + *mtail = me; + mtail = &me->me_next; } freemntlist(mntlist); } @@ -242,14 +332,12 @@ read_filesystem_list (need_fs_type, all_fs) while ((mnt = getmntent (fp))) { - if (!all_fs && (!strcmp (mnt->mnt_type, "ignore") - || !strcmp (mnt->mnt_type, "auto"))) - continue; - me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); me->me_devname = xstrdup (mnt->mnt_fsname); me->me_mountdir = xstrdup (mnt->mnt_dir); me->me_type = xstrdup (mnt->mnt_type); + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); devopt = strstr (mnt->mnt_opts, "dev="); if (devopt) { @@ -260,15 +348,14 @@ read_filesystem_list (need_fs_type, all_fs) } else me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - me->me_next = NULL; /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } if (endmntent (fp) == 0) - return NULL; + goto free_then_fail; } #endif /* MOUNTED_GETMNTENT1. */ @@ -280,23 +367,21 @@ read_filesystem_list (need_fs_type, all_fs) entries = getmntinfo (&fsp, MNT_NOWAIT); if (entries < 0) return NULL; - while (entries-- > 0) + for (; entries-- > 0; fsp++) { + char *fs_type = fsp_to_string (fsp); + me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); me->me_devname = xstrdup (fsp->f_mntfromname); me->me_mountdir = xstrdup (fsp->f_mntonname); -#ifdef __NetBSD__ - me->me_type = xstrdup (fsp->f_fstypename); -#else - me->me_type = fstype_to_string (fsp->f_type); -#endif + me->me_type = fs_type; + 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. */ - me->me_next = NULL; /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - fsp++; + *mtail = me; + mtail = &me->me_next; } } #endif /* MOUNTED_GETMNTINFO */ @@ -307,22 +392,24 @@ read_filesystem_list (need_fs_type, all_fs) int val; struct fs_data fsd; - while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, - (char *) 0)) > 0) + while (errno = 0, + 0 <= (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, + (char *) 0))) { me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); me->me_devname = xstrdup (fsd.fd_req.devname); me->me_mountdir = xstrdup (fsd.fd_req.path); me->me_type = gt_names[fsd.fd_req.fstype]; + 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 = fsd.fd_req.dev; - me->me_next = NULL; /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } if (val < 0) - return NULL; + goto free_then_fail; } #endif /* MOUNTED_GETMNT. */ @@ -351,12 +438,13 @@ read_filesystem_list (need_fs_type, all_fs) me->me_devname = xstrdup (stats[counter].f_mntfromname); me->me_mountdir = xstrdup (stats[counter].f_mntonname); me->me_type = mnt_names[stats[counter].f_type]; + 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. */ - me->me_next = NULL; /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } free (stats); @@ -376,17 +464,17 @@ read_filesystem_list (need_fs_type, all_fs) while (fread (&mnt, sizeof mnt, 1, fp) > 0) { me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); -#ifdef GETFSTYP /* SVR3. */ +# ifdef GETFSTYP /* SVR3. */ me->me_devname = xstrdup (mnt.mt_dev); -#else +# else me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6); strcpy (me->me_devname, "/dev/"); strcpy (me->me_devname + 5, mnt.mt_dev); -#endif +# endif me->me_mountdir = xstrdup (mnt.mt_filsys); me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ me->me_type = ""; -#ifdef GETFSTYP /* SVR3. */ +# ifdef GETFSTYP /* SVR3. */ if (need_fs_type) { struct statfs fsd; @@ -396,16 +484,25 @@ read_filesystem_list (need_fs_type, all_fs) && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) me->me_type = xstrdup (typebuf); } -#endif - me->me_next = NULL; +# endif + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; + } + + if (ferror (fp)) + { + int saved_errno = errno; + fclose (fp); + errno = saved_errno; + goto free_then_fail; } if (fclose (fp) == EOF) - return NULL; + goto free_then_fail; } #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ @@ -418,12 +515,13 @@ read_filesystem_list (need_fs_type, all_fs) me->me_devname = xstrdup ( (*ent)->mt_resource); me->me_mountdir = xstrdup( (*ent)->mt_directory); me->me_type = xstrdup ((*ent)->mt_fstype); + 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. */ - me->me_next = NULL; /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } endmnttbl(); } @@ -435,29 +533,69 @@ read_filesystem_list (need_fs_type, all_fs) char *table = MNTTAB; FILE *fp; int ret; + int lockfd = -1; + +# if defined F_RDLCK && defined F_SETLKW + /* MNTTAB_LOCK is a macro name of our own invention; it's not present in + e.g. Solaris 2.6. If the SVR4 folks ever define a macro + for this file name, we should use their macro name instead. + (Why not just lock MNTTAB directly? We don't know.) */ +# ifndef MNTTAB_LOCK +# define MNTTAB_LOCK "/etc/.mnttab.lock" +# endif + lockfd = open (MNTTAB_LOCK, O_RDONLY); + if (0 <= lockfd) + { + struct flock flock; + flock.l_type = F_RDLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + while (fcntl (lockfd, F_SETLKW, &flock) == -1) + if (errno != EINTR) + { + int saved_errno = errno; + close (lockfd); + errno = saved_errno; + return NULL; + } + } + else if (errno != ENOENT) + return NULL; +# endif + errno = 0; fp = fopen (table, "r"); if (fp == NULL) - return NULL; - - while ((ret = getmntent (fp, &mnt)) == 0) + ret = errno; + else { - me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); - me->me_devname = xstrdup (mnt.mnt_special); - me->me_mountdir = xstrdup (mnt.mnt_mountp); - me->me_type = xstrdup (mnt.mnt_fstype); - me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - me->me_next = NULL; + while ((ret = getmntent (fp, &mnt)) == 0) + { + me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); + me->me_devname = xstrdup (mnt.mnt_special); + me->me_mountdir = xstrdup (mnt.mnt_mountp); + me->me_type = xstrdup (mnt.mnt_fstype); + me->me_dummy = MNT_IGNORE (&mnt) != 0; + 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; + } - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1; } - if (ret > 0) - return NULL; - if (fclose (fp) == EOF) - return NULL; + if (0 <= lockfd && close (lockfd) != 0) + ret = errno; + + if (0 <= ret) + { + errno = ret; + goto free_then_fail; + } } #endif /* MOUNTED_GETMNTENT2. */ @@ -483,6 +621,7 @@ read_filesystem_list (need_fs_type, all_fs) { char *host, *path; + me->me_remote = 1; /* Prepend the remote pathname. */ host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; @@ -493,25 +632,43 @@ read_filesystem_list (need_fs_type, all_fs) } else { + me->me_remote = 0; me->me_devname = xstrdup (thisent + vmp->vmt_data[VMT_OBJECT].vmt_off); } me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */ - me->me_next = NULL; /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; + *mtail = me; + mtail = &me->me_next; } free (entries); } #endif /* MOUNTED_VMOUNT. */ - /* Free the dummy head. */ - me = mount_list; - mount_list = mount_list->me_next; - free (me); + *mtail = NULL; return mount_list; + + + free_then_fail: + { + int saved_errno = errno; + *mtail = NULL; + + while (mount_list) + { + me = mount_list->me_next; + free (mount_list->me_devname); + free (mount_list->me_mountdir); + /* FIXME: me_type is not always malloced. */ + free (mount_list); + mount_list = me; + } + + errno = saved_errno; + return NULL; + } }