X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmountlist.c;h=138fd227267b1aba48c432da3c5862a11ecca0c3;hb=c6cb26ec2993800dda1b95c213fc4539acd4fa51;hp=68a07cb7c44e0d41feef871e7f22828a50d03928;hpb=67f394c1d2be473276ccd5e071f986511a13e212;p=gnulib.git diff --git a/lib/mountlist.c b/lib/mountlist.c index 68a07cb7c..138fd2272 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, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1997, 1998, 1999 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 @@ -42,6 +42,19 @@ char *xrealloc (); char *xstrdup (); void error (); +#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 @@ -116,10 +129,10 @@ void error (); /* 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; @@ -140,107 +153,120 @@ xatoi (cp) } #endif /* MOUNTED_GETMNTENT1. */ -#if defined (MOUNTED_GETMNTINFO) && !defined (__NetBSD__) && !defined (__OpenBSD__) +#if MOUNTED_GETMNTINFO + +# if ! HAVE_F_FSTYPENAME_IN_STATFS static char * -fstype_to_string (t) - short t; +fstype_to_string (short t) { switch (t) { -# 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 -# ifdef MOUNT_UFS +# endif +# ifdef MOUNT_UFS case MOUNT_UFS: return "ufs" ; -# endif -# ifdef MOUNT_NFS +# endif +# ifdef MOUNT_NFS case MOUNT_NFS: return "nfs" ; -# endif -# ifdef MOUNT_MSDOS +# endif +# ifdef MOUNT_MSDOS case MOUNT_MSDOS: return "msdos" ; -# endif -# ifdef MOUNT_LFS +# endif +# ifdef MOUNT_LFS case MOUNT_LFS: return "lfs" ; -# endif -# ifdef MOUNT_LOFS +# endif +# ifdef MOUNT_LOFS case MOUNT_LOFS: return "lofs" ; -# endif -# ifdef MOUNT_FDESC +# endif +# ifdef MOUNT_FDESC case MOUNT_FDESC: return "fdesc" ; -# endif -# ifdef MOUNT_PORTAL +# endif +# ifdef MOUNT_PORTAL case MOUNT_PORTAL: return "portal" ; -# endif -# ifdef MOUNT_NULL +# endif +# ifdef MOUNT_NULL case MOUNT_NULL: return "null" ; -# endif -# ifdef MOUNT_UMAP +# endif +# ifdef MOUNT_UMAP case MOUNT_UMAP: return "umap" ; -# endif -# ifdef MOUNT_KERNFS +# endif +# ifdef MOUNT_KERNFS case MOUNT_KERNFS: return "kernfs" ; -# endif -# ifdef MOUNT_PROCFS +# endif +# ifdef MOUNT_PROCFS case MOUNT_PROCFS: return "procfs" ; -# endif -# ifdef MOUNT_AFS +# endif +# ifdef MOUNT_AFS case MOUNT_AFS: return "afs" ; -# endif -# ifdef MOUNT_CD9660 +# endif +# ifdef MOUNT_CD9660 case MOUNT_CD9660: return "cd9660" ; -# endif -# ifdef MOUNT_UNION +# endif +# ifdef MOUNT_UNION case MOUNT_UNION: return "union" ; -# endif -# ifdef MOUNT_DEVFS +# endif +# ifdef MOUNT_DEVFS case MOUNT_DEVFS: return "devfs" ; -# endif -# ifdef MOUNT_EXT2FS +# endif +# ifdef MOUNT_EXT2FS case MOUNT_EXT2FS: return "ext2fs" ; -# endif +# 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; @@ -255,22 +281,14 @@ 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 { @@ -285,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); } @@ -315,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) { @@ -333,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. */ @@ -353,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); -# if defined (__NetBSD__) || defined (__OpenBSD__) - 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 */ @@ -380,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. */ @@ -424,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); @@ -470,15 +485,24 @@ read_filesystem_list (need_fs_type, all_fs) me->me_type = xstrdup (typebuf); } # endif - me->me_next = NULL; + 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. */ @@ -491,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(); } @@ -508,33 +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 { - /* Don't show automounted filesystems twice on e.g., Solaris. */ - if (!all_fs && MNT_IGNORE (&mnt)) - continue; - - 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. */ @@ -560,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; @@ -570,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; + } }