#include <pakfire/arch.h>
#include <pakfire/logging.h>
#include <pakfire/pakfire.h>
+#include <pakfire/parse.h>
+#include <pakfire/path.h>
#include <pakfire/mount.h>
#include <pakfire/string.h>
#include <pakfire/util.h>
// 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 },
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 },
};
{ 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
*/
return r;
}
-static int __pakfire_is_mountpoint(struct pakfire* pakfire,
- struct libmnt_fs* fs, const void* data) {
- const char* path = (const char*)data;
-
- return mnt_fs_streq_target(fs, path);
-}
-
-int pakfire_is_mountpoint(struct pakfire* pakfire, const char* path) {
- return pakfire_mount_foreach(pakfire, MNT_ITER_FORWARD,
- __pakfire_is_mountpoint, path);
-}
-
static int pakfire_mount(struct pakfire* pakfire, const char* source, const char* target,
const char* fstype, unsigned long mflags, const void* data) {
const char* options = (const char*)data;
return 0;
}
-int pakfire_mount_list(struct pakfire* pakfire) {
- DEBUG(pakfire, "Mountpoints:\n");
+static int __pakfire_mount_list(char* line, size_t length, void* data) {
+ struct pakfire_ctx* ctx = data;
+
+ // Send the line to the logger
+ CTX_DEBUG(ctx, " %.*s", (int)length, line);
+
+ return 0;
+}
+
+int pakfire_mount_list(struct pakfire_ctx* ctx) {
+ CTX_DEBUG(ctx, "Mountpoints:\n");
- return pakfire_mount_foreach(pakfire, MNT_ITER_FORWARD,
- __pakfire_mount_print, NULL);
+ return pakfire_parse_file("/proc/self/mounts", __pakfire_mount_list, ctx);
}
-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);
}
// 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;
}
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) {
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);
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
return r;
}
-int pakfire_mount_all(struct pakfire* pakfire) {
+int pakfire_mount_all(struct pakfire* pakfire, int flags) {
char target[PATH_MAX];
int r;
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;
return 0;
}
+int pakfire_make_ramdisk(struct pakfire* pakfire, char* path, const char* args) {
+ int r;
+
+ // Create a new temporary directory
+ char* p = pakfire_mkdtemp(path);
+ if (!p)
+ return -errno;
+
+ // 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;
+}
+
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);
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_REC|MS_BIND, NULL);
+ return pakfire_mount(pakfire, src, mountpoint, "bind", flags|MS_BIND|MS_REC, NULL);
}