From: Steve Dickson Date: Mon, 27 Sep 2010 13:35:26 +0000 (-0400) Subject: libnfs.a: Remove support/nfs/fstab.c X-Git-Tag: nfs-utils-1-2-3~13 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=5341111d4b34bcd1b1263d5ed215cbe375aa9314;p=nfs-utils.git libnfs.a: Remove support/nfs/fstab.c Signed-off-by: Steve Dickson --- diff --git a/support/nfs/fstab.c b/support/nfs/fstab.c deleted file mode 100644 index b4f8710..0000000 --- a/support/nfs/fstab.c +++ /dev/null @@ -1,554 +0,0 @@ -/* 1999-02-22 Arkadiusz Mi¶kiewicz - * - added Native Language Support - * Sun Mar 21 1999 - Arnaldo Carvalho de Melo - * - fixed strerr(errno) in gettext calls - * - * 2006-06-08 Amit Gud - * - Moved code to nfs-utils/support/nfs from util-linux/mount. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "fstab.h" -#include "xcommon.h" -#include "nfs_mntent.h" -#include "nfs_paths.h" -#include "nls.h" - -#define LOCK_TIMEOUT 10 -#define streq(s, t) (strcmp ((s), (t)) == 0) -#define PROC_MOUNTS "/proc/mounts" - -extern int verbose; - -/* Information about mtab. ------------------------------------*/ -static int have_mtab_info = 0; -static int var_mtab_does_not_exist = 0; -static int var_mtab_is_a_symlink = 0; - -static void -get_mtab_info(void) { - struct stat mtab_stat; - - if (!have_mtab_info) { - if (lstat(MOUNTED, &mtab_stat)) - var_mtab_does_not_exist = 1; - else if (S_ISLNK(mtab_stat.st_mode)) - var_mtab_is_a_symlink = 1; - have_mtab_info = 1; - } -} - -int -mtab_does_not_exist(void) { - get_mtab_info(); - return var_mtab_does_not_exist; -} - -static int -mtab_is_a_symlink(void) { - get_mtab_info(); - return var_mtab_is_a_symlink; -} - -int -mtab_is_writable() { - int fd; - - /* Should we write to /etc/mtab upon an update? - Probably not if it is a symlink to /proc/mounts, since that - would create a file /proc/mounts in case the proc filesystem - is not mounted. */ - if (mtab_is_a_symlink()) - return 0; - - fd = open(MOUNTED, O_RDWR | O_CREAT, 0644); - if (fd >= 0) { - close(fd); - return 1; - } else - return 0; -} - -/* Contents of mtab and fstab ---------------------------------*/ - -struct mntentchn mounttable; -static int got_mtab = 0; -struct mntentchn fstab; -static int got_fstab = 0; - -static void read_mounttable(void); -static void read_fstab(void); - -static struct mntentchn * -mtab_head(void) { - if (!got_mtab) - read_mounttable(); - return &mounttable; -} - -static struct mntentchn * -fstab_head(void) -{ - if (!got_fstab) - read_fstab(); - return &fstab; -} - -#if 0 -static void -my_free(const void *s) { - if (s) - free((void *) s); -} - -static void -discard_mntentchn(struct mntentchn *mc0) { - struct mntentchn *mc, *mc1; - - for (mc = mc0->nxt; mc && mc != mc0; mc = mc1) { - mc1 = mc->nxt; - my_free(mc->m.mnt_fsname); - my_free(mc->m.mnt_dir); - my_free(mc->m.mnt_type); - my_free(mc->m.mnt_opts); - free(mc); - } -} -#endif - -static void -read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) { - struct mntentchn *mc = mc0; - struct mntent *mnt; - - while ((mnt = nfs_getmntent(mfp)) != NULL) { - if (!streq(mnt->mnt_type, MNTTYPE_IGNORE)) { - mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc)); - mc->nxt->prev = mc; - mc = mc->nxt; - mc->m = *mnt; - mc->nxt = mc0; - } - } - mc0->prev = mc; - if (ferror(mfp->mntent_fp)) { - int errsv = errno; - nfs_error(_("warning: error reading %s: %s"), - fnam, strerror (errsv)); - mc0->nxt = mc0->prev = NULL; - } - nfs_endmntent(mfp); -} - -/* - * Read /etc/mtab. If that fails, try /proc/mounts. - * This produces a linked list. The list head mounttable is a dummy. - * Return 0 on success. - */ -static void -read_mounttable() { - mntFILE *mfp; - const char *fnam; - struct mntentchn *mc = &mounttable; - - got_mtab = 1; - mc->nxt = mc->prev = NULL; - - fnam = MOUNTED; - mfp = nfs_setmntent (fnam, "r"); - if (mfp == NULL || mfp->mntent_fp == NULL) { - int errsv = errno; - fnam = PROC_MOUNTS; - mfp = nfs_setmntent (fnam, "r"); - if (mfp == NULL || mfp->mntent_fp == NULL) { - nfs_error(_("warning: can't open %s: %s"), - MOUNTED, strerror (errsv)); - return; - } - if (verbose) - printf (_("mount: could not open %s - " - "using %s instead\n"), - MOUNTED, PROC_MOUNTS); - } - read_mntentchn(mfp, fnam, mc); -} - -static void -read_fstab() -{ - mntFILE *mfp = NULL; - const char *fnam; - struct mntentchn *mc = &fstab; - - got_fstab = 1; - mc->nxt = mc->prev = NULL; - - fnam = _PATH_FSTAB; - mfp = nfs_setmntent (fnam, "r"); - if (mfp == NULL || mfp->mntent_fp == NULL) { - int errsv = errno; - nfs_error(_("warning: can't open %s: %s"), - _PATH_FSTAB, strerror (errsv)); - return; - } - read_mntentchn(mfp, fnam, mc); -} - -/* - * Given the directory name NAME, and the place MCPREV we found it last time, - * try to find more occurrences. - */ -struct mntentchn * -getmntdirbackward (const char *name, struct mntentchn *mcprev) { - struct mntentchn *mc, *mc0; - - mc0 = mtab_head(); - if (!mcprev) - mcprev = mc0; - for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) - if (streq(mc->m.mnt_dir, name)) - return mc; - return NULL; -} - -/* - * Given the device name NAME, and the place MCPREV we found it last time, - * try to find more occurrences. - */ -struct mntentchn * -getmntdevbackward (const char *name, struct mntentchn *mcprev) { - struct mntentchn *mc, *mc0; - - mc0 = mtab_head(); - if (!mcprev) - mcprev = mc0; - for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) - if (streq(mc->m.mnt_fsname, name)) - return mc; - return NULL; -} - -/* Find the dir FILE in fstab. */ -struct mntentchn * -getfsfile (const char *file) -{ - struct mntentchn *mc, *mc0; - - mc0 = fstab_head(); - for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) - if (streq(mc->m.mnt_dir, file)) - return mc; - return NULL; -} - -/* Find the device SPEC in fstab. */ -struct mntentchn * -getfsspec (const char *spec) -{ - struct mntentchn *mc, *mc0; - - mc0 = fstab_head(); - for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) - if (streq(mc->m.mnt_fsname, spec)) - return mc; - return NULL; -} - -/* Updating mtab ----------------------------------------------*/ - -/* Flag for already existing lock file. */ -static int we_created_lockfile = 0; -static int lockfile_fd = -1; - -/* Flag to indicate that signals have been set up. */ -static int signals_have_been_setup = 0; - -/* Ensure that the lock is released if we are interrupted. */ -extern char *strsignal(int sig); /* not always in */ - -static void -handler (int sig) { - die(EX_USER, "%s", strsignal(sig)); -} - -static void -setlkw_timeout (int sig) { - /* nothing, fcntl will fail anyway */ -} - -/* Remove lock file. */ -void -unlock_mtab (void) { - if (we_created_lockfile) { - close(lockfile_fd); - lockfile_fd = -1; - unlink (MOUNTED_LOCK); - we_created_lockfile = 0; - } -} - -/* Create the lock file. - The lock file will be removed if we catch a signal or when we exit. */ -/* The old code here used flock on a lock file /etc/mtab~ and deleted - this lock file afterwards. However, as rgooch remarks, that has a - race: a second mount may be waiting on the lock and proceed as - soon as the lock file is deleted by the first mount, and immediately - afterwards a third mount comes, creates a new /etc/mtab~, applies - flock to that, and also proceeds, so that the second and third mount - now both are scribbling in /etc/mtab. - The new code uses a link() instead of a creat(), where we proceed - only if it was us that created the lock, and hence we always have - to delete the lock afterwards. Now the use of flock() is in principle - superfluous, but avoids an arbitrary sleep(). */ - -/* Where does the link point to? Obvious choices are mtab and mtab~~. - HJLu points out that the latter leads to races. Right now we use - mtab~. instead. Use 20 as upper bound for the length of %d. */ -#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d" -#define MOUNTLOCK_LINKTARGET_LTH (sizeof(MOUNTED_LOCK)+20) - -void -lock_mtab (void) { - int tries = 100000, i; - char linktargetfile[MOUNTLOCK_LINKTARGET_LTH]; - - at_die = unlock_mtab; - - if (!signals_have_been_setup) { - int sig = 0; - struct sigaction sa; - - sa.sa_handler = handler; - sa.sa_flags = 0; - sigfillset (&sa.sa_mask); - - while (sigismember (&sa.sa_mask, ++sig) != -1 - && sig != SIGCHLD) { - if (sig == SIGALRM) - sa.sa_handler = setlkw_timeout; - else - sa.sa_handler = handler; - sigaction (sig, &sa, (struct sigaction *) 0); - } - signals_have_been_setup = 1; - } - - sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ()); - - i = open (linktargetfile, O_WRONLY|O_CREAT, 0); - if (i < 0) { - int errsv = errno; - /* linktargetfile does not exist (as a file) - and we cannot create it. Read-only filesystem? - Too many files open in the system? - Filesystem full? */ - die (EX_FILEIO, _("can't create lock file %s: %s " - "(use -n flag to override)"), - linktargetfile, strerror (errsv)); - } - close(i); - - /* Repeat until it was us who made the link */ - while (!we_created_lockfile) { - struct flock flock; - int errsv, j; - - j = link(linktargetfile, MOUNTED_LOCK); - errsv = errno; - - if (j == 0) - we_created_lockfile = 1; - - if (j < 0 && errsv != EEXIST) { - (void) unlink(linktargetfile); - die (EX_FILEIO, _("can't link lock file %s: %s " - "(use -n flag to override)"), - MOUNTED_LOCK, strerror (errsv)); - } - - lockfile_fd = open (MOUNTED_LOCK, O_WRONLY); - - if (lockfile_fd < 0) { - int errsv = errno; - /* Strange... Maybe the file was just deleted? */ - if (errno == ENOENT && tries-- > 0) { - if (tries % 200 == 0) - usleep(30); - continue; - } - (void) unlink(linktargetfile); - die (EX_FILEIO, _("can't open lock file %s: %s " - "(use -n flag to override)"), - MOUNTED_LOCK, strerror (errsv)); - } - - flock.l_type = F_WRLCK; - flock.l_whence = SEEK_SET; - flock.l_start = 0; - flock.l_len = 0; - - if (j == 0) { - /* We made the link. Now claim the lock. */ - if (fcntl (lockfile_fd, F_SETLK, &flock) == -1) { - if (verbose) { - int errsv = errno; - printf(_("Can't lock lock file %s: %s\n"), - MOUNTED_LOCK, strerror (errsv)); - } - /* proceed anyway */ - } - (void) unlink(linktargetfile); - } else { - static int tries = 0; - - /* Someone else made the link. Wait. */ - alarm(LOCK_TIMEOUT); - if (fcntl (lockfile_fd, F_SETLKW, &flock) == -1) { - int errsv = errno; - (void) unlink(linktargetfile); - die (EX_FILEIO, _("can't lock lock file %s: %s"), - MOUNTED_LOCK, (errno == EINTR) ? - _("timed out") : strerror (errsv)); - } - alarm(0); - /* Limit the number of iterations - maybe there - still is some old /etc/mtab~ */ - ++tries; - if (tries % 200 == 0) - usleep(30); - if (tries > 100000) { - (void) unlink(linktargetfile); - close(lockfile_fd); - die (EX_FILEIO, _("Cannot create link %s\n" - "Perhaps there is a stale lock file?\n"), - MOUNTED_LOCK); - } - close(lockfile_fd); - } - } -} - -/* - * Update the mtab. - * Used by umount with null INSTEAD: remove the last DIR entry. - * Used by mount upon a remount: update option part, - * and complain if a wrong device or type was given. - * [Note that often a remount will be a rw remount of / - * where there was no entry before, and we'll have to believe - * the values given in INSTEAD.] - */ - -void -update_mtab (const char *dir, struct mntent *instead) -{ - mntFILE *mfp, *mftmp; - const char *fnam = MOUNTED; - struct mntentchn mtabhead; /* dummy */ - struct mntentchn *mc, *mc0, *absent = NULL; - - if (mtab_does_not_exist() || !mtab_is_writable()) - return; - - lock_mtab(); - - /* having locked mtab, read it again */ - mc0 = mc = &mtabhead; - mc->nxt = mc->prev = NULL; - - mfp = nfs_setmntent(fnam, "r"); - if (mfp == NULL || mfp->mntent_fp == NULL) { - int errsv = errno; - nfs_error (_("cannot open %s (%s) - mtab not updated"), - fnam, strerror (errsv)); - goto leave; - } - - read_mntentchn(mfp, fnam, mc); - - /* find last occurrence of dir */ - for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev) - if (streq(mc->m.mnt_dir, dir)) - break; - if (mc && mc != mc0) { - if (instead == NULL) { - /* An umount - remove entry */ - if (mc && mc != mc0) { - mc->prev->nxt = mc->nxt; - mc->nxt->prev = mc->prev; - free(mc); - } - } else { - /* A remount */ - mc->m.mnt_opts = instead->mnt_opts; - } - } else if (instead) { - /* not found, add a new entry */ - absent = xmalloc(sizeof(*absent)); - absent->m = *instead; - absent->nxt = mc0; - absent->prev = mc0->prev; - mc0->prev = absent; - if (mc0->nxt == NULL) - mc0->nxt = absent; - } - - /* write chain to mtemp */ - mftmp = nfs_setmntent (MOUNTED_TEMP, "w"); - if (mftmp == NULL || mftmp->mntent_fp == NULL) { - int errsv = errno; - nfs_error (_("cannot open %s (%s) - mtab not updated"), - MOUNTED_TEMP, strerror (errsv)); - goto leave; - } - - for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { - if (nfs_addmntent(mftmp, &(mc->m)) == 1) { - int errsv = errno; - die (EX_FILEIO, _("error writing %s: %s"), - MOUNTED_TEMP, strerror (errsv)); - } - } - -#if 0 - /* the chain might have strings copied from 'instead', - * so we cannot safely free it. - * And there is no need anyway because we are going to exit - * shortly. So just don't call discard_mntentchn.... - */ - discard_mntentchn(mc0); -#endif - if (fchmod (fileno (mftmp->mntent_fp), - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { - int errsv = errno; - fprintf(stderr, _("error changing mode of %s: %s\n"), - MOUNTED_TEMP, strerror (errsv)); - } - nfs_endmntent (mftmp); - - { /* - * If mount is setuid and some non-root user mounts sth, - * then mtab.tmp might get the group of this user. Copy uid/gid - * from the present mtab before renaming. - */ - struct stat sbuf; - if (stat (MOUNTED, &sbuf) == 0) - chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid); - } - - /* rename mtemp to mtab */ - if (rename (MOUNTED_TEMP, MOUNTED) < 0) { - int errsv = errno; - fprintf(stderr, _("can't rename %s to %s: %s\n"), - MOUNTED_TEMP, MOUNTED, strerror(errsv)); - } - - leave: - unlock_mtab(); -}