From: Liza Tretyakova Date: Tue, 15 May 2018 09:36:10 +0000 (+0300) Subject: lxccontainer: add handling of file mounts X-Git-Tag: lxc-3.1.0~195^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c6885c3f247528c65402d1c4362afd977bdae95a;p=thirdparty%2Flxc.git lxccontainer: add handling of file mounts Signed-off-by: Liza Tretyakova --- diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 0a70d7f9a..5e2a19b24 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -390,6 +390,84 @@ on_error: return ret; } +static int ensure_dir(const char *dest) { + struct stat sb; + int ret = -1; + + if (stat(dest, &sb) == 0) { + if ((sb.st_mode & S_IFMT) == S_IFDIR) + return 0; + ret = unlink(dest); + if (ret < 0) { + SYSERROR("Failed to remove old \"%s\"", dest); + return ret; + } + } + + ret = mkdir(dest, 0755); + if (ret < 0) { + SYSERROR("Failed to mkdir \"%s\"", dest); + return ret; + } + + return 0; +} + +static int ensure_file(const char *dest) { + struct stat sb; + int fd, ret; + + if (stat(dest, &sb) == 0) { + if ((sb.st_mode & S_IFMT) != S_IFDIR) + return 0; + ret = rmdir(dest); + if (ret < 0) { + SYSERROR("Failed to remove old \"%s\"", dest); + return ret; + } + } + + fd = creat(dest, 0755); + if (fd < 0) { + SYSERROR("Failed to mkdir \"%s\"", dest); + return ret; + } + close(fd); + + return 0; +} + +/* @st_mode is the st_mode field of the stat(source) return struct */ +static int create_mount_target(mode_t st_mode, const char *dest) { + char *dirdup, *destdirname; + int ret = -1; + + dirdup = strdup(dest); + if (!dirdup) { + SYSERROR("Failed to duplicate target name"); + return ret; + } + + destdirname = dirname(dirdup); + + ret = mkdir_p(destdirname, 0755); + if (ret < 0) { + SYSERROR("failed to create path: %s", destdirname); + free(dirdup); + return ret; + } + free(dirdup); + + switch (st_mode & S_IFMT) { + case S_IFDIR: + ensure_dir(dest); + return 0; + default: + ensure_file(dest); + return 0; + } +} + #define WRAP_API(rettype, fnname) \ static rettype fnname(struct lxc_container *c) \ { \ @@ -4922,6 +5000,7 @@ static int do_lxcapi_mount(struct lxc_container *c, char template[MAXPATHLEN], path[MAXPATHLEN]; pid_t pid, init_pid; size_t len; + struct stat sb; int ret = -1, fd = -EBADF; if (!c || !c->lxc_conf) { @@ -4941,11 +5020,40 @@ static int do_lxcapi_mount(struct lxc_container *c, goto out; } - /* Create a temporary dir under the shared mountpoint */ - sret = mkdtemp(template); - if (!sret) { - SYSERROR("Could not create shmounts temporary dir"); - goto out; + /* Create a temporary file / dir under the shared mountpoint */ + if (!source || strcmp(source, "") == 0) { + /* If source is not specified, maybe we want to mount a filesystem? */ + sb.st_mode = S_IFDIR; + } else { + ret = stat(source, &sb); + if (ret < 0) { + SYSERROR("Error getting stat info about the source \"%s\"", source); + goto out; + } + } + + if ((sb.st_mode & S_IFMT) == S_IFDIR) { + sret = mkdtemp(template); + if (!sret) { + SYSERROR("Could not create shmounts temporary dir"); + goto out; + } + ret = chmod(template, 0); + if (ret < 0) { + SYSERROR("Could not chmod shmounts temporary dir \"%s\"", template); + goto out; + } + } else { + fd = lxc_make_tmpfile(template, false); + if (fd < 0) { + SYSERROR("Could not create shmounts temporary file"); + goto out; + } + ret = fchmod(fd, 0); + if (ret < 0) { + SYSERROR("Could not chmod shmounts temporary file"); + goto out; + } } /* Do the fork */ @@ -4959,7 +5067,7 @@ static int do_lxcapi_mount(struct lxc_container *c, /* Do the mount */ ret = mount(source, template, filesystemtype, mountflags, data); if (ret < 0) { - SYSERROR("Failed to mount \"%s\" onto \"%s\"", source, template); + SYSERROR("Failed to mount onto \"%s\"", template); _exit(EXIT_FAILURE); } @@ -4981,6 +5089,10 @@ static int do_lxcapi_mount(struct lxc_container *c, _exit(EXIT_FAILURE); } + ret = create_mount_target(sb.st_mode, target); + if (ret < 0) + _exit(EXIT_FAILURE); + suff = strrchr(template, '/'); if (!suff) _exit(EXIT_FAILURE); @@ -4992,12 +5104,6 @@ static int do_lxcapi_mount(struct lxc_container *c, _exit(EXIT_FAILURE); } - ret = mkdir_p(target, 0700); - if (ret < 0) { - ERROR("Failed to create container temp mountpoint"); - _exit(EXIT_FAILURE); - } - ret = mount(path, target, NULL, MS_REC | MS_MOVE, NULL); if (ret < 0) { SYSERROR("Failed to move the mount from \"%s\" to \"%s\"", path, target);