[lxc-devel] [patch 4/7] Add separate mount interface

Andrian Nord nightnord at gmail.com
Mon Dec 7 10:46:29 UTC 2009


This is parsing interface for mount procedures. Usage of mntent is
dropped, as it could not be used without file. Still, mntent structure
is used and fully completed. This is probably redundant, as correctly
stated by Michael Tokarev. It could be replaced in different ways, one
of which is composite-types into configuration file. That should be
discussed separately, probably into bugzilla.

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..6c6ed22
--- /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 <sys/param.h>
+
+#include "parse.h"
+#include "variables.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:
+	mntent_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,
+							sizeof(buffer), &state);
+
+}
diff --git a/src/lxc/mount.h b/src/lxc/mount.h
new file mode 100644
index 0000000..9465f52
--- /dev/null
+++ b/src/lxc/mount.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+ */
+
+#ifndef __mount_h
+#define __mount_h
+
+struct lxc_conf;
+
+extern int lxc_mount_fstab(const char *file, struct lxc_conf *conf);
+extern int lxc_mount_line(char *line);
+
+#endif




More information about the lxc-devel mailing list