[lxc-devel] [patch 4/6] [draft] Add separate interface for mounting

Andrian Nord nightnord at gmail.com
Tue Nov 17 23:26:06 UTC 2009


Update for new git head. Also, memory leak when using simple free on
mntent is fixed.

Reason why it's included into variables patchset, is that multifstab is
unusable by it's own, as you may specify only static data. Situation
with lxc.mount.entry is better, as for their resolution you need only
confile change, but, as for me, fstab's are better =)

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