]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxccontainer: add handling of file mounts
authorLiza Tretyakova <elizabet.tretyakova@gmail.com>
Tue, 15 May 2018 09:36:10 +0000 (12:36 +0300)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sun, 22 Jul 2018 13:33:51 +0000 (15:33 +0200)
Signed-off-by: Liza Tretyakova <elizabet.tretyakova@gmail.com>
src/lxc/lxccontainer.c

index 0a70d7f9ab28aa2d657176b8d7c566003f7aba37..5e2a19b24844fde6c70c4186d469f5bb51dfc744 100644 (file)
@@ -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);