[lxc-devel] [patch 4/6] [draft] Add separate interface for mounting fstab
Andrian Nord
nightnord at gmail.com
Mon Nov 16 22:27:35 UTC 2009
This patch adds mount.c mount.h files, which contains a functions for
parsing and mounting mount entries/files.
lxc_mount_line does not require lxc_conf, as it's intended to be used
from setup_mount_entries, which are already resolved into config
Signed-off-by: Andrian Nord <NightNord at gmail.com>
diff --git a/src/lxc/mount.c b/src/lxc/mount.c
new file mode 100644
index 0000000..1d2437d
--- /dev/null
+++ b/src/lxc/mount.c
@@ -0,0 +1,314 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <mntent.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/mount.h>
+
+#include "parse.h"
+#include "variables.h"
+
+#include <lxc/lxc.h>
+#include <lxc/log.h>
+
+lxc_log_define(lxc_mount, lxc);
+
+#ifndef MS_REC
+#define MS_REC 16384
+#endif
+
+struct parsing_state {
+ const char *file;
+ int line;
+ struct lxc_conf *lxc_conf;
+};
+
+struct mount_opt {
+ char *name;
+ int clear;
+ int flag;
+};
+
+static struct mount_opt mount_opt[] = {
+ { "defaults", 0, 0 },
+ { "ro", 0, MS_RDONLY },
+ { "rw", 1, MS_RDONLY },
+ { "suid", 1, MS_NOSUID },
+ { "nosuid", 0, MS_NOSUID },
+ { "dev", 1, MS_NODEV },
+ { "nodev", 0, MS_NODEV },
+ { "exec", 1, MS_NOEXEC },
+ { "noexec", 0, MS_NOEXEC },
+ { "sync", 0, MS_SYNCHRONOUS },
+ { "async", 1, MS_SYNCHRONOUS },
+ { "remount", 0, MS_REMOUNT },
+ { "mand", 0, MS_MANDLOCK },
+ { "nomand", 1, MS_MANDLOCK },
+ { "atime", 1, MS_NOATIME },
+ { "noatime", 0, MS_NOATIME },
+ { "diratime", 1, MS_NODIRATIME },
+ { "nodiratime", 0, MS_NODIRATIME },
+ { "bind", 0, MS_BIND },
+ { "rbind", 0, MS_BIND|MS_REC },
+ { NULL, 0, 0 },
+};
+
+static void parse_mntopt(char *opt, unsigned long *flags, char **data)
+{
+ struct mount_opt *mo;
+
+ /* If opt is found in mount_opt, set or clear flags.
+ * Otherwise append it to data. */
+
+ for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
+ if (!strncmp(opt, mo->name, strlen(mo->name))) {
+ if (mo->clear)
+ *flags &= ~mo->flag;
+ else
+ *flags |= mo->flag;
+ return;
+ }
+ }
+
+ if (strlen(*data))
+ strcat(*data, ",");
+ strcat(*data, opt);
+}
+
+static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
+ char **mntdata)
+{
+ char *s, *data;
+ char *p, *saveptr = NULL;
+
+ if (!mntent->mnt_opts)
+ return 0;
+
+ s = strdup(mntent->mnt_opts);
+ if (!s) {
+ SYSERROR("failed to allocate memory");
+ return -1;
+ }
+
+ data = malloc(strlen(s) + 1);
+ if (!data) {
+ SYSERROR("failed to allocate memory");
+ free(s);
+ return -1;
+ }
+ *data = 0;
+
+ for (p = strtok_r(s, ",", &saveptr); p != NULL;
+ p = strtok_r(NULL, ",", &saveptr))
+ parse_mntopt(p, mntflags, &data);
+
+ if (*data)
+ *mntdata = data;
+ else
+ free(data);
+ free(s);
+
+ return 0;
+}
+
+static int mount_entry(struct mntent *mntent)
+{
+ unsigned long mntflags;
+ char *mntdata;
+
+ int ret = -1;
+
+ mntflags = 0;
+ mntdata = NULL;
+
+ if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
+ goto out;
+ }
+
+ if (mount(mntent->mnt_fsname, mntent->mnt_dir,
+ mntent->mnt_type, mntflags, mntdata)) {
+ SYSERROR("failed to mount '%s' on '%s'",
+ mntent->mnt_fsname, mntent->mnt_dir);
+ goto free;
+ }
+
+ DEBUG("mounted %s on %s, type %s", mntent->mnt_fsname,
+ mntent->mnt_dir, mntent->mnt_type);
+
+ ret = 0;
+free:
+ free(mntdata);
+out:
+ return ret;
+}
+
+static void mntent_free(struct mntent* mntent)
+{
+ if (mntent->mnt_opts)
+ free(mntent->mnt_opts);
+
+ if (mntent->mnt_type)
+ free(mntent->mnt_type);
+
+ if (mntent->mnt_dir)
+ free(mntent->mnt_dir);
+
+ if (mntent->mnt_fsname)
+ free(mntent->mnt_fsname);
+
+ free(mntent);
+}
+
+static int parse_mount_line(char *line, struct mntent **mntent)
+{
+ struct mntent *entry;
+
+ int ret = -1;
+ int anchor = 0, length = strlen(line);
+ char *token;
+ int toknum = 0;
+ int *int_holder = NULL;
+
+ *mntent = NULL;
+
+ if (lxc_is_line_empty(line))
+ return 0;
+
+ entry = malloc(sizeof(struct mntent));
+
+ if (!entry) {
+ SYSERROR("failed to allocate memory");
+ goto out;
+ }
+
+ memset(entry, 0, sizeof(struct mntent));
+
+ while ((token = lxc_next_token(line, &anchor, length))) {
+ if ( *token == '#' )
+ break;
+
+ toknum++;
+
+ switch (toknum) {
+ case 1: entry->mnt_fsname = token; break;
+ case 2: entry->mnt_dir = token; break;
+ case 3: entry->mnt_type = token; break;
+ case 4: entry->mnt_opts = token; break;
+ case 5:
+ int_holder = &entry->mnt_freq;
+ case 6:
+ if (!int_holder)
+ int_holder = &entry->mnt_passno;
+
+ if (sscanf(token, "%u", int_holder) < 0) {
+ ERROR("invalid integer '%s'", token);
+ goto fail;
+ }
+
+ int_holder = NULL;
+ break;
+ }
+ }
+
+ if (toknum == 0) {
+ ret = 0;
+ goto fail;
+ } else if (toknum < 6) {
+ ERROR("too less columns into '%s': %u", line, toknum - 1);
+ goto fail;
+ } else if (toknum > 6) {
+ ERROR("garbage at the end of string '%s'", line);
+ goto fail;
+ }
+
+ ret = 0;
+ *mntent = entry;
+
+ goto out;
+fail:
+ mntent_free(entry);
+out:
+ return ret;
+}
+
+int lxc_mount_line(char *line)
+{
+ struct mntent *mntent;
+ int ret = -1;
+
+ if (parse_mount_line(line, &mntent)) {
+ ERROR("parsing of line '%s' failed", line);
+ return ret;
+ }
+
+ if (!mntent)
+ return 0;
+
+ if (mount_entry(mntent)) {
+ ERROR("'%s' entry mount failed", line);
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ free(mntent);
+
+ return ret;
+}
+
+static int parse_fstab_line(void *buffer, void *data)
+{
+ struct parsing_state *state = data;
+ char *line;
+
+ if (lxc_resolve_variables(buffer, &line, state->lxc_conf)) {
+ ERROR("%s: %u: variable resolving failed",
+ state->file, state->line);
+
+ return -1;
+ }
+
+ state->line++;
+
+ return lxc_mount_line(line);
+}
+
+int lxc_mount_fstab(const char *fstab, struct lxc_conf *lxc_conf)
+{
+ char buffer[MAXPATHLEN];
+
+ struct parsing_state state = {
+ .file = fstab,
+ .line = 1,
+ .lxc_conf = lxc_conf
+ };
+
+ return lxc_file_for_each_line(fstab, parse_fstab_line,
+ buffer, MAXPATHLEN, &state);
+
+}
diff --git a/src/lxc/mount.h b/src/lxc/mount.h
new file mode 100644
index 0000000..c6c6983
--- /dev/null
+++ b/src/lxc/mount.h
@@ -0,0 +1,27 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+struct lxc_conf;
+
+extern int lxc_mount_fstab(const char *file, struct lxc_conf *conf);
+extern int lxc_mount_line(char *line);
More information about the lxc-devel
mailing list