From 90316a0ec638e82819188647d6c0ceed339c7714 Mon Sep 17 00:00:00 2001 From: aszlig Date: Sat, 9 Jun 2018 23:19:19 +0200 Subject: pkgs/sandbox: Handle store paths that are symlinks For example the store path of libGL-1.0.0 is a symlink pointing to libglvnd-1.0.0 right now on my machine. If we have such a symlink the sandbox would just silently skip it and only mount the *resolved* path instead of creating the symlink leading to the target. Now whenever bind_mount() with the resolve argument being true is used, we create all the symlinks leading to the target path determined by realpath(). Signed-off-by: aszlig --- pkgs/build-support/build-sandbox/src/setup.c | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'pkgs/build-support/build-sandbox') diff --git a/pkgs/build-support/build-sandbox/src/setup.c b/pkgs/build-support/build-sandbox/src/setup.c index a23983c8..da6c65c7 100644 --- a/pkgs/build-support/build-sandbox/src/setup.c +++ b/pkgs/build-support/build-sandbox/src/setup.c @@ -189,6 +189,62 @@ static bool bind_file(const char *path) return true; } +static bool makelinks(const char *from, const char *to) +{ + char linktarget[PATH_MAX]; + char *target, *tmp; + ssize_t linksize; + bool result; + + if (strcmp(from, to) == 0) + return true; + + if ((linksize = readlink(from, linktarget, PATH_MAX)) == -1) { + if (errno == EINVAL) + // Not a symbolic link + return true; + + fprintf(stderr, "reading link %s: %s\n", from, strerror(errno)); + return false; + } + + linktarget[linksize] = '\0'; + + if ((target = get_mount_target(from)) == NULL) + return false; + + if ((tmp = strdup(target)) == NULL) { + fprintf(stderr, "strdup of %s: %s\n", target, strerror(errno)); + free(target); + return false; + } + + if (!makedirs(dirname(tmp), true)) { + free(target); + free(tmp); + return false; + } + + free(tmp); + + if (cache_path(cached_paths, target)) { + if (symlink(linktarget, target) == -1) { + if (errno == EEXIST) + goto recurse; + + fprintf(stderr, "creating symlink from %s to %s: %s\n", + target, linktarget, strerror(errno)); + free(target); + return false; + } + } + +recurse: + result = makelinks(linktarget, to); + free(target); + return result; +} + bool bind_mount(const char *path, bool restricted, bool resolve) { int mflags = MS_BIND | MS_REC; @@ -207,6 +263,13 @@ bool bind_mount(const char *path, bool restricted, bool resolve) if ((target = get_mount_target(resolve ? src : path)) == NULL) return false; + if (resolve) { + if (!makelinks(path, src)) { + free(target); + return false; + } + } + if (!makedirs(target, false)) { free(target); return false; -- cgit 1.4.1