diff options
Diffstat (limited to 'pkgs/games/build-support/build-sandbox')
8 files changed, 211 insertions, 29 deletions
diff --git a/pkgs/games/build-support/build-sandbox/default.nix b/pkgs/games/build-support/build-sandbox/default.nix index 337456e0..e7243d2c 100644 --- a/pkgs/games/build-support/build-sandbox/default.nix +++ b/pkgs/games/build-support/build-sandbox/default.nix @@ -1,6 +1,6 @@ { stdenv, lib, pkgconfig, nix }: -drv: { extraSandboxPaths ? [], ... }@attrs: +drv: { extraSandboxPaths ? [], runtimePathVariables ? [], ... }@attrs: stdenv.mkDerivation ({ name = "${drv.name}-sandboxed"; @@ -43,11 +43,20 @@ stdenv.mkDerivation ({ in "${result} >> params.c") extraSandboxPaths} echo 'return true; }' >> params.c - cat params.c + + echo 'bool mount_runtime_path_vars(struct query_state *qs) {' >> params.c + + ${lib.concatMapStringsSep "\n" (pathvar: let + escaped = lib.escapeShellArg (lib.escape ["\\" "\""] pathvar); + fun = "mount_from_path_var"; + result = "echo 'if (!${fun}(qs, \"'${escaped}'\")) return false;'"; + in "${result} >> params.c") runtimePathVariables} + + echo 'return true; }' >> params.c ''; nativeBuildInputs = [ pkgconfig ]; buildInputs = [ nix ]; makeFlags = [ "BINDIR=${drv}/bin" ]; -} // removeAttrs attrs [ "extraSandboxPaths" ]) +} // removeAttrs attrs [ "extraSandboxPaths" "runtimePathVariables" ]) diff --git a/pkgs/games/build-support/build-sandbox/src/Makefile b/pkgs/games/build-support/build-sandbox/src/Makefile index 49b266fe..f662b5ba 100644 --- a/pkgs/games/build-support/build-sandbox/src/Makefile +++ b/pkgs/games/build-support/build-sandbox/src/Makefile @@ -1,10 +1,14 @@ BINARIES = $(wildcard $(BINDIR)/*) WRAPPERS = $(subst $(BINDIR),$(out)/bin,$(BINARIES)) -OBJECTS = get-closure.o params.o setup.o +NIX_VERSION = `pkg-config --modversion nix-main | \ + sed -e 's/^\([0-9]\+\)\.\([0-9]\+\).*/\1\2/'` -CFLAGS = -Wall -std=gnu11 -DFS_ROOT_DIR=\"$(out)\" -CXXFLAGS = -Wall -std=c++14 `pkg-config --cflags nix-main` +OBJECTS = nix-query.o params.o setup.o + +CFLAGS = -g -Wall -std=gnu11 -DFS_ROOT_DIR=\"$(out)\" +CXXFLAGS = -g -Wall -std=c++14 `pkg-config --cflags nix-main` +CXXFLAGS += -DNIX_VERSION=$(NIX_VERSION) LDFLAGS = `pkg-config --libs nix-main` all: $(OBJECTS) diff --git a/pkgs/games/build-support/build-sandbox/src/get-closure.cc b/pkgs/games/build-support/build-sandbox/src/get-closure.cc deleted file mode 100644 index 11330a9c..00000000 --- a/pkgs/games/build-support/build-sandbox/src/get-closure.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include <nix/util.hh> -#include <nix/local-store.hh> -#include <nix/store-api.hh> -#include <nix/misc.hh> - -using namespace nix; - -int get_closure(const char *path) -{ - Path query(path); - PathSet paths; - auto store = openStore(false); - - computeFSClosure( - *store, followLinksToStorePath(query), paths, false, true - ); - - for (auto i = paths.begin(); i != paths.end(); ++i) { - // TODO! - } - - return 1; -} diff --git a/pkgs/games/build-support/build-sandbox/src/nix-query.cc b/pkgs/games/build-support/build-sandbox/src/nix-query.cc new file mode 100644 index 00000000..128c376a --- /dev/null +++ b/pkgs/games/build-support/build-sandbox/src/nix-query.cc @@ -0,0 +1,116 @@ +#include <iostream> + +#if NIX_VERSION >= 112 +#include <nix/config.h> +#endif +#include <nix/util.hh> +#include <nix/local-store.hh> +#include <nix/store-api.hh> + +#if NIX_VERSION < 112 +#include <nix/misc.hh> +#include <nix/globals.hh> +#endif + +using namespace nix; + +struct query_state { +#if NIX_VERSION >= 112 + std::shared_ptr<Store> store; +#else + std::shared_ptr<StoreAPI> store; +#endif + PathSet paths; + PathSet::iterator iter; +}; + +static Path get_store_path(query_state *qs, Path path) +{ + Path canonicalized = canonPath(path, true); +#if NIX_VERSION >= 112 + return qs->store->toStorePath(canonicalized); +#else + return toStorePath(canonicalized); +#endif +} + +static Path get_ancestor(query_state *qs, Path path) +{ + size_t pos = 0; + std::string tmp; + + while (pos != std::string::npos) { + if ((pos = path.find('/', pos + 1)) != std::string::npos) { + Path current = path.substr(0, pos); + + if (!isLink(current)) + continue; + + try { + current = get_store_path(qs, current); + } catch (...) { + continue; + } + + return current; + } + } + + return path; +} + +extern "C" { + struct query_state *new_query(void) { + query_state *initial = new query_state(); +#if NIX_VERSION >= 112 + initial->store = openStore(); +#else + settings.processEnvironment(); + settings.loadConfFile(); + initial->store = openStore(false); +#endif + return initial; + } + + void free_query(query_state *qs) { + delete qs; + } + + bool query_requisites(query_state *qs, const char *path) + { + Path query(path); + + try { + query = get_ancestor(qs, query); + +#if NIX_VERSION >= 112 + qs->store->computeFSClosure( + qs->store->followLinksToStorePath(query), + qs->paths, false, true + ); +#else + computeFSClosure( + *qs->store, followLinksToStorePath(query), + qs->paths, false, true + ); +#endif + } catch (Error &e) { + std::cerr << "Error while querying requisites for " + << query << ": " << e.what() + << std::endl; + return false; + } + + qs->iter = qs->paths.begin(); + + return true; + } + + const char *next_query_result(query_state *qs) + { + if (qs->iter == qs->paths.end()) + return NULL; + + return (qs->iter++)->c_str(); + } +} diff --git a/pkgs/games/build-support/build-sandbox/src/nix-query.h b/pkgs/games/build-support/build-sandbox/src/nix-query.h new file mode 100644 index 00000000..3eef7c4a --- /dev/null +++ b/pkgs/games/build-support/build-sandbox/src/nix-query.h @@ -0,0 +1,6 @@ +struct query_state; + +struct query_state *new_query(void); +void free_query(struct query_state *qs); +bool query_requisites(struct query_state *qs, const char *path); +const char *next_query_result(struct query_state *qs); diff --git a/pkgs/games/build-support/build-sandbox/src/params.h b/pkgs/games/build-support/build-sandbox/src/params.h index ea33872d..ecfa7295 100644 --- a/pkgs/games/build-support/build-sandbox/src/params.h +++ b/pkgs/games/build-support/build-sandbox/src/params.h @@ -2,7 +2,9 @@ #define _PARAMS_H #include <stdbool.h> +#include "nix-query.h" bool setup_app_paths(void); +bool mount_runtime_path_vars(struct query_state *qs); #endif diff --git a/pkgs/games/build-support/build-sandbox/src/setup.c b/pkgs/games/build-support/build-sandbox/src/setup.c index 72b2f80e..3251a861 100644 --- a/pkgs/games/build-support/build-sandbox/src/setup.c +++ b/pkgs/games/build-support/build-sandbox/src/setup.c @@ -18,6 +18,7 @@ #include <unistd.h> #include "params.h" +#include "nix-query.h" static bool write_proc(int proc_pid_fd, const char *fname, const char *buf, size_t buflen, bool ignore_errors) @@ -193,6 +194,7 @@ static bool bind_file(const char *path) return false; } + free(target); return true; } @@ -480,6 +482,67 @@ static bool setup_xauthority(void) return result; } +static bool mount_requisites(struct query_state *qs, const char *path) +{ + const char *requisite; + + if (!query_requisites(qs, path)) { + fprintf(stderr, "Unable to get requisites for %s.\n", path); + return false; + } + + while ((requisite = next_query_result(qs)) != NULL) { + if (!bind_mount(requisite, true, false)) + return false; + } + + return true; +} + +bool mount_from_path_var(struct query_state *qs, const char *name) +{ + char *buf, *ptr, *value = getenv(name); + + if (value == NULL) + return true; + + if ((buf = strdup(value)) == NULL) { + fprintf(stderr, "strdup %s: %s\n", value, strerror(errno)); + return false; + } + + ptr = strtok(buf, ":"); + + while (ptr != NULL) { + if (!mount_requisites(qs, ptr)) { + free(buf); + return false; + } + ptr = strtok(NULL, ":"); + } + + free(buf); + return true; +} + +static bool setup_runtime_paths(void) +{ + struct query_state *qs; + + if ((qs = new_query()) == NULL) { + fputs("Unable to allocate Nix query state.\n", stderr); + return false; + } + + if (!mount_runtime_path_vars(qs)) { + free_query(qs); + return false; + } + + free_query(qs); + return true; +} + static bool setup_chroot(void) { int mflags; @@ -512,6 +575,9 @@ static bool setup_chroot(void) if (!bind_mount("/tmp", true, false)) return false; + if (!setup_runtime_paths()) + return false; + if (!setup_app_paths()) return false; diff --git a/pkgs/games/build-support/build-sandbox/src/setup.h b/pkgs/games/build-support/build-sandbox/src/setup.h index 19cc6ca2..c3b69699 100644 --- a/pkgs/games/build-support/build-sandbox/src/setup.h +++ b/pkgs/games/build-support/build-sandbox/src/setup.h @@ -3,10 +3,12 @@ #include <stdbool.h> #include <sys/types.h> +#include "nix-query.h" bool write_maps(pid_t parent_pid); bool bind_mount(const char *path, bool restricted, bool resolve); bool extra_mount(const char *path); +bool mount_from_path_var(struct query_state *qs, const char *name); bool setup_sandbox(void); #endif |