]> git.ipfire.org Git - people/ms/pakfire.git/blobdiff - src/libpakfire/mount.c
mount: Make changing mount operation not dependant on pakfire
[people/ms/pakfire.git] / src / libpakfire / mount.c
index 321d702d8f321a32c74c27444fd1dd2a616ceb7d..494c25852921b3dd166f6ccc91933449586a508d 100644 (file)
@@ -32,8 +32,9 @@
 #include <pakfire/arch.h>
 #include <pakfire/logging.h>
 #include <pakfire/pakfire.h>
-#include <pakfire/private.h>
+#include <pakfire/path.h>
 #include <pakfire/mount.h>
+#include <pakfire/string.h>
 #include <pakfire/util.h>
 
 static const struct pakfire_mountpoint {
@@ -79,6 +80,10 @@ static const struct pakfire_mountpoint {
        { "pakfire_dev_pts",     "dev/pts",            "devpts", MS_NOSUID|MS_NOEXEC,
                "newinstance,ptmxmode=0666,mode=620", },
 
+       // Create a new /dev/shm
+       { "pakfire_dev_shm",     "dev/shm",            "tmpfs",
+               MS_NOSUID|MS_NODEV|MS_STRICTATIME, "mode=1777,size=1024m", },
+
        // Mount /dev/mqueue
        { "mqueue",               "dev/mqueue",        "mqueue",
                MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL },
@@ -89,7 +94,7 @@ static const struct pakfire_mountpoint {
 
        // Create a new /tmp
        { "pakfire_tmp",          "tmp",               "tmpfs",
-               MS_NOSUID|MS_NODEV|MS_STRICTATIME, "mode=1777,size=1024m", },
+               MS_NOSUID|MS_NODEV|MS_STRICTATIME, "mode=1777,size=4096m", },
 
        // The end
        { NULL },
@@ -100,16 +105,29 @@ static const struct pakfire_devnode {
        int major;
        int minor;
        mode_t mode;
+       int flags;
 } devnodes[] = {
-       { "/dev/null",      1,  3, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/zero",      1,  5, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/full",      1,  7, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/random",    1,  8, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
-       { "/dev/urandom",   1,  9, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
-       { "/dev/kmsg",      1, 11, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
-       { "/dev/tty",       5,  0, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/console",   5,  1, S_IFCHR|S_IRUSR|S_IWUSR, },
-       { "/dev/rtc0",    252,  0, S_IFCHR|S_IRUSR|S_IWUSR, },
+       { "/dev/null",      1,  3, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, 0 },
+       { "/dev/zero",      1,  5, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, 0 },
+       { "/dev/full",      1,  7, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, 0 },
+       { "/dev/random",    1,  8, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, 0 },
+       { "/dev/urandom",   1,  9, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, 0 },
+       { "/dev/kmsg",      1, 11, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, 0 },
+       { "/dev/tty",       5,  0, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, 0 },
+       { "/dev/console",   5,  1, S_IFCHR|S_IRUSR|S_IWUSR, 0 },
+       { "/dev/rtc0",    252,  0, S_IFCHR|S_IRUSR|S_IWUSR, 0 },
+
+       // Loop Devices
+       { "/dev/loop-control", 10, 237, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop0",         7,   0, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop1",         7,   1, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop2",         7,   2, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop3",         7,   3, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop4",         7,   4, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop5",         7,   5, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop6",         7,   6, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+       { "/dev/loop7",         7,   7, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, PAKFIRE_MOUNT_LOOP_DEVICES },
+
        { NULL },
 };
 
@@ -126,6 +144,50 @@ static const struct pakfire_symlink {
        { NULL },
 };
 
+int pakfire_mount_change_propagation(struct pakfire_ctx* ctx, const char* path, int propagation) {
+       CTX_DEBUG(ctx, "Changing mount propagation on %s\n", path);
+
+       int r = mount(NULL, path, NULL, propagation|MS_REC, NULL);
+       if (r)
+               CTX_ERROR(ctx, "Failed to change mount propagation on %s: %m\n", path);
+
+       return r;
+}
+
+static int pakfire_mount_is_mountpoint(struct pakfire* pakfire, const char* path) {
+       // XXX THIS STILL NEEDS TO BE IMPLEMENTED
+       return 1;
+}
+
+int pakfire_mount_make_mounpoint(struct pakfire* pakfire, const char* path) {
+       int r;
+
+       // Check if path already is a mountpoint
+       r = pakfire_mount_is_mountpoint(pakfire, path);
+       switch (r) {
+               // Already is a mountpoint
+               case 0:
+                       return 0;
+
+               // Is not a mountpoint
+               case 1:
+                       break;
+
+               default:
+                       ERROR(pakfire, "Could not determine whether %s is a mountpoint: %m\n", path);
+                       return r;
+       }
+
+       // Bind-mount to self
+       r = mount(path, path, NULL, MS_BIND|MS_REC, NULL);
+       if (r) {
+               ERROR(pakfire, "Could not make %s a mountpoint: %m\n", path);
+               return r;
+       }
+
+       return 0;
+}
+
 /*
        Easy way to iterate through all mountpoints
 */
@@ -211,27 +273,6 @@ static int pakfire_mount(struct pakfire* pakfire, const char* source, const char
        return r;
 }
 
-static int pakfire_umount(struct pakfire* pakfire, const char* path, int flags) {
-       int r;
-
-       DEBUG(pakfire, "Umounting %s\n", path);
-
-RETRY:
-       // Perform umount
-       r = umount2(path, flags);
-       if (r) {
-               // Attempt a lazy umount when busy
-               if (errno == EBUSY) {
-                       flags |= MNT_DETACH;
-                       goto RETRY;
-               }
-
-               ERROR(pakfire, "Could not umount %s: %m\n", path);
-       }
-
-       return r;
-}
-
 static int __pakfire_mount_print(struct pakfire* pakfire,
                struct libmnt_fs* fs, const void* data) {
        DEBUG(pakfire,
@@ -252,16 +293,20 @@ int pakfire_mount_list(struct pakfire* pakfire) {
                __pakfire_mount_print, NULL);
 }
 
-static int pakfire_populate_dev(struct pakfire* pakfire) {
+static int pakfire_populate_dev(struct pakfire* pakfire, int flags) {
        char path[PATH_MAX];
 
        // Create device nodes
        for (const struct pakfire_devnode* devnode = devnodes; devnode->path; devnode++) {
                DEBUG(pakfire, "Creating device node %s\n", devnode->path);
 
-               int r = pakfire_make_path(pakfire, path, devnode->path);
-               if (r < 0)
-                       return 1;
+               // Check if flags match
+               if (devnode->flags && !(flags & devnode->flags))
+                       continue;
+
+               int r = pakfire_path(pakfire, path, "%s", devnode->path);
+               if (r)
+                       return r;
 
                dev_t dev = makedev(devnode->major, devnode->minor);
 
@@ -290,7 +335,7 @@ MOUNT:
                }
 
                // Create a bind-mount over the file
-               r = pakfire_mount(pakfire, path, devnode->path, "bind", MS_BIND, NULL);
+               r = pakfire_mount(pakfire, devnode->path, path, "bind", MS_BIND, NULL);
                if (r)
                        return r;
        }
@@ -299,9 +344,9 @@ MOUNT:
        for (const struct pakfire_symlink* s = symlinks; s->target; s++) {
                DEBUG(pakfire, "Creating symlink %s -> %s\n", s->path, s->target);
 
-               int r = pakfire_make_path(pakfire, path, s->path);
-               if (r < 0)
-                       return 1;
+               int r = pakfire_path(pakfire, path, "%s", s->path);
+               if (r)
+                       return r;
 
                r = symlink(s->target, path);
                if (r) {
@@ -317,7 +362,7 @@ static int pakfire_mount_interpreter(struct pakfire* pakfire) {
        char target[PATH_MAX];
 
        // Fetch the target architecture
-       const char* arch = pakfire_get_arch(pakfire);
+       const char* arch = pakfire_get_effective_arch(pakfire);
 
        // Can we emulate this architecture?
        char* interpreter = pakfire_arch_find_interpreter(arch);
@@ -329,8 +374,8 @@ static int pakfire_mount_interpreter(struct pakfire* pakfire) {
        DEBUG(pakfire, "Mounting interpreter %s for %s\n", interpreter, arch);
 
        // Where to mount this?
-       int r = pakfire_make_path(pakfire, target, interpreter);
-       if (r < 0)
+       int r = pakfire_path(pakfire, target, "%s", interpreter);
+       if (r)
                return r;
 
        // Create directory
@@ -351,7 +396,7 @@ static int pakfire_mount_interpreter(struct pakfire* pakfire) {
        return r;
 }
 
-int pakfire_mount_all(struct pakfire* pakfire) {
+int pakfire_mount_all(struct pakfire* pakfire, int flags) {
        char target[PATH_MAX];
        int r;
 
@@ -360,34 +405,27 @@ int pakfire_mount_all(struct pakfire* pakfire) {
 
        for (const struct pakfire_mountpoint* mp = mountpoints; mp->source; mp++) {
                // Figure out where to mount
-               r = pakfire_path_join(target, root, mp->target);
-               if (r < 0)
+               r = pakfire_path_append(target, root, mp->target);
+               if (r)
                        return r;
 
-               // Create target
-               pakfire_mkdir(target, 0755);
+               // Create target if it doesn't exist
+               if (!pakfire_path_exists(target)) {
+                       r = pakfire_mkdir(target, 0755);
+                       if (r) {
+                               ERROR(pakfire, "Could not create %s: %m\n", target);
+                               return r;
+                       }
+               }
 
-RETRY:
                // Perform mount()
                r = pakfire_mount(pakfire, mp->source, target, mp->fstype, mp->flags, mp->options);
-               if (r) {
-                       // If the target directory does not exist, we will create it
-                       if (errno == ENOENT) {
-                               r = pakfire_mkdir(target, 0755);
-                               if (r) {
-                                       ERROR(pakfire, "Could not create %s\n", target);
-                                       return r;
-                               }
-
-                               goto RETRY;
-                       }
-
+               if (r)
                        return r;
-               }
        }
 
        // Populate /dev
-       r = pakfire_populate_dev(pakfire);
+       r = pakfire_populate_dev(pakfire, flags);
        if (r)
                return r;
 
@@ -399,33 +437,36 @@ RETRY:
        return 0;
 }
 
-static int __pakfire_umount(struct pakfire* pakfire,
-               struct libmnt_fs* fs, const void* data) {
-       const char* target = mnt_fs_get_target(fs);
-       if (!target)
-               return 1;
+int pakfire_make_ramdisk(struct pakfire* pakfire, char* path, const char* args) {
+       int r;
 
-       return pakfire_umount(pakfire, target, 0);
-}
+       // Create a new temporary directory
+       char* p = pakfire_mkdtemp(path);
+       if (!p)
+               return -errno;
 
-/*
-       umounts everything that hasn't been umounted, yet
-*/
-int pakfire_umount_all(struct pakfire* pakfire) {
-       return pakfire_mount_foreach(pakfire, MNT_ITER_BACKWARD,
-               __pakfire_umount, NULL);
+       // Mount the ramdisk
+       r = pakfire_mount(pakfire, "pakfire_ramdisk", p, "tmpfs", 0, args);
+       if (r) {
+               ERROR_ERRNO(pakfire, r, "Could not mount ramdisk at %s (%s): %m\n", p, args);
+               return r;
+       }
+
+       DEBUG(pakfire, "Ramdisk mounted at %s (%s)\n", p, args);
+
+       return 0;
 }
 
-PAKFIRE_EXPORT int pakfire_bind(struct pakfire* pakfire, const char* src, const char* dst, int flags) {
+int pakfire_bind(struct pakfire* pakfire, const char* src, const char* dst, int flags) {
        struct stat st;
        char mountpoint[PATH_MAX];
 
        if (!dst)
                dst = src;
 
-       int r = pakfire_make_path(pakfire, mountpoint, dst);
-       if (r < 0)
-               return 1;
+       int r = pakfire_path(pakfire, mountpoint, "%s", dst);
+       if (r)
+               return r;
 
        DEBUG(pakfire, "Bind-mounting %s to %s\n", src, mountpoint);
 
@@ -462,6 +503,18 @@ PAKFIRE_EXPORT int pakfire_bind(struct pakfire* pakfire, const char* src, const
                        return 1;
        }
 
+       // The Linux kernel seems to be quite funny when trying to bind-mount something
+       // as read-only and requires us to mount the source first, and then remount it
+       // again using MS_RDONLY.
+       if (flags & MS_RDONLY) {
+               r = pakfire_mount(pakfire, src, mountpoint, "bind", MS_BIND|MS_REC, NULL);
+               if (r)
+                       return r;
+
+               // Add the remount flag
+               flags |= MS_REMOUNT;
+       }
+
        // Perform mount
-       return pakfire_mount(pakfire, src, mountpoint, NULL, flags|MS_BIND, NULL);
+       return pakfire_mount(pakfire, src, mountpoint, "bind", flags|MS_BIND|MS_REC, NULL);
 }