about summary refs log tree commit diff
path: root/pkgs/games/build-support/build-sandbox/src/nix-query.cc
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2017-10-03 21:32:35 +0200
committeraszlig <aszlig@redmoonstudios.org>2017-10-03 23:41:37 +0200
commit0bf66bd8d1a1db8c512c66069731bf67a9836a44 (patch)
tree3d010ba317b2dbe8c4f9d05d18de568ff9bf2f62 /pkgs/games/build-support/build-sandbox/src/nix-query.cc
parent2c68ece11b950dc9f078ff843a0ba137c76f7076 (diff)
pkgs/sandbox: Mount paths from path-like variables
On NixOS the LD_LIBRARY_PATH looks similar to this (depending on the
configuration):

/run/opengl-driver/lib:/run/opengl-driver-32/lib

However, we don't have these paths available within the sandbox, because
so far we've only used exportReferencesGraph to gather the runtime
dependencies after the build has succeeded.

This obviously doesn't take into account runtime dependencies from the
system itself.

We are now taking care of this by using the Nix store library to query
the requisities of all the paths that are contained inside path-like
variables (multiple paths delimited by colons) and mount them during
sandbox setup.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Diffstat (limited to 'pkgs/games/build-support/build-sandbox/src/nix-query.cc')
-rw-r--r--pkgs/games/build-support/build-sandbox/src/nix-query.cc116
1 files changed, 116 insertions, 0 deletions
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();
+    }
+}