about summary refs log tree commit diff
path: root/pkgs/games/build-support
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/games/build-support')
-rw-r--r--pkgs/games/build-support/build-sandbox/default.nix15
-rw-r--r--pkgs/games/build-support/build-sandbox/src/Makefile10
-rw-r--r--pkgs/games/build-support/build-sandbox/src/get-closure.cc23
-rw-r--r--pkgs/games/build-support/build-sandbox/src/nix-query.cc116
-rw-r--r--pkgs/games/build-support/build-sandbox/src/nix-query.h6
-rw-r--r--pkgs/games/build-support/build-sandbox/src/params.h2
-rw-r--r--pkgs/games/build-support/build-sandbox/src/setup.c66
-rw-r--r--pkgs/games/build-support/build-sandbox/src/setup.h2
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