strcat(*data, opt);
}
-static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
+static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
char **mntdata)
{
char *s, *data;
char *p, *saveptr = NULL;
- if (!mntent->mnt_opts)
+ *mntdata = NULL;
+
+ if (!mntopts)
return 0;
- s = strdup(mntent->mnt_opts);
+ s = strdup(mntopts);
if (!s) {
SYSERROR("failed to allocate memory");
return -1;
return 0;
}
-static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file)
+static int mount_entry(const char *fsname, const char *target,
+ const char *fstype, unsigned long mountflags,
+ const char *data)
+{
+ if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
+ SYSERROR("failed to mount '%s' on '%s'", fsname, target);
+ return -1;
+ }
+
+ if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
+
+ DEBUG("remounting %s on %s to respect bind or remount options",
+ fsname, target);
+
+ if (mount(fsname, target, fstype,
+ mountflags | MS_REMOUNT, data)) {
+ SYSERROR("failed to mount '%s' on '%s'",
+ fsname, target);
+ return -1;
+ }
+ }
+
+ DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
+
+ return 0;
+}
+
+static inline int mount_entry_on_systemfs(struct mntent *mntent)
{
- struct mntent *mntent;
- int ret = -1;
unsigned long mntflags;
char *mntdata;
+ int ret;
+
+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
+ return -1;
+ }
+
+ ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
+ mntent->mnt_type, mntflags, mntdata);
+
+ free(mntdata);
+
+ return ret;
+}
+
+static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
+ const char *rootfs)
+{
char path[MAXPATHLEN];
- const char *mntdir, *mntroot;
+ unsigned long mntflags;
+ char *mntdata;
+ int ret;
- while ((mntent = getmntent(file))) {
+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
+ return -1;
+ }
- mntflags = 0;
- mntdata = NULL;
+ if (strncmp(mntent->mnt_dir, rootfs, strlen(rootfs)))
+ WARN("mount target directory '%s' is outside "
+ "container root", mntent->mnt_dir);
+ else
+ WARN("mount target directory '%s' is not "
+ "relative to container root", mntent->mnt_dir);
- if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
- ERROR("failed to parse mount option '%s'",
- mntent->mnt_opts);
- goto out;
- }
+ ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir, mntent->mnt_type,
+ mntflags, mntdata);
- /* now figure out where to mount it to. */
- mntdir = mntent->mnt_dir;
- mntroot = NULL;
+ free(mntdata);
+ return ret;
+}
- if (!rootfs->path) {
- /* if we use system root fs, the mount is relative to '/'
- * and can be absolute */
- if (mntdir[0] != '/')
- mntroot = ""; /* this is '/' */
- } else {
- /* else we have a separate root, mounts are
- * relative to it, and absolute paths are risky */
- if (mntdir[0] != '/')
- /* relative to root mount point */
- mntroot = rootfs->mount;
- else if (strncmp(mntdir, rootfs->mount,
- strlen(rootfs->mount)))
- WARN("mount target directory '%s' is outside "
- "container root", mntdir);
- else
- WARN("mount target directory '%s' is not "
- "relative to container root", mntdir);
- }
+static int mount_entry_on_relative_rootfs(struct mntent *mntent,
+ const char *rootfs)
+{
+ char path[MAXPATHLEN];
+ unsigned long mntflags;
+ char *mntdata;
+ int ret;
- if (mntroot) {
- /* make it relative to mntroot */
- snprintf(path, sizeof(path), "%s/%s", mntroot, mntdir);
- mntdir = path;
- }
+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
+ return -1;
+ }
- if (mount(mntent->mnt_fsname, mntdir,
- mntent->mnt_type, mntflags & ~MS_REMOUNT, mntdata)) {
- SYSERROR("failed to mount '%s' on '%s'",
- mntent->mnt_fsname, mntent->mnt_dir);
- goto out;
- }
+ /* relative to root mount point */
+ snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
+
+ ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
+ mntflags, mntdata);
+
+ free(mntdata);
- if ((mntflags & MS_REMOUNT) == MS_REMOUNT ||
- ((mntflags & MS_BIND) == MS_BIND)) {
+ return ret;
+}
+
+static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file)
+{
+ struct mntent *mntent;
+ int ret = -1;
- DEBUG ("remounting %s on %s to respect bind " \
- "or remount options",
- mntent->mnt_fsname, mntent->mnt_dir);
+ while ((mntent = getmntent(file))) {
- if (mount(mntent->mnt_fsname, mntent->mnt_dir,
- mntent->mnt_type,
- mntflags | MS_REMOUNT, mntdata)) {
- SYSERROR("failed to mount '%s' on '%s'",
- mntent->mnt_fsname, mntent->mnt_dir);
+ if (!rootfs->path) {
+ if (mount_entry_on_systemfs(mntent))
goto out;
- }
+ continue;
}
- DEBUG("mounted %s on %s, type %s", mntent->mnt_fsname,
- mntent->mnt_dir, mntent->mnt_type);
+ /* We have a separate root, mounts are relative to it */
+ if (mntent->mnt_dir[0] != '/') {
+ if (mount_entry_on_relative_rootfs(mntent,
+ rootfs->mount))
+ goto out;
+ continue;
+ }
- free(mntdata);
+ if (mount_entry_on_absolute_rootfs(mntent, rootfs->path))
+ goto out;
}
ret = 0;