[Ocfs2-tools-commits] smushran commits r642 - trunk/mount.ocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Tue Mar 15 17:25:40 CST 2005
Author: smushran
Signed-off-by: mfasheh
Date: 2005-03-15 17:25:37 -0600 (Tue, 15 Mar 2005)
New Revision: 642
Added:
trunk/mount.ocfs2/CREDITS
trunk/mount.ocfs2/fstab.c
trunk/mount.ocfs2/fstab.h
trunk/mount.ocfs2/get_label_uuid.c
trunk/mount.ocfs2/get_label_uuid.h
trunk/mount.ocfs2/linux_fs.h
trunk/mount.ocfs2/mntent.c
trunk/mount.ocfs2/mntent.h
trunk/mount.ocfs2/mount.ocfs2.h
trunk/mount.ocfs2/mount_constants.h
trunk/mount.ocfs2/nls.h
trunk/mount.ocfs2/opts.c
trunk/mount.ocfs2/opts.h
trunk/mount.ocfs2/realpath.c
trunk/mount.ocfs2/realpath.h
trunk/mount.ocfs2/sundries.c
trunk/mount.ocfs2/sundries.h
Modified:
trunk/mount.ocfs2/Cscope.make
trunk/mount.ocfs2/Makefile
trunk/mount.ocfs2/mount.ocfs2.c
Log:
mount now handles arguments and /etc/mtab
Signed-off-by: mfasheh
Added: trunk/mount.ocfs2/CREDITS
===================================================================
--- trunk/mount.ocfs2/CREDITS 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/CREDITS 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,14 @@
+
+The following files have been copied from util-linux-2.12a/mount:
+ fstab.c/h
+ get_label_uuid.c/h
+ mntent.c/h
+ mount_constants.h
+ linux_fs.h
+ realpath.c/h
+ sundries.c/h
+
+The following files have code which has been copied from one or more files
+in util-linux-2.12a/mount:
+ opts.c/h
+ nls.h
Modified: trunk/mount.ocfs2/Cscope.make
===================================================================
--- trunk/mount.ocfs2/Cscope.make 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/Cscope.make 2005-03-15 23:25:37 UTC (rev 642)
@@ -3,7 +3,7 @@
rm -f cscope.*
echo "-k" >> cscope.files
echo "-I inc" >> cscope.files
- find . -maxdepth 2 -name '*.c' -print >>cscope.files
+ find . -maxdepth 2 -name '*.c' -print | grep -v group.c >>cscope.files
find . -maxdepth 2 -name '*.h' -print >>cscope.files
find ../libocfs2/ -maxdepth 2 -name '*.c' -print >>cscope.files
find ../libocfs2/ -maxdepth 2 -name '*.h' -print >>cscope.files
Modified: trunk/mount.ocfs2/Makefile
===================================================================
--- trunk/mount.ocfs2/Makefile 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/Makefile 2005-03-15 23:25:37 UTC (rev 642)
@@ -8,6 +8,8 @@
-I$(TOPDIR)/libo2cb/include -I$(TOPDIR)/libo2dlm/include
LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
+LIBO2DLM_LIBS = -L$(TOPDIR)/libo2dlm -lo2dlm
+LIBO2DLM_DEPS = $(TOPDIR)/libo2dlm/libo2dlm.a
ifdef OCFS_DEBUG
OPTS += -ggdb
@@ -18,16 +20,17 @@
CFLAGS := $(OPTS) -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wmissing-declarations
-DEFINES = -DOCFS2_FLAT_INCLUDES -DO2DLM_FLAT_INCLUDES
+DEFINES = -DOCFS2_FLAT_INCLUDES -DO2DLM_FLAT_INCLUDES -DVERSION=\"$(VERSION)\"
-CFILES = mount.ocfs2.c
+CFILES = opts.c mount.ocfs2.c
+CFILES += fstab.c get_label_uuid.c mntent.c sundries.c realpath.c
OBJS = $(subst .c,.o,$(CFILES))
DIST_FILES = $(CFILES)
-mount.ocfs2: $(OBJS) $(LIBOCFS2_DEPS)
- $(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+mount.ocfs2: $(OBJS) $(LIBOCFS2_DEPS) $(LIBO2DLM_DEPS)
+ $(LINK) $(LIBOCFS2_LIBS) $(LIBO2DLM_LIBS) $(COM_ERR_LIBS)
group: group.o $(LIBOCFS2_DEPS)
$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
Added: trunk/mount.ocfs2/fstab.c
===================================================================
--- trunk/mount.ocfs2/fstab.c 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/fstab.c 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,633 @@
+/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at pld.ORG.PL>
+ * - added Native Language Support
+ * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+ * - fixed strerr(errno) in gettext calls
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "mntent.h"
+#include "fstab.h"
+#include "sundries.h" /* for xmalloc() etc */
+#include "get_label_uuid.h"
+#include "nls.h"
+
+#define streq(s, t) (strcmp ((s), (t)) == 0)
+
+#define PROC_MOUNTS "/proc/mounts"
+
+
+/* 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;
+}
+
+int
+mtab_is_a_symlink(void) {
+ get_mtab_info();
+ return var_mtab_is_a_symlink;
+}
+
+int
+mtab_is_writable() {
+ static int ret = -1;
+
+ /* 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;
+
+ if (ret == -1) {
+ int fd = open(MOUNTED, O_RDWR | O_CREAT, 0644);
+ if (fd >= 0) {
+ close(fd);
+ ret = 1;
+ } else
+ ret = 0;
+ }
+ return ret;
+}
+
+/* Contents of mtab and fstab ---------------------------------*/
+
+struct mntentchn mounttable, fstab;
+static int got_mtab = 0;
+static int got_fstab = 0;
+
+static void read_mounttable(void), read_fstab(void);
+
+struct mntentchn *
+mtab_head() {
+ if (!got_mtab)
+ read_mounttable();
+ return &mounttable;
+}
+
+struct mntentchn *
+fstab_head() {
+ if (!got_fstab)
+ read_fstab();
+ return &fstab;
+}
+
+static void
+read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {
+ struct mntentchn *mc = mc0;
+ struct mntent *mnt;
+
+ while ((mnt = my_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;
+ error(_("warning: error reading %s: %s"),
+ fnam, strerror (errsv));
+ mc0->nxt = mc0->prev = NULL;
+ }
+ my_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 = my_setmntent (fnam, "r");
+ if (mfp == NULL || mfp->mntent_fp == NULL) {
+ int errsv = errno;
+ fnam = PROC_MOUNTS;
+ mfp = my_setmntent (fnam, "r");
+ if (mfp == NULL || mfp->mntent_fp == NULL) {
+ 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 = my_setmntent (fnam, "r");
+ if (mfp == NULL || mfp->mntent_fp == NULL) {
+ int errsv = errno;
+ error(_("warning: can't open %s: %s"),
+ _PATH_FSTAB, strerror (errsv));
+ return;
+ }
+ read_mntentchn(mfp, fnam, mc);
+}
+
+
+/* Given the name NAME, try to find it in mtab. */
+struct mntentchn *
+getmntfile (const char *name) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = mtab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (streq(mc->m.mnt_dir, name) ||
+ streq(mc->m.mnt_fsname, name))
+ return mc;
+ return NULL;
+}
+
+/*
+ * 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;
+}
+
+/*
+ * Given the name NAME, check that it occurs precisely once as dir or dev.
+ */
+int
+is_mounted_once(const char *name) {
+ struct mntentchn *mc, *mc0;
+ int ct = 0;
+
+ mc0 = mtab_head();
+ for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
+ if (streq(mc->m.mnt_dir, name) ||
+ streq(mc->m.mnt_fsname, name))
+ ct++;
+ return (ct == 1);
+}
+
+/* Given the name FILE, try to find the option "loop=FILE" in mtab. */
+struct mntentchn *
+getmntoptfile (const char *file) {
+ struct mntentchn *mc, *mc0;
+ char *opts, *s;
+ int l;
+
+ if (!file)
+ return NULL;
+
+ l = strlen(file);
+
+ mc0 = mtab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if ((opts = mc->m.mnt_opts) != NULL
+ && (s = strstr(opts, "loop="))
+ && !strncmp(s+5, file, l)
+ && (s == opts || s[-1] == ',')
+ && (s[l+5] == 0 || s[l+5] == ','))
+ return mc;
+ return NULL;
+}
+
+static int
+has_label(const char *device, const char *label) {
+ char devuuid[16];
+ char *devlabel;
+
+ return !get_label_uuid(device, &devlabel, devuuid) &&
+ !strcmp(label, devlabel);
+}
+
+static int
+has_uuid(const char *device, const char *uuid){
+ char devuuid[16];
+ char *devlabel;
+
+ return !get_label_uuid(device, &devlabel, devuuid) &&
+ !memcmp(uuid, devuuid, sizeof(devuuid));
+}
+
+/* Find the entry (SPEC,FILE) in fstab */
+struct mntentchn *
+getfsspecfile (const char *spec, const char *file) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = fstab_head();
+
+ /* first attempt: names occur precisely as given */
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (streq(mc->m.mnt_dir, file) &&
+ streq(mc->m.mnt_fsname, spec))
+ return mc;
+
+ /* second attempt: names found after symlink resolution */
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if ((streq(mc->m.mnt_dir, file) ||
+ streq(canonicalize(mc->m.mnt_dir), file))
+ && (streq(mc->m.mnt_fsname, spec) ||
+ streq(canonicalize(mc->m.mnt_fsname), spec)))
+ return mc;
+
+ /* third attempt: names found after LABEL= or UUID= resolution */
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
+ if (!strncmp (mc->m.mnt_fsname, "LABEL=", 6) &&
+ (streq(mc->m.mnt_dir, file) ||
+ streq(canonicalize(mc->m.mnt_dir), file))) {
+ if (has_label(spec, mc->m.mnt_fsname+6))
+ return mc;
+ }
+ if (!strncmp (mc->m.mnt_fsname, "UUID=", 5) &&
+ (streq(mc->m.mnt_dir, file) ||
+ streq(canonicalize(mc->m.mnt_dir), file))) {
+ if (has_uuid(spec, mc->m.mnt_fsname+5))
+ 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;
+}
+
+/* Find the uuid UUID in fstab. */
+struct mntentchn *
+getfsuuidspec (const char *uuid) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (strncmp (mc->m.mnt_fsname, "UUID=", 5) == 0
+ && streq(mc->m.mnt_fsname + 5, uuid))
+ return mc;
+ return NULL;
+}
+
+/* Find the label LABEL in fstab. */
+struct mntentchn *
+getfsvolspec (const char *label) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (strncmp (mc->m.mnt_fsname, "LABEL=", 6) == 0
+ && streq(mc->m.mnt_fsname + 6, label))
+ return mc;
+ return NULL;
+}
+
+/* Updating mtab ----------------------------------------------*/
+
+/* Flag for already existing lock file. */
+static int we_created_lockfile = 0;
+
+/* 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. */
+static void
+handler (int sig) {
+ die (EX_USER, "%s", sys_siglist[sig]);
+}
+
+static void
+setlkw_timeout (int sig) {
+ /* nothing, fcntl will fail anyway */
+}
+
+/* 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~.<pid> instead. */
+#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d"
+
+void
+lock_mtab (void) {
+ int tries = 3;
+ char *linktargetfile;
+
+ 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;
+ }
+
+ /* somewhat clumsy, but some ancient systems do not have snprintf() */
+ /* use 20 as upper bound for the length of %d output */
+ linktargetfile = xmalloc(strlen(MOUNTLOCK_LINKTARGET) + 20);
+ sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ());
+
+ /* Repeat until it was us who made the link */
+ while (!we_created_lockfile) {
+ struct flock flock;
+ int errsv, fd, i, j;
+
+ 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);
+
+ j = link(linktargetfile, MOUNTED_LOCK);
+ errsv = errno;
+
+ (void) unlink(linktargetfile);
+
+ if (j < 0 && errsv != EEXIST) {
+ die (EX_FILEIO, _("can't link lock file %s: %s "
+ "(use -n flag to override)"),
+ MOUNTED_LOCK, strerror (errsv));
+ }
+
+ fd = open (MOUNTED_LOCK, O_WRONLY);
+
+ if (fd < 0) {
+ int errsv = errno;
+ /* Strange... Maybe the file was just deleted? */
+ if (errno == ENOENT && tries-- > 0)
+ continue;
+ 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 (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 */
+ }
+ we_created_lockfile = 1;
+ } else {
+ static int tries = 0;
+
+ /* Someone else made the link. Wait. */
+ alarm(LOCK_TIMEOUT);
+ if (fcntl (fd, F_SETLKW, &flock) == -1) {
+ int errsv = errno;
+ 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~ */
+ if (tries++ > 3) {
+ if (tries > 5)
+ die (EX_FILEIO, _("Cannot create link %s\n"
+ "Perhaps there is a stale lock file?\n"),
+ MOUNTED_LOCK);
+ sleep(1);
+ }
+ }
+
+ close(fd);
+ }
+}
+
+/* Remove lock file. */
+void
+unlock_mtab (void) {
+ if (we_created_lockfile) {
+ unlink (MOUNTED_LOCK);
+ we_created_lockfile = 0;
+ }
+}
+
+/*
+ * 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;
+
+ if (mtab_does_not_exist() || mtab_is_a_symlink())
+ return;
+
+ lock_mtab();
+
+ /* having locked mtab, read it again */
+ mc0 = mc = &mtabhead;
+ mc->nxt = mc->prev = NULL;
+
+ mfp = my_setmntent(fnam, "r");
+ if (mfp == NULL || mfp->mntent_fp == NULL) {
+ int errsv = errno;
+ 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;
+ }
+ } else {
+ /* A remount */
+ mc->m.mnt_opts = instead->mnt_opts;
+ }
+ } else if (instead) {
+ /* not found, add a new entry */
+ 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 = my_setmntent (MOUNTED_TEMP, "w");
+ if (mftmp == NULL || mftmp->mntent_fp == NULL) {
+ int errsv = errno;
+ 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 (my_addmntent(mftmp, &(mc->m)) == 1) {
+ int errsv = errno;
+ die (EX_FILEIO, _("error writing %s: %s"),
+ MOUNTED_TEMP, strerror (errsv));
+ }
+ }
+
+ 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));
+ }
+ my_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();
+}
Added: trunk/mount.ocfs2/fstab.h
===================================================================
--- trunk/mount.ocfs2/fstab.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/fstab.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,38 @@
+#include <mntent.h>
+#define _PATH_FSTAB "/etc/fstab"
+#ifdef _PATH_MOUNTED
+#define MOUNTED_LOCK _PATH_MOUNTED "~"
+#define MOUNTED_TEMP _PATH_MOUNTED ".tmp"
+#else
+#define MOUNTED_LOCK "/etc/mtab~"
+#define MOUNTED_TEMP "/etc/mtab.tmp"
+#endif
+#define LOCK_TIMEOUT 10
+
+int mtab_is_writable(void);
+int mtab_does_not_exist(void);
+int mtab_is_a_symlink(void);
+int is_mounted_once(const char *name);
+
+struct mntentchn {
+ struct mntentchn *nxt, *prev;
+ struct mntent m;
+};
+
+struct mntentchn *mtab_head (void);
+struct mntentchn *getmntfile (const char *name);
+struct mntentchn *getmntoptfile (const char *file);
+struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc);
+struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc);
+
+struct mntentchn *fstab_head (void);
+struct mntentchn *getfsfile (const char *file);
+struct mntentchn *getfsspec (const char *spec);
+struct mntentchn *getfsspecfile (const char *spec, const char *file);
+struct mntentchn *getfsuuidspec (const char *uuid);
+struct mntentchn *getfsvolspec (const char *label);
+
+#include <mntent.h>
+void lock_mtab (void);
+void unlock_mtab (void);
+void update_mtab (const char *special, struct mntent *with);
Added: trunk/mount.ocfs2/get_label_uuid.c
===================================================================
--- trunk/mount.ocfs2/get_label_uuid.c 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/get_label_uuid.c 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,174 @@
+/*
+ * Get label. Used by both mount and umount.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "linux_fs.h"
+#include "get_label_uuid.h"
+
+/*
+ * See whether this device has (the magic of) a RAID superblock at the end.
+ * If so, it probably is, or has been, part of a RAID array.
+ *
+ * For the moment this test is switched off - it causes problems.
+ * "Checking for a disk label should only be done on the full raid,
+ * not on the disks that form the raid array. This test causes a lot of
+ * problems when run on my striped promise fasttrak 100 array."
+ */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define INT32_FROM_LE(val) ((unsigned int) ( \
+ (((unsigned int) (val) & (unsigned int) 0x000000ffU) << 24) | \
+ (((unsigned int) (val) & (unsigned int) 0x0000ff00U) << 8) | \
+ (((unsigned int) (val) & (unsigned int) 0x00ff0000U) >> 8) | \
+ (((unsigned int) (val) & (unsigned int) 0xff000000U) >> 24)))
+#else
+#define INT32_FROM_LE(val) (val)
+#endif
+
+typedef struct {
+ unsigned int md_magic;
+} mdp_super_t;
+#ifndef MD_SB_MAGIC
+#define MD_SB_MAGIC 0xa92b4efc
+#endif
+#ifndef MD_RESERVED_BYTES
+#define MD_RESERVED_BYTES 65536L
+#endif
+#ifndef MD_NEW_SIZE_BYTES
+#define MD_NEW_SIZE_BYTES(x) ((x & ~(MD_RESERVED_BYTES - 1L)) - MD_RESERVED_BYTES)
+#endif
+
+static int
+is_raid_partition(int fd)
+{
+ mdp_super_t mdsb;
+ int n;
+ struct stat sbuf;
+ if(fstat(fd, &sbuf))
+ return 2;
+ if(!sbuf.st_size) {
+ uint64_t bsize64;
+ unsigned int bsize32;
+ if(!ioctl(fd, BLKGETSIZE64, &bsize64))
+ sbuf.st_size = bsize64;
+ else if(!ioctl(fd, BLKGETSIZE, &bsize32))
+ sbuf.st_size = bsize32;
+ }
+ if(!sbuf.st_size) return 3;
+ /* hardcode 4096 here in various places,
+ because that's what it's defined to be.
+ Note that even if we used the actual kernel headers,
+ sizeof(mdp_super_t) is slightly larger in the 2.2 kernel on 64-bit
+ archs, so using that wouldn't work. */
+ lseek(fd, MD_NEW_SIZE_BYTES(sbuf.st_size), SEEK_SET);
+ n = 4096; if(sizeof(mdsb) < n) n = sizeof(mdsb);
+ if(read(fd, &mdsb, n) != n)
+ return 4; /* error */
+ mdsb.md_magic = INT32_FROM_LE(mdsb.md_magic);
+ return (mdsb.md_magic == MD_SB_MAGIC); /* If this device has a
+ RAID superblock at
+ the end, it must be
+ part of a RAID
+ array. */
+}
+
+/* for now, only ext2, ext3, xfs, ocfs are supported */
+int
+get_label_uuid(const char *device, char **label, char *uuid) {
+ int fd;
+ int rv = 1;
+ size_t namesize;
+ struct ext2_super_block e2sb;
+ struct xfs_super_block xfsb;
+ struct jfs_super_block jfssb;
+ struct ocfs_volume_header ovh; /* Oracle */
+ struct ocfs_volume_label olbl;
+ union {
+ struct swap_header_v1_2 hdr;
+ char swap_data[1<<16];
+ } swap_u;
+
+ fd = open(device, O_RDONLY);
+ if (fd < 0)
+ return rv;
+
+ /* If there is a RAID partition, or an error, ignore this partition */
+ if (is_raid_partition(fd)) {
+ close(fd);
+ return rv;
+ }
+
+ if(getpagesize() > sizeof(swap_u.swap_data)) {
+ errno = EFAULT;
+ return 1;
+ }
+
+ if (lseek(fd, 1024, SEEK_SET) == 1024
+ && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb)
+ && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) {
+ memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+ namesize = sizeof(e2sb.s_volume_name);
+ if ((*label = calloc(namesize + 1, 1)) != NULL)
+ memcpy(*label, e2sb.s_volume_name, namesize);
+ rv = 0;
+ }
+ else if (lseek(fd, 0, SEEK_SET) == 0
+ && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb)
+ && (strncmp(xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0)) {
+ memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
+ namesize = sizeof(xfsb.s_fname);
+ if ((*label = calloc(namesize + 1, 1)) != NULL)
+ memcpy(*label, xfsb.s_fname, namesize);
+ rv = 0;
+ }
+ else if (lseek(fd, 0, SEEK_SET) == 0
+ && read(fd, (char *) &ovh, sizeof(ovh)) == sizeof(ovh)
+ && (strncmp(ovh.signature, OCFS_MAGIC, sizeof(OCFS_MAGIC)) == 0)
+ && (lseek(fd, 512, SEEK_SET) == 512)
+ && read(fd, (char *) &olbl, sizeof(olbl)) == sizeof(olbl)) {
+ uuid[0] = '\0';
+ namesize = ocfslabellen(olbl);
+ if ((*label = calloc(namesize + 1, 1)) != NULL)
+ memcpy(*label, olbl.label, namesize);
+ rv = 0;
+ }
+ else if (lseek(fd, JFS_SUPER1_OFF, SEEK_SET) == JFS_SUPER1_OFF
+ && read(fd, (char *) &jfssb, sizeof(jfssb)) == sizeof(jfssb)
+ && (strncmp(jfssb.s_magic, JFS_MAGIC, 4) == 0)) {
+ if (assemble4le(jfssb.s_version) == 1) {
+ /* old (OS/2 compatible) jfs filesystems don't
+ have UUIDs and only have a very small label. */
+ memset(uuid, 0, 16);
+ namesize = sizeof(jfssb.s_fpack);
+ if ((*label = calloc(namesize + 1, 1)) != NULL)
+ memcpy(*label, jfssb.s_fpack, namesize);
+ } else {
+ memcpy(uuid, jfssb.s_uuid, sizeof(jfssb.s_uuid));
+ namesize = sizeof(jfssb.s_label);
+ if ((*label = calloc(namesize + 1, 1)) != NULL)
+ memcpy(*label, jfssb.s_label, namesize);
+ }
+ rv = 0;
+ }
+ else if (lseek(fd, 0, SEEK_SET) == 0
+ && read(fd, &swap_u, getpagesize()) == getpagesize()
+ && !strncmp(swap_u.swap_data+getpagesize()-10, "SWAPSPACE2", strlen("SWAPSPACE2"))) {
+ memcpy(uuid, swap_u.hdr.uuid, sizeof(swap_u.hdr.uuid));
+ if(label)
+ *label = swap_u.hdr.volume_name[0]?strndup(swap_u.hdr.volume_name, sizeof(swap_u.hdr.volume_name)):NULL;
+ rv = 0;
+ }
+
+
+ close(fd);
+ return rv;
+}
Added: trunk/mount.ocfs2/get_label_uuid.h
===================================================================
--- trunk/mount.ocfs2/get_label_uuid.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/get_label_uuid.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1 @@
+int get_label_uuid(const char *device, char **label, char *uuid);
Added: trunk/mount.ocfs2/linux_fs.h
===================================================================
--- trunk/mount.ocfs2/linux_fs.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/linux_fs.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,296 @@
+/* Including <linux/fs.h> became more and more painful.
+ Below a very abbreviated version of some declarations,
+ only designed to be able to check a magic number
+ in case no filesystem type was given. */
+
+#ifndef BLKGETSIZE
+#ifndef _IO
+/* pre-1.3.45 */
+#define BLKGETSIZE 0x1260 /* return device size */
+#else
+/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
+#define BLKGETSIZE _IO(0x12,96)
+#endif
+#endif
+
+#include <inttypes.h>
+#ifndef BLKGETSIZE64
+#include <sys/ioctl.h>
+#define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t))
+#endif
+
+#define MINIX_SUPER_MAGIC 0x137F /* minix v1, 14 char names */
+#define MINIX_SUPER_MAGIC2 0x138F /* minix v1, 30 char names */
+#define MINIX2_SUPER_MAGIC 0x2468 /* minix v2, 14 char names */
+#define MINIX2_SUPER_MAGIC2 0x2478 /* minix v2, 30 char names */
+struct minix_super_block {
+ u_char s_dummy[16];
+ u_char s_magic[2];
+};
+#define minixmagic(s) assemble2le(s.s_magic)
+
+#define ISODCL(from, to) (to - from + 1)
+#define ISO_STANDARD_ID "CD001"
+struct iso_volume_descriptor {
+ char type[ISODCL(1,1)]; /* 711 */
+ char id[ISODCL(2,6)];
+ char version[ISODCL(7,7)];
+ char data[ISODCL(8,2048)];
+};
+
+#define HS_STANDARD_ID "CDROM"
+struct hs_volume_descriptor {
+ char foo[ISODCL ( 1, 8)]; /* 733 */
+ char type[ISODCL ( 9, 9)]; /* 711 */
+ char id[ISODCL ( 10, 14)];
+ char version[ISODCL ( 15, 15)]; /* 711 */
+ char data[ISODCL(16,2048)];
+};
+
+#define EXT_SUPER_MAGIC 0x137D
+struct ext_super_block {
+ u_char s_dummy[56];
+ u_char s_magic[2];
+};
+#define extmagic(s) assemble2le(s.s_magic)
+
+#define EXT2_PRE_02B_MAGIC 0xEF51
+#define EXT2_SUPER_MAGIC 0xEF53
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
+struct ext2_super_block {
+ u_char s_dummy1[56];
+ u_char s_magic[2];
+ u_char s_dummy2[34];
+ u_char s_feature_compat[4];
+ u_char s_feature_incompat[4];
+ u_char s_feature_ro_compat[4];
+ u_char s_uuid[16];
+ u_char s_volume_name[16];
+ u_char s_dummy3[88];
+ u_char s_journal_inum[4]; /* ext3 only */
+};
+#define ext2magic(s) assemble2le(s.s_magic)
+
+struct reiserfs_super_block
+{
+ u_char s_block_count[4];
+ u_char s_free_blocks[4];
+ u_char s_root_block[4];
+ u_char s_journal_block[4];
+ u_char s_journal_dev[4];
+ u_char s_orig_journal_size[4];
+ u_char s_journal_trans_max[4];
+ u_char s_journal_block_count[4];
+ u_char s_journal_max_batch[4];
+ u_char s_journal_max_commit_age[4];
+ u_char s_journal_max_trans_age[4];
+ u_char s_blocksize[2];
+ u_char s_oid_maxsize[2];
+ u_char s_oid_cursize[2];
+ u_char s_state[2];
+ u_char s_magic[12];
+};
+#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
+#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
+#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
+/* the spot for the super in versions 3.5 - 3.5.10 (inclusive) */
+#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
+
+#define _XIAFS_SUPER_MAGIC 0x012FD16D
+struct xiafs_super_block {
+ u_char s_boot_segment[512]; /* 1st sector reserved for boot */
+ u_char s_dummy[60];
+ u_char s_magic[4];
+};
+#define xiafsmagic(s) assemble4le(s.s_magic)
+
+/* From jj at sunsite.ms.mff.cuni.cz Mon Mar 23 15:19:05 1998 */
+#define UFS_SUPER_MAGIC_LE 0x00011954
+#define UFS_SUPER_MAGIC_BE 0x54190100
+struct ufs_super_block {
+ u_char s_dummy[0x55c];
+ u_char s_magic[4];
+};
+#define ufsmagic(s) assemble4le(s.s_magic)
+
+/* From Richard.Russon at ait.co.uk Wed Feb 24 08:05:27 1999 */
+#define NTFS_SUPER_MAGIC "NTFS"
+struct ntfs_super_block {
+ u_char s_dummy[3];
+ u_char s_magic[4];
+};
+
+/* From inspection of a few FAT filesystems - aeb */
+/* Unfortunately I find almost the same thing on an extended partition;
+ it looks like a primary has some directory entries where the extended
+ has a partition table: IO.SYS, MSDOS.SYS, WINBOOT.SYS */
+struct fat_super_block {
+ u_char s_dummy[3];
+ u_char s_os[8]; /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
+ /* mtools-3.9.4 writes "MTOOL394" */
+ u_char s_dummy2[32];
+ u_char s_label[11]; /* for DOS? */
+ u_char s_fs[8]; /* "FAT12 " or "FAT16 " or all zero */
+ /* OS/2 BM has "FAT " here. */
+ u_char s_dummy3[9];
+ u_char s_label2[11]; /* for Windows? */
+ u_char s_fs2[8]; /* garbage or "FAT32 " */
+};
+
+#define XFS_SUPER_MAGIC "XFSB"
+struct xfs_super_block {
+ u_char s_magic[4];
+ u_char s_dummy[28];
+ u_char s_uuid[16];
+ u_char s_dummy2[60];
+ u_char s_fname[12];
+};
+
+#define CRAMFS_SUPER_MAGIC 0x28cd3d45
+#define CRAMFS_SUPER_MAGIC_BE 0x453dcd28
+struct cramfs_super_block {
+ u_char s_magic[4];
+ u_char s_dummy[12];
+ u_char s_id[16];
+};
+#define cramfsmagic(s) assemble4le(s.s_magic)
+
+#define HFS_SUPER_MAGIC 0x4244
+struct hfs_super_block {
+ u_char s_magic[2]; /* drSigWord */
+ u_char s_dummy[18];
+ u_char s_blksize[4]; /* drAlBlkSiz */
+};
+#define hfsmagic(s) assemble2be(s.s_magic)
+#define hfsblksize(s) assemble4be(s.s_blksize)
+
+#define HPFS_SUPER_MAGIC 0xf995e849
+struct hpfs_super_block {
+ u_char s_magic[4];
+ u_char s_magic2[4];
+};
+#define hpfsmagic(s) assemble4le(s.s_magic)
+
+struct adfs_super_block {
+ u_char s_dummy[448];
+ u_char s_blksize[1];
+ u_char s_dummy2[62];
+ u_char s_checksum[1];
+};
+#define adfsblksize(s) ((uint) s.s_blksize[0])
+
+/* found in first 4 bytes of block 1 */
+struct vxfs_super_block {
+ u_char s_magic[4];
+};
+#define vxfsmagic(s) assemble4le(s.s_magic)
+#define VXFS_SUPER_MAGIC 0xa501FCF5
+
+struct jfs_super_block {
+ char s_magic[4];
+ u_char s_version[4];
+ u_char s_dummy1[93];
+ char s_fpack[11];
+ u_char s_dummy2[24];
+ u_char s_uuid[16];
+ char s_label[16];
+};
+#define JFS_SUPER1_OFF 0x8000
+#define JFS_MAGIC "JFS1"
+
+struct sysv_super_block {
+ u_char s_dummy1[504];
+ u_char s_magic[4];
+ u_char type[4];
+};
+#define sysvmagic(s) assemble4le(s.s_magic)
+#define SYSV_SUPER_MAGIC 0xfd187e20
+
+struct mdp_super_block {
+ u_char md_magic[4];
+};
+#define MD_SB_MAGIC 0xa92b4efc
+#define mdsbmagic(s) assemble4le(s.md_magic)
+
+struct ocfs_volume_header {
+ u_char minor_version[4];
+ u_char major_version[4];
+ u_char signature[128];
+};
+
+struct ocfs_volume_label {
+ u_char disk_lock[48];
+ u_char label[64];
+ u_char label_len[2];
+};
+
+#define ocfslabellen(o) assemble2le(o.label_len)
+#define OCFS_MAGIC "OracleCFS"
+
+struct efs_volume_directory { /* size 16 */
+ char vd_name[8];
+ char vd_lbn[4];
+ char vd_nbytes[4];
+};
+
+struct efs_partition_table { /* size 12 */
+ char pt_nblks[4];
+ char pt_firstlbn[4];
+ char pt_type[4];
+};
+
+struct efs_volume_header { /* size 512 */
+ char vh_magic[4];
+ short vh_rootpt;
+ short vh_swappt;
+ char vh_bootfile[16];
+ char pad[48];
+ struct efs_volume_directory vh_vd[15];
+ struct efs_partition_table vh_pt[16];
+ int vh_csum;
+ int vh_fill;
+};
+
+struct efs_super {
+ char fs_stuff[512+28];
+ char fs_magic[4];
+ char fs_fname[6];
+ char fs_fpack[6];
+ /* ... */
+};
+
+#define EFS_VHMAGIC 0x0be5a941 /* big endian */
+#define EFS_SBMAGIC 0x00072959 /* idem */
+#define EFS_SBMAGIC2 0x0007295a /* idem */
+
+static inline int
+assemble2le(unsigned char *p) {
+ return (p[0] | (p[1] << 8));
+}
+
+static inline int
+assemble2be(unsigned char *p) {
+ return (p[1] | (p[0] << 8));
+}
+
+static inline int
+assemble4le(unsigned char *p) {
+ return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
+}
+
+static inline int
+assemble4be(unsigned char *p) {
+ return (p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24));
+}
+
+/* Linux swap */
+struct swap_header_v1_2 {
+ char bootbits[1024]; /* Space for disklabel etc. */
+ unsigned int version;
+ unsigned int last_page;
+ unsigned int nr_badpages;
+ char uuid[16];
+ char volume_name[16];
+ unsigned int padding[117];
+ unsigned int badpages[1];
+};
Added: trunk/mount.ocfs2/mntent.c
===================================================================
--- trunk/mount.ocfs2/mntent.c 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/mntent.c 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,224 @@
+/* Private version of the libc *mntent() routines. */
+/* Note slightly different prototypes. */
+
+/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at pld.ORG.PL>
+ * - added Native Language Support
+ */
+
+#include <stdio.h>
+#include <string.h> /* for index */
+#include <ctype.h> /* for isdigit */
+#include <sys/stat.h> /* for umask */
+#include "mntent.h"
+#include "sundries.h" /* for xmalloc */
+#include "nls.h"
+
+/* Unfortunately the classical Unix /etc/mtab and /etc/fstab
+ do not handle directory names containing spaces.
+ Here we mangle them, replacing a space by \040.
+ What do other Unices do? */
+
+static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
+
+static char *
+mangle(unsigned char *s) {
+ char *ss, *sp;
+ int n;
+
+ n = strlen(s);
+ ss = sp = xmalloc(4*n+1);
+ while(1) {
+ for (n = 0; n < sizeof(need_escaping); n++) {
+ if (*s == need_escaping[n]) {
+ *sp++ = '\\';
+ *sp++ = '0' + ((*s & 0300) >> 6);
+ *sp++ = '0' + ((*s & 070) >> 3);
+ *sp++ = '0' + (*s & 07);
+ goto next;
+ }
+ }
+ *sp++ = *s;
+ if (*s == 0)
+ break;
+ next:
+ s++;
+ }
+ return ss;
+}
+
+static int
+is_space_or_tab (char c) {
+ return (c == ' ' || c == '\t');
+}
+
+static char *
+skip_spaces(char *s) {
+ while (is_space_or_tab(*s))
+ s++;
+ return s;
+}
+
+static char *
+skip_nonspaces(char *s) {
+ while (*s && !is_space_or_tab(*s))
+ s++;
+ return s;
+}
+
+#define isoctal(a) (((a) & ~7) == '0')
+
+/* returns malloced pointer - no more strdup required */
+static char *
+unmangle(char *s) {
+ char *ret, *ss, *sp;
+
+ ss = skip_nonspaces(s);
+ ret = sp = xmalloc(ss-s+1);
+ while(s != ss) {
+ if (*s == '\\' && isoctal(s[1]) && isoctal(s[2]) && isoctal(s[3])) {
+ *sp++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
+ s += 4;
+ } else
+ *sp++ = *s++;
+ }
+ *sp = 0;
+ return ret;
+}
+
+/*
+ * fstat'ing the file and allocating a buffer holding all of it
+ * may be a bad idea: if the file is /proc/mounts, the stat
+ * returns 0.
+ * (On the other hand, mangling and unmangling is meaningless
+ * for /proc/mounts.)
+ */
+
+mntFILE *
+my_setmntent (const char *file, char *mode) {
+ mntFILE *mfp = xmalloc(sizeof(*mfp));
+ mode_t old_umask = umask(077);
+
+ mfp->mntent_fp = fopen (file, mode);
+ umask(old_umask);
+ mfp->mntent_file = xstrdup(file);
+ mfp->mntent_errs = (mfp->mntent_fp == NULL);
+ mfp->mntent_softerrs = 0;
+ mfp->mntent_lineno = 0;
+ return mfp;
+}
+
+void
+my_endmntent (mntFILE *mfp) {
+ if (mfp) {
+ if (mfp->mntent_fp)
+ fclose(mfp->mntent_fp);
+ if (mfp->mntent_file)
+ free(mfp->mntent_file);
+ free(mfp);
+ }
+}
+
+
+int
+my_addmntent (mntFILE *mfp, struct mntent *mnt) {
+ char *m1, *m2, *m3, *m4;
+ int res;
+
+ if (fseek (mfp->mntent_fp, 0, SEEK_END))
+ return 1; /* failure */
+
+ m1 = mangle(mnt->mnt_fsname);
+ m2 = mangle(mnt->mnt_dir);
+ m3 = mangle(mnt->mnt_type);
+ m4 = mangle(mnt->mnt_opts);
+
+ res = ((fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n",
+ m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno)
+ < 0) ? 1 : 0);
+
+ free(m1);
+ free(m2);
+ free(m3);
+ free(m4);
+ return res;
+}
+
+/* Read the next entry from the file fp. Stop reading at an incorrect entry. */
+struct mntent *
+my_getmntent (mntFILE *mfp) {
+ static char buf[4096];
+ static struct mntent me;
+ char *s;
+
+ again:
+ if (mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX)
+ return NULL;
+
+ /* read the next non-blank non-comment line */
+ do {
+ if (fgets (buf, sizeof(buf), mfp->mntent_fp) == NULL)
+ return NULL;
+
+ mfp->mntent_lineno++;
+ s = index (buf, '\n');
+ if (s == NULL) {
+ /* Missing final newline? Otherwise extremely */
+ /* long line - assume file was corrupted */
+ if (feof(mfp->mntent_fp)) {
+ fprintf(stderr, _("[mntent]: warning: no final "
+ "newline at the end of %s\n"),
+ mfp->mntent_file);
+ s = index (buf, 0);
+ } else {
+ mfp->mntent_errs = 1;
+ goto err;
+ }
+ }
+ *s = 0;
+ if (--s >= buf && *s == '\r')
+ *s = 0;
+ s = skip_spaces(buf);
+ } while (*s == '\0' || *s == '#');
+
+ me.mnt_fsname = unmangle(s);
+ s = skip_nonspaces(s);
+ s = skip_spaces(s);
+ me.mnt_dir = unmangle(s);
+ s = skip_nonspaces(s);
+ s = skip_spaces(s);
+ me.mnt_type = unmangle(s);
+ s = skip_nonspaces(s);
+ s = skip_spaces(s);
+ me.mnt_opts = unmangle(s);
+ s = skip_nonspaces(s);
+ s = skip_spaces(s);
+
+ if(isdigit(*s)) {
+ me.mnt_freq = atoi(s);
+ while(isdigit(*s)) s++;
+ } else
+ me.mnt_freq = 0;
+ if(*s && !is_space_or_tab(*s))
+ goto err;
+
+ s = skip_spaces(s);
+ if(isdigit(*s)) {
+ me.mnt_passno = atoi(s);
+ while(isdigit(*s)) s++;
+ } else
+ me.mnt_passno = 0;
+ if(*s && !is_space_or_tab(*s))
+ goto err;
+
+ /* allow more stuff, e.g. comments, on this line */
+
+ return &me;
+
+ err:
+ mfp->mntent_softerrs++;
+ fprintf(stderr, _("[mntent]: line %d in %s is bad%s\n"),
+ mfp->mntent_lineno, mfp->mntent_file,
+ (mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX) ?
+ _("; rest of file ignored") : "");
+ goto again;
+}
Added: trunk/mount.ocfs2/mntent.h
===================================================================
--- trunk/mount.ocfs2/mntent.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/mntent.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,16 @@
+#include <mntent.h> /* for struct mntent */
+
+#define ERR_MAX 5
+
+typedef struct mntFILEstruct {
+ FILE *mntent_fp;
+ char *mntent_file;
+ int mntent_lineno;
+ int mntent_errs;
+ int mntent_softerrs;
+} mntFILE;
+
+mntFILE *my_setmntent (const char *file, char *mode);
+void my_endmntent (mntFILE *mfp);
+int my_addmntent (mntFILE *mfp, struct mntent *mnt);
+struct mntent *my_getmntent (mntFILE *mfp);
Modified: trunk/mount.ocfs2/mount.ocfs2.c
===================================================================
--- trunk/mount.ocfs2/mount.ocfs2.c 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/mount.ocfs2.c 2005-03-15 23:25:37 UTC (rev 642)
@@ -1,6 +1,8 @@
/*
- * Copyright (C) 2004 Oracle. All rights reserved.
+ * mount.ocfs2.c Mounts ocfs2 volume
*
+ * Copyright (C) 2005 Oracle. All rights reserved.
+ *
* 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 the Free Software Foundation; either
@@ -16,384 +18,166 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*
- * Authors: Sunil Mushran
*/
+#include "mount.ocfs2.h"
-#define _LARGEFILE64_SOURCE
-#define _GNU_SOURCE /* Because libc really doesn't want us using O_DIRECT? */
+int verbose = 0;
+int mount_quiet=0;
+int nomtab = 0;
+char *progname = NULL;
+char op_buf[PAGE_SIZE];
-#include <sys/types.h>
-#include <asm/types.h>
-#include <inttypes.h>
+struct mount_options {
+ char *dev;
+ char *dir;
+ char *opts;
+ int flags;
+ char *xtra_opts;
+};
-#define u8 __u8
-#define s8 __s8
-#define u16 __u16
-#define s16 __s16
-#define u32 __u32
-#define s32 __s32
-#define u64 __u64
-#define s64 __s64
-#define atomic_t int
-#define spinlock_t unsigned long
-typedef unsigned short kdev_t;
-
-
-
-
-#include <asm/page.h>
-#include <sys/mount.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/fd.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#define OCFS2_FLAT_INCLUDES 1
-#include <ocfs2.h>
-#include <ocfs2_fs.h>
-#include <ocfs1_fs_compat.h>
-#include <kernel-list.h>
-
-#include "bitops.h"
-
-#include "ocfs2_nodemanager.h"
-#include "ocfs2_heartbeat.h"
-#include "ocfs2_tcp.h"
-
-#define CLUSTER_FILE "/proc/cluster/nm/.cluster"
-#define GROUP_FILE "/proc/cluster/nm/.group"
-#define NODE_FILE "/proc/cluster/nm/.node"
-#define HEARTBEAT_DISK_FILE "/proc/cluster/heartbeat/.disk"
-
-
-int create_remote_group(char *group_name, __u8 node);
-int get_node_map(__u8 group_num, char *bitmap);
-int get_raw_node_map(__u8 groupnum, char *groupdev, __u32 block_bits, __u32 num_blocks, __u64 start_block, char *bitmap);
-int get_ocfs2_disk_hb_params(char *group_dev, __u32 *block_bits, __u32 *cluster_bits,
- __u64 *start_block, __u32 *num_clusters);
-int activate_group(char *group_name, char *group_dev, __u8 group_num,
- __u32 block_bits, __u64 num_blocks, __u64 start_block);
-int add_to_local_group(char *uuid, __u8 group_num, __u8 node_num);
-int create_group(char *uuid, __u8 *group_num);
-int get_my_nodenum(__u8 *nodenum);
-int add_me_to_group(char *groupname, char *groupdev);
-int ocfs2_detect_one(char *dev, char *uuid, int uuid_size);
-static int read_options(int argc, char **argv, char **device, char **mp);
-
-char *op_buf = NULL;
-
-/* returns fs_type: 0 for unknown, 1 for ocfs, 2 for ocfs2 */
-int ocfs2_detect_one(char *dev, char *uuid, int uuid_size)
+static int get_uuid(char *dev, char *uuid)
{
ocfs2_filesys *fs = NULL;
- int fs_type = 0;
- int fs_size = sizeof(OCFS2_RAW_SB(fs->fs_super)->s_uuid);
- errcode_t ret;
+ errcode_t ret = 0;
+ int i;
+ char *p;
+ uint8_t *s_uuid;
- if (uuid_size != fs_size)
- goto out;
-
ret = ocfs2_open(dev, OCFS2_FLAG_RO, 0, 0, &fs);
if (ret)
goto out;
- memcpy(uuid, OCFS2_RAW_SB(fs->fs_super)->s_uuid,
- uuid_size);
- fs_type = 2;
+ s_uuid = OCFS2_RAW_SB(fs->fs_super)->s_uuid;
+ for (i = 0, p = uuid; i < 16; i++, p += 2)
+ sprintf(p, "%02X", s_uuid[i]);
+ *p = '\0';
+
ocfs2_close(fs);
out:
- return fs_type;
+ return ret;
}
-/*
- * read_options()
- *
- */
-//static int read_options(int argc, char **argv, char **hbuuid, char **hbdev, char **device, char **mp)
-static int read_options(int argc, char **argv, char **device, char **mp)
+static void read_options(int argc, char **argv, struct mount_options *mo)
{
- int ret = 0;
int c;
- char *tmp;
- if (argc < 2) {
- ret = 1;
+ progname = basename(argv[0]);
+
+ if (argc < 2)
goto bail;
- }
while(1) {
- c = getopt(argc, argv, "o:");
+ c = getopt(argc, argv, "vno:");
if (c == -1)
break;
switch (c) {
- case 'o': /* options */
- ret = 1;
- tmp = optarg;
- while (*tmp) {
- /* TODO: Fill me in with all the -o
- * options we'll honor. */
+ case 'v':
+ ++verbose;
+ break;
- /* unknown option, ignore
- * these for now, but we need
- * to eventually handle
- * them. */
- tmp = strchr(tmp, ',');
- if (!tmp || !*tmp)
- break;
- tmp++;
- }
- ret = 0;
+ case 'n':
+ ++nomtab;
break;
+ case 'o':
+ if (optarg)
+ mo->opts = xstrdup(optarg);
+ break;
+
default:
break;
}
}
- if (!ret) {
- ret = 1;
- /* need device and mountpoint */
- if (optind+1 < argc && argv[optind] && argv[optind+1]) {
- *device = strdup(argv[optind]);
- *mp = strdup(argv[optind+1]);
- ret = 0;
- }
- }
+ if (optind < argc && argv[optind])
+ mo->dev = xstrdup(argv[optind]);
+ ++optind;
+
+ if (optind < argc && argv[optind])
+ mo->dir = xstrdup(argv[optind]);
+
bail:
- return ret;
+ return ;
}
-
/*
- * main()
+ * Code based on similar function in util-linux-2.12a/mount/mount.c
*
*/
-int main(int argc, char **argv)
+static void print_one (const struct mntent *me)
{
- char *device = NULL, *mountpoint = NULL;
- char *hbuuid = NULL;
- errcode_t ret = 0;
- ocfs2_devices *dev;
- char *p;
- int i;
- unsigned long flags = 0;
- char *args = NULL;
+ if (mount_quiet)
+ return ;
- op_buf = malloc(PAGE_SIZE);
- if (!op_buf) {
- ret = 1;
- goto bail;
- }
+ printf ("%s on %s", me->mnt_fsname, me->mnt_dir);
- ret = read_options (argc, argv, &device, &mountpoint);
- if (ret) {
- com_err("mount.ocfs2", ret, "while reading options");
- goto bail;
- }
+ if (me->mnt_type != NULL && *(me->mnt_type) != '\0')
+ printf (" type %s", me->mnt_type);
- if (!device) {
- ret = OCFS2_ET_BAD_DEVICE_NAME;
- com_err("mount.ocfs2", ret, "no device specified");
- goto bail;
- }
- if (!mountpoint) {
- ret = OCFS2_ET_INVALID_ARGUMENT;
- com_err("mount.ocfs2", ret, "no mountpoint specified");
- goto bail;
- }
+ if (me->mnt_opts)
+ printf (" (%s)", me->mnt_opts);
- dev = calloc(1, sizeof(*dev));
- if (dev == NULL) {
- ret = OCFS2_ET_NO_MEMORY;
- com_err("mount.ocfs2", ret, "while allocating a dev");
- goto bail;
- }
- snprintf(dev->dev_name, sizeof(dev->dev_name), "%s", device);
-
- ret = ocfs2_detect_one(dev->dev_name, dev->uuid, sizeof(dev->uuid));
- if (ret != 2) {
- com_err("mount.ocfs2", ret, "while opening the file system");
- goto bail;
- }
- dev->fs_type = ret;
-
- hbuuid = malloc(33);
- memset(hbuuid, 0, 33);
- for (i = 0, p = hbuuid; i < 16; i++, p += 2)
- sprintf(p, "%02X", dev->uuid[i]);
-
- printf("device=%s hbuuid=%s\n", device, hbuuid);
-
- ret = add_me_to_group(hbuuid, device);
- if (ret < 0) {
- printf("eeek! something bad happened in add_me_to_group: "
- "ret=%d\n", (int)ret);
- goto bail;
- }
-
- args = malloc(strlen(hbuuid) + strlen("group=") + 1);
- if (!args) {
- ret = OCFS2_ET_NO_MEMORY;
- com_err("mount.ocfs2", ret, "while allocating memory");
- goto bail;
- }
- sprintf(args, "group=%s", hbuuid);
- flags = 0;
- ret = mount(device, mountpoint, "ocfs2", flags, args);
-
-bail:
- if (args)
- free(args);
- if (device)
- free(device);
- if (mountpoint)
- free(mountpoint);
- if (hbuuid)
- free(hbuuid);
-
- if (op_buf)
- free(op_buf);
-
- return ret;
+ printf ("\n");
}
-
-
/*
- * this will try to add the group (and the node to the group)
- * for every mount. luckily, there are many shortcut paths
- * along the way, so checking for -EEXIST will save time.
+ * Code based on similar function in util-linux-2.12a/mount/mount.c
+ *
*/
-int add_me_to_group(char *groupname, char *groupdev)
+static void update_mtab_entry(char *spec, char *node, char *type, char *opts,
+ int flags, int freq, int pass)
{
- int ret;
- __u8 my_nodenum, groupnum;
- __u32 pre_nodemap[] = {0, 0, 0, 0, 0, 0, 0, 0};
- __u32 post_nodemap[] = {0, 0, 0, 0, 0, 0, 0, 0};
- int start, next, i;
- __u32 block_bits, cluster_bits, num_clusters;
- __u64 start_block, num_blocks;
+ struct mntent mnt;
+ mntFILE *mfp;
- /* either create the group or find that it already exists */
- ret = get_my_nodenum(&my_nodenum);
- if (ret < 0)
- return ret;
+ mnt.mnt_fsname = canonicalize (spec);
+ mnt.mnt_dir = canonicalize (node);
+ mnt.mnt_type = type;
+ mnt.mnt_opts = opts;
+ mnt.mnt_freq = freq;
+ mnt.mnt_passno = pass;
+
+ /* We get chatty now rather than after the update to mtab since the
+ mount succeeded, even if the write to /etc/mtab should fail. */
+ if (verbose)
+ print_one (&mnt);
- ret = get_ocfs2_disk_hb_params(groupdev, &block_bits, &cluster_bits,
- &start_block, &num_clusters);
- if (ret < 0)
- return ret;
+ if (nomtab || !mtab_is_writable())
+ goto bail;
- num_blocks = num_clusters << cluster_bits;
- num_blocks >>= block_bits;
-
- ret = create_group(groupname, &groupnum);
- if (ret != -EEXIST && ret != 0)
- return ret;
+// if (flags & MS_REMOUNT) {
+// update_mtab (mnt.mnt_dir, &mnt);
+// goto bail;
+// }
- ret = activate_group(groupname, groupdev, groupnum, block_bits, num_blocks, start_block);
- if (ret < 0)
- return ret;
+ lock_mtab();
- ret = add_to_local_group(groupname, groupnum, my_nodenum);
- if (ret != -EEXIST && ret != 0)
- return ret;
-
- /* at this point my node is heartbeating, so any other nodes
- * joining right now must communicate with me */
-
- while (1) {
- ret = get_node_map(groupnum, (char *)pre_nodemap);
- if (ret < 0)
- return ret;
- if (ocfs2_test_bit(my_nodenum, (char *)pre_nodemap)) {
- printf("found myself (%u) in nodemap! continuing...\n", my_nodenum);
- break;
- } else {
- printf("have not yet found myself (%u) in nodemap...\n", my_nodenum);
- }
- /* TODO: set this to the default hb interval. 2 seconds right now */
- sleep(2);
+ mfp = my_setmntent(MOUNTED, "a+");
+ if (mfp == NULL || mfp->mntent_fp == NULL) {
+ com_err(progname, OCFS2_ET_IO, "%s, %s", MOUNTED,
+ strerror(errno));
+ goto unlock;
}
- /* now that we see ourself heartbeating, take a look
- * at ALL of the nodes that seem to be heartbeating
- * on this device. add them here and have them add
- * me there... */
- ret = get_raw_node_map(groupnum, groupdev, block_bits, num_blocks, start_block, (char *)pre_nodemap);
- if (ret < 0)
- return ret;
-
-again:
- /* go create this group and add this node on every other node I see */
- start = 0;
- while (1) {
- next = ocfs2_find_next_bit_set((unsigned long *)pre_nodemap, NM_MAX_NODES, start);
- if (next >= NM_MAX_NODES) {
- break;
- }
- if (next != my_nodenum) {
- /* add remote node here... */
- ret = add_to_local_group(groupname, groupnum, next);
- if (ret != -EEXIST && ret != 0)
- return ret;
-
- /* ...and add this node there */
- ret = create_remote_group(groupname, next);
- if (ret != 0 && ret != -EEXIST) {
- printf("create_remote_group: node=%u returned %d!\n",
- next, ret);
- break;
- }
- }
- start = next + 1;
+ if ((my_addmntent (mfp, &mnt)) == 1) {
+ com_err(progname, OCFS2_ET_IO, "%s, %s", MOUNTED,
+ strerror(errno));
}
- if (ret != 0 && ret != -EEXIST)
- return ret;
- printf("done creating remote groups\n");
+ my_endmntent(mfp);
- /* grab the nodemap again and look for changes */
- ret = get_raw_node_map(groupnum, groupdev, block_bits, num_blocks, start_block, (char *)post_nodemap);
- if (ret < 0)
- return ret;
-
- printf("checking raw node map again.....\n");
-
- if (memcmp(pre_nodemap, post_nodemap, sizeof(pre_nodemap)) == 0) {
- /* nothing changed. we are DONE! */
- printf("woot. nothing changed. all done\n");
- return 0;
- }
-
- printf("something changed\n");
-
- /* something changed */
- for (i=0; i<8; i++) {
- post_nodemap[i] &= ~pre_nodemap[i];
- pre_nodemap[i] = post_nodemap[i];
- post_nodemap[i] = 0;
- }
-
- /* keep going while there are still nodes to contact */
- if (ocfs2_find_next_bit_set((unsigned long *)pre_nodemap, NM_MAX_NODES, 0) < NM_MAX_NODES)
- goto again;
-
- printf("ah nothing left to care about ... leaving\n");
-
- return 0;
+unlock:
+ unlock_mtab();
+bail:
+ return ;
}
-int get_my_nodenum(__u8 *nodenum)
+static int get_my_nodenum(uint8_t *nodenum)
{
FILE *file;
int ret = -EINVAL;
@@ -423,7 +207,7 @@
return ret;
}
-int create_group(char *uuid, __u8 *group_num)
+static int create_group(char *uuid, uint8_t *group_num)
{
FILE *file;
int ret = -EINVAL, retval;
@@ -473,7 +257,7 @@
}
-int add_to_local_group(char *uuid, __u8 group_num, __u8 node_num)
+static int add_to_local_group(char *uuid, uint8_t group_num, uint8_t node_num)
{
FILE *file;
int ret = -EINVAL, retval;
@@ -522,15 +306,16 @@
return ret;
}
-int activate_group(char *group_name, char *group_dev, __u8 group_num,
- __u32 block_bits, __u64 num_blocks, __u64 start_block)
+static int activate_group(char *group_name, char *group_dev, uint8_t group_num,
+ uint32_t block_bits, uint64_t num_blocks, uint64_t start_block)
{
int dev_fd = -1;
int ret = -EINVAL, retval;
FILE *file;
hb_op *op;
- printf("starting disk heartbeat...\n");
+ if (verbose)
+ printf("starting disk heartbeat...\n");
memset(op_buf, 0, PAGE_SIZE);
op = (hb_op *)op_buf;
@@ -568,9 +353,8 @@
return 0;
}
-
-int get_ocfs2_disk_hb_params(char *group_dev, __u32 *block_bits, __u32 *cluster_bits,
- __u64 *start_block, __u32 *num_clusters)
+static int get_ocfs2_disk_hb_params(char *group_dev, uint32_t *block_bits, uint32_t *cluster_bits,
+ uint64_t *start_block, uint32_t *num_clusters)
{
int status = -EINVAL;
errcode_t ret = 0;
@@ -619,17 +403,18 @@
return status;
}
-int get_node_map(__u8 group_num, char *bitmap)
+static int get_node_map(uint8_t group_num, char *bitmap)
{
FILE *file = NULL;
hb_op *op;
int ret = -EINVAL;
int retval;
- u8 bytemap[NM_MAX_NODES];
+ uint8_t bytemap[NM_MAX_NODES];
int i;
+
+ if (verbose)
+ printf("getting node map...\n");
- printf("getting node map...\n");
-
memset(op_buf, 0, PAGE_SIZE);
op = (hb_op *)op_buf;
op->magic = HB_OP_MAGIC;
@@ -667,19 +452,19 @@
return ret;
}
-
-int get_raw_node_map(__u8 groupnum, char *groupdev, __u32 block_bits, __u32 num_blocks, __u64 start_block, char *bitmap)
+static int get_raw_node_map(uint8_t groupnum, char *groupdev,
+ uint32_t block_bits, uint32_t num_blocks,
+ uint64_t start_block, char *bitmap)
{
int i;
int ret = -EINVAL;
char *buf = NULL, *tmpbuf;
hb_disk_heartbeat_block *times = NULL;
-
errcode_t err;
io_channel *channel;
-
- printf("getting raw node map...\n");
+ if (verbose)
+ printf("getting raw node map...\n");
times = malloc(sizeof(hb_disk_heartbeat_block) * NM_MAX_NODES);
if (!times) {
@@ -732,11 +517,12 @@
tmpbuf = buf;
for (i=0; i<NM_MAX_NODES; i++) {
- printf("node: %d: before=%"PRIu64", after=%"PRIu64"\n", i,
- times[i].time,
- ((hb_disk_heartbeat_block *)tmpbuf)->time);
+ if (verbose)
+ printf("node: %d: before=%"PRIu64", after=%"PRIu64"\n",
+ i, times[i].time, ((hb_disk_heartbeat_block *)tmpbuf)->time);
if (times[i].time != ((hb_disk_heartbeat_block *)tmpbuf)->time) {
- printf(" >>>>> aha node %d seems to be up!\n", i);
+ if (verbose)
+ printf(" >>>>> aha node %d seems to be up!\n", i);
ocfs2_set_bit(i, bitmap);
}
tmpbuf += (1 << block_bits);
@@ -753,7 +539,7 @@
return ret;
}
-int create_remote_group(char *group_name, __u8 node)
+static int create_remote_group(char *group_name, uint8_t node)
{
int ret, fd = -1, remote_node = -1;
gsd_ioc ioc;
@@ -761,7 +547,8 @@
DIR *dir = NULL;
struct dirent *de = NULL;
- printf("create_remote_group: name=%s, remote node=%u\n", group_name, node);
+ if (verbose)
+ printf("create_remote_group: name=%s, remote node=%u\n", group_name, node);
/* NOTE: this is a bit of a hack. we actually normally would not
* know which "global" node corresponds to this "group relative" node.
@@ -786,7 +573,8 @@
ret = -EINVAL;
goto leave;
}
- printf("found file %s corresponding to node %u\n", fname, node);
+ if (verbose)
+ printf("found file %s corresponding to node %u\n", fname, node);
/* open a file descriptor to the node we want to talk to */
remote_node = open(fname, O_RDONLY);
@@ -794,7 +582,8 @@
ret = -errno;
goto leave;
}
- printf("fd for remote node=%d\n", remote_node);
+ if (verbose)
+ printf("fd for remote node=%d\n", remote_node);
/* TODO: move this over to a transaction file on the inode, eliminate the ioctl */
fd = open("/proc/cluster/net", O_RDONLY);
@@ -803,7 +592,8 @@
goto leave;
}
- printf("fd for net ioctl file=%d\n", fd);
+ if (verbose)
+ printf("fd for net ioctl file=%d\n", fd);
/* call an ioctl to create the group over there */
memset(&ioc, 0, sizeof(gsd_ioc));
@@ -815,7 +605,8 @@
goto leave;
}
ret = ioc.status;
- printf("create group ioctl returned ret=%d\n", ret);
+ if (verbose)
+ printf("create group ioctl returned ret=%d\n", ret);
if (ret != 0 && ret != -EEXIST)
goto leave;
@@ -830,7 +621,8 @@
goto leave;
}
ret = ioc.status;
- printf("add node ioctl returned ret=%d\n", ret);
+ if (verbose)
+ printf("add node ioctl returned ret=%d\n", ret);
leave:
if (fd != -1)
@@ -839,3 +631,216 @@
close(remote_node);
return ret;
}
+
+/*
+ * this will try to add the group (and the node to the group)
+ * for every mount. luckily, there are many shortcut paths
+ * along the way, so checking for -EEXIST will save time.
+ */
+static int add_me_to_group(char *groupname, char *groupdev)
+{
+ int ret;
+ uint8_t my_nodenum, groupnum;
+ uint32_t pre_nodemap[] = {0, 0, 0, 0, 0, 0, 0, 0};
+ uint32_t post_nodemap[] = {0, 0, 0, 0, 0, 0, 0, 0};
+ int start, next, i;
+ uint32_t block_bits, cluster_bits, num_clusters;
+ uint64_t start_block, num_blocks;
+
+ /* either create the group or find that it already exists */
+ ret = get_my_nodenum(&my_nodenum);
+ if (ret < 0)
+ return ret;
+
+ ret = get_ocfs2_disk_hb_params(groupdev, &block_bits, &cluster_bits,
+ &start_block, &num_clusters);
+ if (ret < 0)
+ return ret;
+
+ num_blocks = num_clusters << cluster_bits;
+ num_blocks >>= block_bits;
+
+ ret = create_group(groupname, &groupnum);
+ if (ret != -EEXIST && ret != 0)
+ return ret;
+
+ ret = activate_group(groupname, groupdev, groupnum, block_bits, num_blocks, start_block);
+ if (ret < 0)
+ return ret;
+
+ ret = add_to_local_group(groupname, groupnum, my_nodenum);
+ if (ret != -EEXIST && ret != 0)
+ return ret;
+
+ /* at this point my node is heartbeating, so any other nodes
+ * joining right now must communicate with me */
+
+ while (1) {
+ ret = get_node_map(groupnum, (char *)pre_nodemap);
+ if (ret < 0)
+ return ret;
+ if (ocfs2_test_bit(my_nodenum, (char *)pre_nodemap)) {
+ if (verbose)
+ printf("found myself (%u) in nodemap! continuing...\n", my_nodenum);
+ break;
+ } else {
+ if (verbose)
+ printf("have not yet found myself (%u) in nodemap...\n", my_nodenum);
+ }
+ /* TODO: set this to the default hb interval. 2 seconds right now */
+ sleep(2);
+ }
+
+ /* now that we see ourself heartbeating, take a look
+ * at ALL of the nodes that seem to be heartbeating
+ * on this device. add them here and have them add
+ * me there... */
+ ret = get_raw_node_map(groupnum, groupdev, block_bits, num_blocks, start_block, (char *)pre_nodemap);
+ if (ret < 0)
+ return ret;
+
+again:
+ /* go create this group and add this node on every other node I see */
+ start = 0;
+ while (1) {
+ next = ocfs2_find_next_bit_set((unsigned long *)pre_nodemap, NM_MAX_NODES, start);
+ if (next >= NM_MAX_NODES) {
+ break;
+ }
+ if (next != my_nodenum) {
+ /* add remote node here... */
+ ret = add_to_local_group(groupname, groupnum, next);
+ if (ret != -EEXIST && ret != 0)
+ return ret;
+
+ /* ...and add this node there */
+ ret = create_remote_group(groupname, next);
+ if (ret != 0 && ret != -EEXIST) {
+ com_err(progname, ret, "unable to create remote group");
+ break;
+ }
+ }
+ start = next + 1;
+ }
+ if (ret != 0 && ret != -EEXIST)
+ return ret;
+
+ if (verbose)
+ printf("done creating remote groups\n");
+
+ /* grab the nodemap again and look for changes */
+ ret = get_raw_node_map(groupnum, groupdev, block_bits, num_blocks, start_block, (char *)post_nodemap);
+ if (ret < 0)
+ return ret;
+
+ if (verbose)
+ printf("checking raw node map again.....\n");
+
+ if (memcmp(pre_nodemap, post_nodemap, sizeof(pre_nodemap)) == 0) {
+ /* nothing changed. we are DONE! */
+ if (verbose)
+ printf("woot. nothing changed. all done\n");
+ return 0;
+ }
+
+ if (verbose)
+ printf("something changed\n");
+
+ /* something changed */
+ for (i=0; i<8; i++) {
+ post_nodemap[i] &= ~pre_nodemap[i];
+ pre_nodemap[i] = post_nodemap[i];
+ post_nodemap[i] = 0;
+ }
+
+ /* keep going while there are still nodes to contact */
+ if (ocfs2_find_next_bit_set((unsigned long *)pre_nodemap, NM_MAX_NODES, 0) < NM_MAX_NODES)
+ goto again;
+
+ if (verbose)
+ printf("ah nothing left to care about ... leaving\n");
+
+ return 0;
+}
+
+static int process_options(struct mount_options *mo)
+{
+ if (!mo->dev) {
+ com_err(progname, OCFS2_ET_BAD_DEVICE_NAME, " ");
+ return -1;
+ }
+
+ if (!mo->dir) {
+ com_err(progname, OCFS2_ET_INVALID_ARGUMENT, "no mountpoint specified");
+ return -1;
+ }
+
+ if (mo->opts)
+ parse_opts(mo->opts, &mo->flags, &mo->xtra_opts);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ errcode_t ret = 0;
+ struct mount_options mo = { NULL, NULL, NULL };
+ char hbuuid[33];
+
+ initialize_ocfs_error_table();
+ initialize_o2dl_error_table();
+
+ read_options (argc, argv, &mo);
+
+ ret = process_options(&mo);
+ if (ret)
+ goto bail;
+
+ ret = get_uuid(mo.dev, hbuuid);
+ if (ret) {
+ com_err(progname, ret, "while opening the file system");
+ goto bail;
+ }
+
+ if (verbose)
+ printf("device=%s hbuuid=%s\n", mo.dev, hbuuid);
+
+ ret = add_me_to_group(hbuuid, mo.dev);
+ if (ret < 0) {
+ fprintf(stderr, "%s: Error '%d' while adding to group\n", progname, ret);
+ goto bail;
+ }
+
+ mo.xtra_opts = realloc(mo.xtra_opts, (strlen(mo.xtra_opts) +
+ strlen(hbuuid) +
+ strlen("group=") + 1));
+ if (!mo.xtra_opts) {
+ com_err(progname, OCFS2_ET_NO_MEMORY, " ");
+ goto bail;
+ }
+
+ if (strlen(mo.xtra_opts))
+ strcat(mo.xtra_opts, ",");
+ strcat(mo.xtra_opts, "group=");
+ strcat(mo.xtra_opts, hbuuid);
+
+ ret = mount(mo.dev, mo.dir, "ocfs2", mo.flags, mo.xtra_opts);
+ if (ret) {
+ com_err(progname, errno, "while mounting %s on %s", mo.dev, mo.dir);
+ goto bail;
+ }
+
+ update_mtab_entry(mo.dev, mo.dir, "ocfs2", mo.xtra_opts, mo.flags, 0, 0);
+
+bail:
+ if (mo.dev)
+ free(mo.dev);
+ if (mo.dir)
+ free(mo.dir);
+ if (mo.opts)
+ free(mo.opts);
+ if (mo.xtra_opts)
+ free(mo.xtra_opts);
+
+ return ret;
+}
Added: trunk/mount.ocfs2/mount.ocfs2.h
===================================================================
--- trunk/mount.ocfs2/mount.ocfs2.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/mount.ocfs2.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,65 @@
+/*
+ * mount.ocfs2.h Definitions, etc.
+ *
+ * Copyright (C) 2004 Oracle. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+#define _LARGEFILE64_SOURCE
+#define _GNU_SOURCE /* Because libc really doesn't want us using O_DIRECT? */
+
+#include <sys/types.h>
+#include <asm/types.h>
+#include <inttypes.h>
+
+#include <asm/page.h>
+#include <sys/mount.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "fstab.h"
+#include "get_label_uuid.h"
+#include "linux_fs.h"
+#include "nls.h"
+#include "realpath.h"
+#include "sundries.h"
+#include "mntent.h"
+#include "mount_constants.h"
+#include "opts.h"
+
+#include <ocfs2.h>
+#include <ocfs2_fs.h>
+#include <ocfs1_fs_compat.h>
+#include <kernel-list.h>
+
+#include "bitops.h"
+
+#include "ocfs2_nodemanager.h"
+#include "ocfs2_heartbeat.h"
+#include "ocfs2_tcp.h"
+
+#define CLUSTER_FILE "/proc/cluster/nm/.cluster"
+#define GROUP_FILE "/proc/cluster/nm/.group"
+#define NODE_FILE "/proc/cluster/nm/.node"
+#define HEARTBEAT_DISK_FILE "/proc/cluster/heartbeat/.disk"
Added: trunk/mount.ocfs2/mount_constants.h
===================================================================
--- trunk/mount.ocfs2/mount_constants.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/mount_constants.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,68 @@
+#ifndef MS_RDONLY
+#define MS_RDONLY 1 /* Mount read-only */
+#endif
+#ifndef MS_NOSUID
+#define MS_NOSUID 2 /* Ignore suid and sgid bits */
+#endif
+#ifndef MS_NODEV
+#define MS_NODEV 4 /* Disallow access to device special files */
+#endif
+#ifndef MS_NOEXEC
+#define MS_NOEXEC 8 /* Disallow program execution */
+#endif
+#ifndef MS_SYNCHRONOUS
+#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
+#endif
+#ifndef MS_REMOUNT
+#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
+#endif
+#ifndef MS_MANDLOCK
+#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
+#endif
+#ifndef MS_DIRSYNC
+#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
+#endif
+
+#ifndef MS_ACTION_MASK
+#define MS_ACTION_MASK 0x380
+/* Remount, but new filesystem may be different from old. Atomic
+ (i.e. there is no interval when nothing is mounted at the mountpoint).
+ If new fs differs from the old one and old is busy - -EBUSY. */
+#define MS_REPLACE 0x080 /* 128 */
+/* After, Before: as soon as we get unions these will add a new member
+ in the end or beginning of the chain. Fail if there is a stack
+ on the mountpoint. */
+#define MS_AFTER 0x100 /* 256 */
+#define MS_BEFORE 0x180
+/* Over: if nothing mounted on a mountpoint - same as if none of these
+flags had been set; if we have a union with more than one element - fail;
+if we have a stack or plain mount - mount atop of it, forming a stack. */
+#define MS_OVER 0x200 /* 512 */
+#endif
+#ifndef MS_NOATIME
+#define MS_NOATIME 0x400 /* 1024: Do not update access times. */
+#endif
+#ifndef MS_NODIRATIME
+#define MS_NODIRATIME 0x800 /* 2048: Don't update directory access times */
+#endif
+#ifndef MS_BIND
+#define MS_BIND 0x1000 /* 4096: Mount existing tree also elsewhere */
+#endif
+#ifndef MS_MOVE
+#define MS_MOVE 0x2000 /* 8192: Atomically move tree */
+#endif
+#ifndef MS_REC
+#define MS_REC 0x4000 /* 16384: Recursive loopback */
+#endif
+#ifndef MS_VERBOSE
+#define MS_VERBOSE 0x8000 /* 32768 */
+#endif
+/*
+ * Magic mount flag number. Had to be or-ed to the flag values.
+ */
+#ifndef MS_MGC_VAL
+#define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */
+#endif
+#ifndef MS_MGC_MSK
+#define MS_MGC_MSK 0xffff0000 /* magic flag number mask */
+#endif
Added: trunk/mount.ocfs2/nls.h
===================================================================
--- trunk/mount.ocfs2/nls.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/nls.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,30 @@
+/*
+ * nls.h
+ *
+ * Code extracted from util-linux-2.12a/mount/nls.h
+ *
+ * Copyright (C) 2005 Oracle. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+# undef bindtextdomain
+# define bindtextdomain(Domain, Directory) /* empty */
+# undef textdomain
+# define textdomain(Domain) /* empty */
+# define _(Text) (Text)
+# define N_(Text) (Text)
Added: trunk/mount.ocfs2/opts.c
===================================================================
--- trunk/mount.ocfs2/opts.c 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/opts.c 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,235 @@
+/*
+ * opts.c Parses options for mount.ocfs2.c
+ *
+ * Code has been extracted from util-linux-2.12a/mount/mount.c
+ *
+ * Copyright (C) 2005 Oracle. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+#include "mount.ocfs2.h"
+
+#include <ctype.h>
+#include <grp.h>
+#include <pwd.h>
+
+/* Custom mount options for our own purposes. */
+/* Maybe these should now be freed for kernel use again */
+#define MS_NOAUTO 0x80000000
+#define MS_USERS 0x40000000
+#define MS_USER 0x20000000
+#define MS_OWNER 0x10000000
+#define MS_PAMCONSOLE 0x08000000
+#define MS_NETDEV 0x00020000
+#define MS_LOOP 0x00010000
+
+/* Options that we keep the mount system call from seeing. */
+#define MS_NOSYS (MS_NOAUTO|MS_USERS|MS_USER|MS_NETDEV|MS_LOOP|MS_PAMCONSOLE)
+
+/* Options that we keep from appearing in the options field in the mtab. */
+#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER|MS_PAMCONSOLE)
+
+/* Options that we make ordinary users have by default. */
+#define MS_SECURE (MS_NOEXEC|MS_NOSUID|MS_NODEV)
+
+/* Options that we make owner-mounted devices have by default */
+#define MS_OWNERSECURE (MS_NOSUID|MS_NODEV)
+
+struct opt_map {
+ const char *opt; /* option name */
+ int skip; /* skip in mtab option string */
+ int inv; /* true if flag value should be inverted */
+ int mask; /* flag mask value */
+};
+
+static const struct opt_map opt_map[] = {
+ { "defaults", 0, 0, 0 }, /* default options */
+ { "ro", 1, 0, MS_RDONLY }, /* read-only */
+ { "rw", 1, 1, MS_RDONLY }, /* read-write */
+ { "exec", 0, 1, MS_NOEXEC }, /* permit execution of binaries */
+ { "noexec", 0, 0, MS_NOEXEC }, /* don't execute binaries */
+ { "suid", 0, 1, MS_NOSUID }, /* honor suid executables */
+ { "nosuid", 0, 0, MS_NOSUID }, /* don't honor suid executables */
+ { "dev", 0, 1, MS_NODEV }, /* interpret device files */
+ { "nodev", 0, 0, MS_NODEV }, /* don't interpret devices */
+ { "sync", 0, 0, MS_SYNCHRONOUS}, /* synchronous I/O */
+ { "async", 0, 1, MS_SYNCHRONOUS}, /* asynchronous I/O */
+ { "dirsync", 0, 0, MS_DIRSYNC}, /* synchronous directory modifications */
+ { "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */
+ { "bind", 0, 0, MS_BIND }, /* Remount part of tree elsewhere */
+ { "auto", 0, 1, MS_NOAUTO }, /* Can be mounted using -a */
+ { "noauto", 0, 0, MS_NOAUTO }, /* Can only be mounted explicitly */
+ { "users", 0, 0, MS_USERS }, /* Allow ordinary user to mount */
+ { "nousers", 0, 1, MS_USERS }, /* Forbid ordinary user to mount */
+ { "user", 0, 0, MS_USER }, /* Allow ordinary user to mount */
+ { "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */
+ { "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */
+ { "noowner", 0, 1, MS_OWNER }, /* Device owner has no special privs */
+ { "_netdev", 0, 0, MS_NETDEV }, /* Device accessible only via network */
+ { "pamconsole", 0, 0, MS_PAMCONSOLE }, /* Allow users at console to mount */
+ { "nopamconsole", 0, 1, MS_PAMCONSOLE }, /* Console user has no special privs */
+#ifdef MS_NOSUB
+ { "sub", 0, 1, MS_NOSUB }, /* allow submounts */
+ { "nosub", 0, 0, MS_NOSUB }, /* don't allow submounts */
+#endif
+#ifdef MS_SILENT
+ { "quiet", 0, 0, MS_SILENT }, /* be quiet */
+ { "loud", 0, 1, MS_SILENT }, /* print out messages. */
+#endif
+#ifdef MS_MANDLOCK
+ { "mand", 0, 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */
+ { "nomand", 0, 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */
+#endif
+ { "loop", 1, 0, MS_LOOP }, /* use a loop device */
+#ifdef MS_NOATIME
+ { "atime", 0, 1, MS_NOATIME }, /* Update access time */
+ { "noatime", 0, 0, MS_NOATIME }, /* Do not update access time */
+#endif
+#ifdef MS_NODIRATIME
+ { "diratime", 0, 1, MS_NODIRATIME }, /* Update dir access times */
+ { "nodiratime", 0, 0, MS_NODIRATIME },/* Do not update dir access times */
+#endif
+ { "kudzu", 0, 0, 0 }, /* Silently remove this option (backwards compat use only) */
+ { "managed", 0, 0, 0 }, /* Silently remove this option */
+ { NULL, 0, 0, 0 }
+};
+
+
+static char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
+ *opt_speed;
+
+static struct string_opt_map {
+ char *tag;
+ int skip;
+ char **valptr;
+} string_opt_map[] = {
+ { "loop=", 0, &opt_loopdev },
+ { "vfs=", 1, &opt_vfstype },
+ { "offset=", 0, &opt_offset },
+ { "encryption=", 0, &opt_encryption },
+ { "speed=", 0, &opt_speed },
+ { NULL, 0, NULL }
+};
+
+static void clear_string_opts(void)
+{
+ struct string_opt_map *m;
+
+ for (m = &string_opt_map[0]; m->tag; m++)
+ *(m->valptr) = NULL;
+}
+
+static int parse_string_opt(char *s)
+{
+ struct string_opt_map *m;
+ int lth;
+
+ for (m = &string_opt_map[0]; m->tag; m++) {
+ lth = strlen(m->tag);
+ if (!strncmp(s, m->tag, lth)) {
+ *(m->valptr) = xstrdup(s + lth);
+ return 1;
+ }
+ }
+ return 0;
+}
+/*
+ * Look for OPT in opt_map table and return mask value.
+ * If OPT isn't found, tack it onto extra_opts (which is non-NULL).
+ * For the options uid= and gid= replace user or group name by its value.
+ */
+static inline void parse_opt (const char *opt, int *mask, char *extra_opts)
+{
+ const struct opt_map *om;
+
+ for (om = opt_map; om->opt != NULL; om++)
+ if (streq (opt, om->opt)) {
+ if (om->inv)
+ *mask &= ~om->mask;
+ else
+ *mask |= om->mask;
+ if ((om->mask == MS_USER || om->mask == MS_USERS || om->mask == MS_PAMCONSOLE)
+ && !om->inv)
+ *mask |= MS_SECURE;
+ if ((om->mask == MS_OWNER) && !om->inv)
+ *mask |= MS_OWNERSECURE;
+
+#ifdef MS_SILENT
+ if (om->mask == MS_SILENT && om->inv) {
+ mount_quiet = 1;
+ verbose = 0;
+ }
+#endif
+ return;
+ }
+
+ if (*extra_opts)
+ strcat(extra_opts, ",");
+
+ /* convert nonnumeric ids to numeric */
+ if (!strncmp(opt, "uid=", 4) && !isdigit(opt[4])) {
+ struct passwd *pw = getpwnam(opt+4);
+ char uidbuf[20];
+
+ if (pw) {
+ sprintf(uidbuf, "uid=%d", pw->pw_uid);
+ strcat(extra_opts, uidbuf);
+ return;
+ }
+ }
+ if (!strncmp(opt, "gid=", 4) && !isdigit(opt[4])) {
+ struct group *gr = getgrnam(opt+4);
+ char gidbuf[20];
+
+ if (gr) {
+ sprintf(gidbuf, "gid=%d", gr->gr_gid);
+ strcat(extra_opts, gidbuf);
+ return;
+ }
+ }
+
+ strcat(extra_opts, opt);
+}
+
+/* Take -o options list and compute 4th and 5th args to mount(2). flags
+ gets the standard options (indicated by bits) and extra_opts all the rest */
+void parse_opts (char *opts, int *flags, char **extra_opts)
+{
+ char *opt;
+
+ *flags = 0;
+ *extra_opts = NULL;
+
+ clear_string_opts();
+
+ if (opts != NULL) {
+ *extra_opts = xmalloc (strlen (opts) + 1);
+ **extra_opts = '\0';
+
+ for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ","))
+ if (!parse_string_opt (opt))
+ parse_opt (opt, flags, *extra_opts);
+ }
+#if 0
+ if (readonly)
+ *flags |= MS_RDONLY;
+ if (readwrite)
+ *flags &= ~MS_RDONLY;
+ *flags |= mounttype;
+#endif
+}
Added: trunk/mount.ocfs2/opts.h
===================================================================
--- trunk/mount.ocfs2/opts.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/opts.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,23 @@
+/*
+ * opts.h Definitions, function prototypes, etc.
+ *
+ * Copyright (C) 2005 Oracle. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+void parse_opts (char *opts, int *flags, char **extra_opts);
Added: trunk/mount.ocfs2/realpath.c
===================================================================
--- trunk/mount.ocfs2/realpath.c 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/realpath.c 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,132 @@
+/*
+ * realpath.c -- canonicalize pathname by removing symlinks
+ * Copyright (C) 1993 Rick Sladkey <jrs at world.std.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library Public License for more details.
+ */
+
+#define resolve_symlinks
+
+/*
+ * This routine is part of libc. We include it nevertheless,
+ * since the libc version has some security flaws.
+ */
+
+#include <limits.h> /* for PATH_MAX */
+#ifndef PATH_MAX
+#define PATH_MAX 8192
+#endif
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "realpath.h"
+#include "sundries.h" /* for xstrdup */
+
+#define MAX_READLINKS 32
+
+/* this leaks some memory - unimportant for mount */
+char *
+myrealpath(const char *path, char *resolved_path, int maxreslth) {
+ int readlinks = 0;
+ char *npath;
+ char link_path[PATH_MAX+1];
+ int n;
+#ifdef resolve_symlinks
+ char *buf;
+ int m;
+#endif
+
+ npath = resolved_path;
+
+ /* If it's a relative pathname use getcwd for starters. */
+ if (*path != '/') {
+ if (!getcwd(npath, maxreslth-2))
+ return NULL;
+ npath += strlen(npath);
+ if (npath[-1] != '/')
+ *npath++ = '/';
+ } else {
+ *npath++ = '/';
+ path++;
+ }
+
+ /* Expand each slash-separated pathname component. */
+ while (*path != '\0') {
+ /* Ignore stray "/" */
+ if (*path == '/') {
+ path++;
+ continue;
+ }
+ if (*path == '.' && (path[1] == '\0' || path[1] == '/')) {
+ /* Ignore "." */
+ path++;
+ continue;
+ }
+ if (*path == '.' && path[1] == '.' &&
+ (path[2] == '\0' || path[2] == '/')) {
+ /* Backup for ".." */
+ path += 2;
+ while (npath > resolved_path+1 &&
+ (--npath)[-1] != '/')
+ ;
+ continue;
+ }
+ /* Safely copy the next pathname component. */
+ while (*path != '\0' && *path != '/') {
+ if (npath-resolved_path > maxreslth-2) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+ *npath++ = *path++;
+ }
+
+ /* Protect against infinite loops. */
+ if (readlinks++ > MAX_READLINKS) {
+ errno = ELOOP;
+ return NULL;
+ }
+
+ /* See if last pathname component is a symlink. */
+ *npath = '\0';
+ n = readlink(resolved_path, link_path, PATH_MAX);
+ if (n < 0) {
+ /* EINVAL means the file exists but isn't a symlink. */
+ if (errno != EINVAL)
+ return NULL;
+ } else {
+#ifdef resolve_symlinks /* Richard Gooch dislikes sl resolution */
+ /* Note: readlink doesn't add the null byte. */
+ link_path[n] = '\0';
+ if (*link_path == '/')
+ /* Start over for an absolute symlink. */
+ npath = resolved_path;
+ else
+ /* Otherwise back up over this component. */
+ while (*(--npath) != '/')
+ ;
+
+ /* Insert symlink contents into path. */
+ m = strlen(path);
+ buf = xmalloc(m + n + 1);
+ memcpy(buf, link_path, n);
+ memcpy(buf + n, path, m + 1);
+ path = buf;
+#endif
+ }
+ *npath++ = '/';
+ }
+ /* Delete trailing slash but don't whomp a lone slash. */
+ if (npath != resolved_path+1 && npath[-1] == '/')
+ npath--;
+ /* Make sure it's null terminated. */
+ *npath = '\0';
+ return resolved_path;
+}
Added: trunk/mount.ocfs2/realpath.h
===================================================================
--- trunk/mount.ocfs2/realpath.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/realpath.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1 @@
+extern char *myrealpath(const char *path, char *resolved_path, int m);
Added: trunk/mount.ocfs2/sundries.c
===================================================================
--- trunk/mount.ocfs2/sundries.c 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/sundries.c 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,287 @@
+/*
+ * Support functions. Exported functions are prototyped in sundries.h.
+ * sundries.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ *
+ * added fcntl locking by Kjetil T. (kjetilho at math.uio.no) - aeb, 950927
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at pld.ORG.PL>
+ * - added Native Language Support
+ *
+ */
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <mntent.h> /* for MNTTYPE_SWAP */
+#include "fstab.h"
+#include "sundries.h"
+#include "realpath.h"
+//#include "nfsmount.h"
+#include "nls.h"
+
+void *
+xmalloc (size_t size) {
+ void *t;
+
+ if (size == 0)
+ return NULL;
+
+ t = malloc (size);
+ if (t == NULL)
+ die (EX_SYSERR, _("not enough memory"));
+
+ return t;
+}
+
+char *
+xstrdup (const char *s) {
+ char *t;
+
+ if (s == NULL)
+ return NULL;
+
+ t = strdup (s);
+
+ if (t == NULL)
+ die (EX_SYSERR, _("not enough memory"));
+
+ return t;
+}
+
+char *
+xstrndup (const char *s, int n) {
+ char *t;
+
+ if (s == NULL)
+ die (EX_SOFTWARE, _("bug in xstrndup call"));
+
+ t = xmalloc(n+1);
+ strncpy(t,s,n);
+ t[n] = 0;
+
+ return t;
+}
+
+char *
+xstrconcat2 (const char *s, const char *t) {
+ char *res;
+
+ if (!s) s = "";
+ if (!t) t = "";
+ res = xmalloc(strlen(s) + strlen(t) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ return res;
+}
+
+char *
+xstrconcat3 (const char *s, const char *t, const char *u) {
+ char *res;
+
+ if (!s) s = "";
+ if (!t) t = "";
+ if (!u) u = "";
+ res = xmalloc(strlen(s) + strlen(t) + strlen(u) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ strcat(res, u);
+ return res;
+}
+
+char *
+xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
+ char *res;
+
+ if (!s) s = "";
+ if (!t) t = "";
+ if (!u) u = "";
+ if (!v) v = "";
+ res = xmalloc(strlen(s) + strlen(t) + strlen(u) + strlen(v) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ strcat(res, u);
+ strcat(res, v);
+ return res;
+}
+
+/* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
+void
+block_signals (int how) {
+ sigset_t sigs;
+
+ sigfillset (&sigs);
+ sigdelset(&sigs, SIGTRAP);
+ sigdelset(&sigs, SIGSEGV);
+ sigprocmask (how, &sigs, (sigset_t *) 0);
+}
+
+
+/* Non-fatal error. Print message and return. */
+/* (print the message in a single printf, in an attempt
+ to avoid mixing output of several threads) */
+void
+error (const char *fmt, ...) {
+ va_list args;
+ char *fmt2;
+
+ if (mount_quiet)
+ return;
+ fmt2 = xstrconcat2 (fmt, "\n");
+ va_start (args, fmt);
+ vfprintf (stderr, fmt2, args);
+ va_end (args);
+ free (fmt2);
+}
+
+/* Fatal error. Print message and exit. */
+void
+die (int err, const char *fmt, ...) {
+ va_list args;
+
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+
+ unlock_mtab ();
+ exit (err);
+}
+
+/* True if fstypes match. Null *TYPES means match anything,
+ except that swap types always return false. */
+/* Accept nonfs,proc,devpts and nonfs,noproc,nodevpts
+ with the same meaning. */
+int
+matching_type (const char *type, const char *types) {
+ int no; /* negated types list */
+ int len;
+ const char *p;
+
+ if (streq (type, MNTTYPE_SWAP))
+ return 0;
+ if (types == NULL)
+ return 1;
+
+ no = 0;
+ if (!strncmp(types, "no", 2)) {
+ no = 1;
+ types += 2;
+ }
+
+ /* Does type occur in types, separated by commas? */
+ len = strlen(type);
+ p = types;
+ while(1) {
+ if (!strncmp(p, "no", 2) && !strncmp(p+2, type, len) &&
+ (p[len+2] == 0 || p[len+2] == ','))
+ return 0;
+ if (strncmp(p, type, len) == 0 &&
+ (p[len] == 0 || p[len] == ','))
+ return !no;
+ p = index(p,',');
+ if (!p)
+ break;
+ p++;
+ }
+ return no;
+}
+
+/* Returns 1 if needle found or noneedle not found in haystack
+ * Otherwise returns 0
+ */
+static int
+check_option(const char *haystack, const char *needle) {
+ const char *p, *r;
+ int len, needle_len, this_len;
+ int no;
+
+ no = 0;
+ if (!strncmp(needle, "no", 2)) {
+ no = 1;
+ needle += 2;
+ }
+ needle_len = strlen(needle);
+ len = strlen(haystack);
+
+ for (p = haystack; p < haystack+len; p++) {
+ r = strchr(p, ',');
+ if (r) {
+ this_len = r-p;
+ } else {
+ this_len = strlen(p);
+ }
+ if (this_len != needle_len) {
+ p += this_len;
+ continue;
+ }
+ if (strncmp(p, needle, this_len) == 0)
+ return !no; /* foo or nofoo was found */
+ p += this_len;
+ }
+
+ return no; /* foo or nofoo was not found */
+}
+
+
+/* Returns 1 if each of the test_opts options agrees with the entire
+ * list of options.
+ * Returns 0 if any noopt is found in test_opts and opt is found in options.
+ * Returns 0 if any opt is found in test_opts but is not found in options.
+ * Unlike fs type matching, nonetdev,user and nonetdev,nouser have
+ * DIFFERENT meanings; each option is matched explicitly as specified.
+ */
+int
+matching_opts (const char *options, const char *test_opts) {
+ const char *p, *r;
+ char *q;
+ int len, this_len;
+
+ if (test_opts == NULL)
+ return 1;
+
+ len = strlen(test_opts);
+ q = alloca(len+1);
+ if (q == NULL)
+ die (EX_SYSERR, _("not enough memory"));
+
+ for (p = test_opts; p < test_opts+len; p++) {
+ r = strchr(p, ',');
+ if (r) {
+ this_len = r-p;
+ } else {
+ this_len = strlen(p);
+ }
+ if (!this_len) continue; /* if two ',' appear in a row */
+ strncpy(q, p, this_len);
+ q[this_len] = '\0';
+ if (!check_option(options, q))
+ return 0; /* any match failure means failure */
+ p += this_len;
+ }
+
+ /* no match failures in list means success */
+ return 1;
+}
+
+/* Make a canonical pathname from PATH. Returns a freshly malloced string.
+ It is up the *caller* to ensure that the PATH is sensible. i.e.
+ canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
+ is not a legal pathname for ``/dev/fd0''. Anything we cannot parse
+ we return unmodified. */
+char *
+canonicalize (const char *path) {
+ char *canonical;
+
+ if (path == NULL)
+ return NULL;
+
+ if (streq(path, "none") || streq(path, "proc") || streq(path, "devpts"))
+ return xstrdup(path);
+
+ canonical = xmalloc (PATH_MAX+2);
+
+ if (myrealpath (path, canonical, PATH_MAX+1))
+ return canonical;
+
+ free(canonical);
+ return xstrdup(path);
+}
Added: trunk/mount.ocfs2/sundries.h
===================================================================
--- trunk/mount.ocfs2/sundries.h 2005-03-15 23:04:40 UTC (rev 641)
+++ trunk/mount.ocfs2/sundries.h 2005-03-15 23:25:37 UTC (rev 642)
@@ -0,0 +1,54 @@
+/*
+ * sundries.h
+ * Support function prototypes. Functions are in sundries.c.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#if !defined(bool_t) && !defined(__GLIBC__)
+#include <rpc/types.h>
+#endif
+
+extern int mount_quiet;
+extern int verbose;
+extern int sloppy;
+
+#define streq(s, t) (strcmp ((s), (t)) == 0)
+
+/* Functions in sundries.c that are used in mount.c and umount.c */
+void block_signals (int how);
+char *canonicalize (const char *path);
+void error (const char *fmt, ...);
+int matching_type (const char *type, const char *types);
+int matching_opts (const char *options, const char *test_opts);
+void *xmalloc (size_t size);
+char *xstrdup (const char *s);
+char *xstrndup (const char *s, int n);
+char *xstrconcat2 (const char *, const char *);
+char *xstrconcat3 (const char *, const char *, const char *);
+char *xstrconcat4 (const char *, const char *, const char *, const char *);
+
+void die (int errcode, const char *fmt, ...);
+
+#ifdef HAVE_NFS
+int nfsmount (const char *spec, const char *node, int *flags,
+ char **orig_opts, char **opt_args, int *version, int running_bg);
+int nfs4mount (const char *spec, const char *node, int *flags,
+ char **orig_opts, char **opt_args, int running_bg);
+int nfsumount(const char *spec, const char *opts);
+#endif
+
+/* exit status - bits below are ORed */
+#define EX_USAGE 1 /* incorrect invocation or permission */
+#define EX_SYSERR 2 /* out of memory, cannot fork, ... */
+#define EX_SOFTWARE 4 /* internal mount bug or wrong version */
+#define EX_USER 8 /* user interrupt */
+#define EX_FILEIO 16 /* problems writing, locking, ... mtab/fstab */
+#define EX_FAIL 32 /* mount failure */
+#define EX_SOMEOK 64 /* some mount succeeded */
+
+#define EX_BG 256 /* retry in background (internal only) */
More information about the Ocfs2-tools-commits
mailing list