about summary refs log tree commit diff
path: root/pkgs/games/build-support
diff options
context:
space:
mode:
authoraszlig <aszlig@nix.build>2017-11-30 06:42:49 +0100
committeraszlig <aszlig@nix.build>2017-11-30 08:33:59 +0100
commit38d3fe573f4d0ad2115eaca71a0b8f67fd01a580 (patch)
treed09bf338919056089be3b59194fa7b647794b15b /pkgs/games/build-support
parent28ac40c9d9e1c9afc63c19646f223b28b7ed3bc8 (diff)
build-sandbox: Move to top-level build-support
This is not only useful for packaging games, so let's make it available
from the vuizvui scope, so we can use it from other packages as well.

Signed-off-by: aszlig <aszlig@nix.build>
Diffstat (limited to 'pkgs/games/build-support')
-rw-r--r--pkgs/games/build-support/build-sandbox/default.nix75
-rw-r--r--pkgs/games/build-support/build-sandbox/src/Makefile23
-rw-r--r--pkgs/games/build-support/build-sandbox/src/nix-query.cc118
-rw-r--r--pkgs/games/build-support/build-sandbox/src/nix-query.h6
-rw-r--r--pkgs/games/build-support/build-sandbox/src/params.h10
-rw-r--r--pkgs/games/build-support/build-sandbox/src/path-cache.cc21
-rw-r--r--pkgs/games/build-support/build-sandbox/src/path-cache.h10
-rw-r--r--pkgs/games/build-support/build-sandbox/src/sandbox.c21
-rw-r--r--pkgs/games/build-support/build-sandbox/src/setup.c709
-rw-r--r--pkgs/games/build-support/build-sandbox/src/setup.h14
-rw-r--r--pkgs/games/build-support/default.nix3
11 files changed, 2 insertions, 1008 deletions
diff --git a/pkgs/games/build-support/build-sandbox/default.nix b/pkgs/games/build-support/build-sandbox/default.nix
deleted file mode 100644
index fa4bac57..00000000
--- a/pkgs/games/build-support/build-sandbox/default.nix
+++ /dev/null
@@ -1,75 +0,0 @@
-{ stdenv, lib, pkgconfig, nix }:
-
-drv: { paths ? {}, ... }@attrs:
-
-let
-  # Extra paths that are required so they are created prior to bind-mounting.
-  pathsRequired    = paths.required    or [];
-  # Extra paths that are skipped if they don't exist.
-  pathsWanted      = paths.wanted      or [];
-  # Paths extracted from PATH-like environment variables, eg. LD_LIBRARY_PATH.
-  pathsRuntimeVars = paths.runtimeVars or [];
-
-  # Create code snippets for params.c to add extra_mount() calls.
-  mkExtraMountParams = isRequired: lib.concatMapStringsSep "\n" (extra: let
-    escaped = lib.escape ["\\" "\""] extra;
-    reqBool = if isRequired then "true" else "false";
-    code = "if (!extra_mount(\"${escaped}\", ${reqBool})) return false;";
-  in "echo ${lib.escapeShellArg code} >> params.c");
-
-in stdenv.mkDerivation ({
-  name = "${drv.name}-sandboxed";
-
-  src = ./src;
-
-  inherit drv;
-
-  exportReferencesGraph = [ "sandbox-closure" drv ];
-
-  configurePhase = ''
-    runtimeDeps="$(sed -ne '
-      p; n; n
-
-      :cdown
-      /^0*$/b
-      :l; s/0\(X*\)$/X\1/; tl
-
-      s/^\(X*\)$/9\1/; tdone
-      ${lib.concatMapStrings (num: ''
-        s/${toString num}\(X*\)$/${toString (num - 1)}\1/; tdone
-      '') (lib.range 1 9)}
-
-      :done
-      y/X/9/
-      x; n; p; x
-      bcdown
-    ' ../sandbox-closure | sort -u)"
-
-    echo '#include "setup.h"' > params.c
-    echo 'bool setup_app_paths(void) {' >> params.c
-
-    for dep in $runtimeDeps; do
-      echo 'if (!bind_mount("'"$dep"'", true, true)) return false;' >> params.c
-    done
-
-    ${mkExtraMountParams true  pathsRequired}
-    ${mkExtraMountParams false pathsWanted}
-
-    echo 'return true; }' >> 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") pathsRuntimeVars}
-
-    echo 'return true; }' >> params.c
-  '';
-
-  nativeBuildInputs = [ pkgconfig ];
-  buildInputs = [ nix ];
-  makeFlags = [ "BINDIR=${drv}/bin" ];
-
-} // removeAttrs attrs [ "paths" ])
diff --git a/pkgs/games/build-support/build-sandbox/src/Makefile b/pkgs/games/build-support/build-sandbox/src/Makefile
deleted file mode 100644
index cd642b8e..00000000
--- a/pkgs/games/build-support/build-sandbox/src/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-BINARIES = $(wildcard $(BINDIR)/*)
-WRAPPERS = $(subst $(BINDIR),$(out)/bin,$(BINARIES))
-
-NIX_VERSION = `pkg-config --modversion nix-main | \
-               sed -e 's/^\([0-9]\+\)\.\([0-9]\+\).*/\1\2/'`
-
-OBJECTS = nix-query.o path-cache.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)
-
-$(out)/bin/%: CFLAGS += -DWRAPPED_PROGNAME=\"$(@F)\"
-$(out)/bin/%: CFLAGS += -DWRAPPED_PATH=\"$(BINDIR)/$(@F)\"
-$(out)/bin/%: $(OBJECTS)
-	mkdir -p $(out)/bin
-	$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $? sandbox.c
-
-.PHONY: install
-install: $(WRAPPERS)
diff --git a/pkgs/games/build-support/build-sandbox/src/nix-query.cc b/pkgs/games/build-support/build-sandbox/src/nix-query.cc
deleted file mode 100644
index 71208693..00000000
--- a/pkgs/games/build-support/build-sandbox/src/nix-query.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-#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 get_store_path(qs, 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
deleted file mode 100644
index 3eef7c4a..00000000
--- a/pkgs/games/build-support/build-sandbox/src/nix-query.h
+++ /dev/null
@@ -1,6 +0,0 @@
-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
deleted file mode 100644
index ecfa7295..00000000
--- a/pkgs/games/build-support/build-sandbox/src/params.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _PARAMS_H
-#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/path-cache.cc b/pkgs/games/build-support/build-sandbox/src/path-cache.cc
deleted file mode 100644
index 5bfa43a7..00000000
--- a/pkgs/games/build-support/build-sandbox/src/path-cache.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <set>
-#include <string>
-
-typedef std::set<std::string> *path_cache;
-
-extern "C" {
-    path_cache new_path_cache(void)
-    {
-        return new std::set<std::string>();
-    }
-
-    void free_path_cache(path_cache pc)
-    {
-        delete pc;
-    }
-
-    bool cache_path(path_cache pc, const char *path)
-    {
-        return pc->insert(std::string(path)).second;
-    }
-}
diff --git a/pkgs/games/build-support/build-sandbox/src/path-cache.h b/pkgs/games/build-support/build-sandbox/src/path-cache.h
deleted file mode 100644
index 368f8d17..00000000
--- a/pkgs/games/build-support/build-sandbox/src/path-cache.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _PATH_CACHE_H
-#define _PATH_CACHE_H
-
-typedef void *path_cache;
-
-path_cache new_path_cache(void);
-void free_path_cache(path_cache pc);
-bool cache_path(path_cache pc, const char *path);
-
-#endif
diff --git a/pkgs/games/build-support/build-sandbox/src/sandbox.c b/pkgs/games/build-support/build-sandbox/src/sandbox.c
deleted file mode 100644
index e2aa47cf..00000000
--- a/pkgs/games/build-support/build-sandbox/src/sandbox.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "setup.h"
-
-int main(int argc, char **argv)
-{
-    if (!setup_sandbox())
-        return 1;
-
-    argv[0] = WRAPPED_PROGNAME;
-    if (execv(WRAPPED_PATH, argv) == -1) {
-        fprintf(stderr, "exec %s: %s\n", WRAPPED_PATH, strerror(errno));
-        return 1;
-    }
-
-    // Should never be reached.
-    return 1;
-}
diff --git a/pkgs/games/build-support/build-sandbox/src/setup.c b/pkgs/games/build-support/build-sandbox/src/setup.c
deleted file mode 100644
index f351ce19..00000000
--- a/pkgs/games/build-support/build-sandbox/src/setup.c
+++ /dev/null
@@ -1,709 +0,0 @@
-#define _GNU_SOURCE
-
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <limits.h>
-#include <malloc.h>
-#include <sched.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "params.h"
-#include "nix-query.h"
-#include "path-cache.h"
-
-static path_cache cached_paths = NULL;
-
-static bool write_proc(int proc_pid_fd, const char *fname, const char *buf,
-                       size_t buflen, bool ignore_errors)
-{
-    int fd;
-
-    if ((fd = openat(proc_pid_fd, fname, O_WRONLY)) == -1) {
-        fprintf(stderr, "open %s: %s\n", fname, strerror(errno));
-        return false;
-    }
-
-    if (write(fd, buf, buflen) == -1) {
-        if (!ignore_errors)
-            fprintf(stderr, "write %s: %s\n", fname, strerror(errno));
-        close(fd);
-        return ignore_errors;
-    }
-
-    close(fd);
-    return true;
-}
-
-#define WRITE_IDMAP(file, value) \
-    buflen = snprintf(buf, 100, "%1$lu %1$lu 1", (unsigned long)value); \
-    if (buflen >= 100) { \
-        fputs("Unable to write buffer for " file ".\n", stderr); \
-        close(proc_pid_fd); \
-        return false; \
-    } else if (buflen < 0) { \
-        perror("snprintf " file " buffer"); \
-        close(proc_pid_fd); \
-        return false; \
-    } \
-    if (!write_proc(proc_pid_fd, file, buf, buflen, false)) { \
-        close(proc_pid_fd); \
-        return false; \
-    }
-
-bool write_maps(pid_t parent_pid)
-{
-    int proc_pid_fd;
-    size_t buflen;
-    char buf[100];
-
-    buflen = snprintf(buf, 100, "/proc/%lu", (unsigned long)parent_pid);
-    if (buflen >= 100) {
-        fputs("Unable to write buffer for child pid proc path.\n", stderr);
-        return false;
-    } else if (buflen < 0) {
-        perror("snprintf child pid proc path");
-        return false;
-    }
-
-    if ((proc_pid_fd = open(buf, O_RDONLY | O_DIRECTORY)) == -1) {
-        fprintf(stderr, "open %s: %s\n", buf, strerror(errno));
-        return false;
-    }
-
-    WRITE_IDMAP("uid_map", geteuid());
-
-    // Kernels prior to Linux 3.19 which do not impose setgroups()
-    // restrictions won't have this file, so ignore failure.
-    write_proc(proc_pid_fd, "setgroups", "deny", 4, true);
-
-    WRITE_IDMAP("gid_map", getegid());
-
-    return true;
-}
-
-static bool makedirs(const char *path, bool do_cache)
-{
-    char *tmp, *segment;
-
-    if ((tmp = strdup(path)) == NULL) {
-        fprintf(stderr, "strdup of %s: %s\n", path, strerror(errno));
-        return false;
-    }
-
-    segment = dirname(tmp);
-
-    if (!(segment[0] == '/' && segment[1] == '\0')) {
-        if (!makedirs(segment, do_cache)) {
-            free(tmp);
-            return false;
-        }
-    }
-
-    if (!do_cache || cache_path(cached_paths, path))
-        (void)mkdir(path, 0755);
-    free(tmp);
-    return true;
-}
-
-static char *get_mount_target(const char *path)
-{
-    size_t pathlen = strlen(path), rootdir_len = strlen(FS_ROOT_DIR);
-    char *target;
-
-    if ((target = malloc(rootdir_len + pathlen + 1)) == NULL) {
-        perror("malloc mount target");
-        return NULL;
-    }
-
-    memcpy(target, FS_ROOT_DIR, rootdir_len);
-    memcpy(target + rootdir_len, path, pathlen + 1);
-    return target;
-}
-
-bool bind_mount(const char *path, bool restricted, bool resolve)
-{
-    int mflags = MS_BIND | MS_REC;
-    char src[PATH_MAX], *target;
-
-    if (restricted)
-        mflags |= MS_NOSUID | MS_NODEV | MS_NOATIME;
-
-    if (resolve ? realpath(path, src) == NULL : access(path, F_OK) == -1)
-        // Skip missing mount source
-        return true;
-
-    if ((target = get_mount_target(resolve ? src : path)) == NULL)
-        return false;
-
-    if (!makedirs(target, false)) {
-        free(target);
-        return false;
-    }
-
-    if (!cache_path(cached_paths, resolve ? src : path)) {
-        free(target);
-        return true;
-    }
-
-    if (mount(resolve ? src : path, target, "", mflags, NULL) == -1) {
-        fprintf(stderr, "mount %s to %s: %s\n",
-                resolve ? src : path, target, strerror(errno));
-        free(target);
-        return false;
-    }
-
-    free(target);
-    return true;
-}
-
-static bool bind_file(const char *path)
-{
-    char *target, *tmp;
-
-    if (access(path, R_OK) == -1)
-        // Skip missing mount source
-        return true;
-
-    if ((target = get_mount_target(path)) == NULL)
-        return false;
-
-    if ((tmp = strdup(target)) == NULL) {
-        perror("strdup bind file target path");
-        free(target);
-        return false;
-    }
-
-    if (!makedirs(dirname(tmp), true)) {
-        free(target);
-        free(tmp);
-        return false;
-    }
-
-    free(tmp);
-
-    if (!cache_path(cached_paths, path)) {
-        free(target);
-        return true;
-    }
-
-    if (creat(target, 0666) == -1) {
-        fprintf(stderr, "unable to create %s: %s\n", target, strerror(errno));
-        free(target);
-        return false;
-    }
-
-    if (mount(path, target, "", MS_BIND, NULL) == -1) {
-        fprintf(stderr, "mount file %s to %s: %s\n",
-                path, target, strerror(errno));
-        free(target);
-        return false;
-    }
-
-    free(target);
-    return true;
-}
-
-struct envar_offset {
-    int start;
-    int length;
-    int var_start;
-    int var_length;
-    struct envar_offset *next;
-};
-
-static struct envar_offset *alloc_offset(void)
-{
-    struct envar_offset *new_offset;
-    new_offset = malloc(sizeof(struct envar_offset));
-
-    if (new_offset == NULL) {
-        perror("malloc envar_offset");
-        return NULL;
-    }
-
-    new_offset->next = NULL;
-    return new_offset;
-}
-
-static struct envar_offset *push_offset(struct envar_offset *current,
-                                        struct envar_offset **base)
-{
-    if (current == NULL) {
-        if ((current = alloc_offset()) != NULL)
-            *base = current;
-        return current;
-    }
-
-    return current->next = alloc_offset();
-}
-
-static void free_offsets(struct envar_offset *base)
-{
-    struct envar_offset *next;
-    if (base == NULL)
-        return;
-    next = base->next;
-    free(base);
-    if (next != NULL)
-        free_offsets(next);
-}
-
-static char *expand_xdg_fallback(const char *xdg_var)
-{
-    static char *home = NULL;
-    static size_t homelen;
-    char *result;
-
-    if (home == NULL) {
-        if ((home = getenv("HOME")) == NULL) {
-            fputs("Unable find $HOME.\n", stderr);
-            return NULL;
-        }
-        homelen = strlen(home);
-    }
-
-    if (strcmp(xdg_var, "XDG_DATA_HOME") == 0) {
-        result = malloc(homelen + 14);
-        if (result == NULL) {
-            perror("malloc XDG_DATA_HOME");
-            return NULL;
-        }
-        memcpy(result, home, homelen);
-        memcpy(result + homelen, "/.local/share", 14);
-        return result;
-    } else if (strcmp(xdg_var, "XDG_CONFIG_HOME") == 0) {
-        result = malloc(homelen + 9);
-        if (result == NULL) {
-            perror("malloc XDG_CONFIG_HOME");
-            return NULL;
-        }
-        memcpy(result, home, homelen);
-        memcpy(result + homelen, "/.config", 9);
-        return result;
-    }
-
-    return NULL;
-}
-
-static char *get_offset_var(struct envar_offset *offset, const char *haystack)
-{
-    char *tmp, *result;
-
-    tmp = strndup(haystack + offset->var_start, offset->var_length);
-
-    if (tmp == NULL) {
-        perror("strndup");
-        return NULL;
-    }
-
-    result = getenv(tmp);
-    if (result == NULL) {
-        if ((result = expand_xdg_fallback(tmp)) == NULL) {
-            fprintf(stderr, "Unable find variable %s in %s\n", tmp, haystack);
-            free(tmp);
-            return NULL;
-        }
-        free(tmp);
-        return result;
-    }
-    free(tmp);
-    return strdup(result);
-}
-
-static char *replace_env_offset_free(const char *path,
-                                     struct envar_offset *offset)
-{
-    struct envar_offset *tmp_offset;
-    size_t buflen, pathlen, varlen, tmplen;
-    int inpos = 0, outpos = 0;
-    char *buf, *curvar;
-
-    buflen = pathlen = strlen(path);
-
-    if ((buf = malloc(buflen + 1)) == NULL) {
-        perror("malloc replace_env buffer");
-        return NULL;
-    }
-
-    while (offset != NULL) {
-        if ((curvar = get_offset_var(offset, path)) == NULL) {
-            free(buf);
-            free_offsets(offset);
-            return NULL;
-        }
-
-        varlen = strlen(curvar);
-        tmplen = varlen + (buflen - offset->length);
-
-        if (tmplen > buflen) {
-            if ((buf = realloc(buf, (buflen = tmplen) + 1)) == NULL) {
-                perror("realloc replace_env buffer");
-                free(buf);
-                free(curvar);
-                free_offsets(offset);
-                return NULL;
-            }
-        }
-
-        memcpy(buf + outpos, path + inpos, offset->start - inpos);
-        outpos += offset->start - inpos;
-        inpos = offset->start;
-
-        memcpy(buf + outpos, curvar, varlen);
-        outpos += varlen;
-        inpos += offset->length;
-
-        free(curvar);
-
-        tmp_offset = offset;
-        offset = offset->next;
-        free(tmp_offset);
-    }
-
-    memcpy(buf + outpos, path + inpos, pathlen - inpos);
-    *(buf + outpos + (pathlen - inpos)) = '\0';
-
-    return buf;
-}
-
-static char *replace_env(const char *path)
-{
-    int i = 0, start = 0, var_start = 0;
-    size_t pathlen;
-    bool in_var = false, curly = false;
-    struct envar_offset *base = NULL, *offset = NULL;
-
-    pathlen = strlen(path);
-
-    while (i < pathlen) {
-        if (path[i] == '$' && !curly && !in_var) {
-            if (i + 1 >= pathlen)
-                break;
-
-            start = i;
-
-            if (path[i + 1] == '{') {
-                curly = true;
-                var_start = i + 2;
-                ++i;
-            } else {
-                in_var = true;
-                var_start = i + 1;
-            }
-        } else if (in_var) {
-            if (!(path[i] >= 'a' && path[i] <= 'z') &&
-                !(path[i] >= 'A' && path[i] <= 'Z') &&
-                !(path[i] >= '0' && path[i] <= '9') &&
-                path[i] != '_'
-            ) {
-                in_var = false;
-
-                if ((offset = push_offset(offset, &base)) == NULL) {
-                    free_offsets(base);
-                    return NULL;
-                }
-
-                offset->start = start;
-                offset->length = i - start;
-                offset->var_start = var_start;
-                offset->var_length = i - var_start;
-                continue;
-            }
-        } else if (curly) {
-            if (path[i] == '}') {
-                curly = false;
-
-                if ((offset = push_offset(offset, &base)) == NULL) {
-                    free_offsets(base);
-                    return NULL;
-                }
-
-                offset->start = start;
-                offset->length = (i + 1) - offset->start;
-                offset->var_start = var_start;
-                offset->var_length = i - offset->var_start;
-            }
-        }
-
-        ++i;
-    }
-
-    if (in_var) {
-        if ((offset = push_offset(offset, &base)) == NULL) {
-            free_offsets(base);
-            return NULL;
-        }
-
-        offset->start = start;
-        offset->length = i - start;
-        offset->var_start = var_start;
-        offset->var_length = i - var_start;
-    }
-
-    return replace_env_offset_free(path, base);
-}
-
-bool extra_mount(const char *path, bool is_required)
-{
-    char *expanded;
-
-    if ((expanded = replace_env(path)) == NULL)
-        return false;
-
-    if (is_required && !makedirs(expanded, false))
-        return false;
-
-    if (!bind_mount(expanded, true, true)) {
-        free(expanded);
-        return false;
-    }
-
-    free(expanded);
-    return true;
-}
-
-static bool setup_xauthority(void)
-{
-    char *xauth, *home;
-    bool result;
-    size_t homelen;
-
-    if ((xauth = getenv("XAUTHORITY")) != NULL)
-        return bind_file(xauth);
-
-    if ((home = getenv("HOME")) == NULL) {
-        fputs("Unable find $HOME.\n", stderr);
-        return false;
-    }
-
-    homelen = strlen(home);
-
-    if ((xauth = malloc(homelen + 13)) == NULL) {
-        perror("malloc xauth file path");
-        return false;
-    }
-
-    memcpy(xauth, home, homelen);
-    memcpy(xauth + homelen, "/.Xauthority", 13);
-
-    result = bind_file(xauth);
-    free(xauth);
-    return result;
-}
-
-static bool is_dir(const char *path)
-{
-    struct stat sb;
-    if (stat(path, &sb) == -1) {
-        fprintf(stderr, "stat %s: %s\n", path, strerror(errno));
-        // Default to directory for mounting
-        return true;
-    }
-    return S_ISDIR(sb.st_mode);
-}
-
-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 (is_dir(requisite)) {
-            if (!bind_mount(requisite, true, false))
-                return false;
-        } else {
-            if (!bind_file(requisite))
-                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_static_etc(struct query_state *qs)
-{
-    char dest[PATH_MAX];
-    ssize_t destlen;
-
-    if ((destlen = readlink("/etc/static", dest, PATH_MAX)) == -1)
-        return true;
-
-    if (destlen >= PATH_MAX) {
-        fputs("readlink of /etc/static larger than PATH_MAX.\n", stderr);
-        return false;
-    }
-
-    dest[destlen] = '\0';
-    return mount_requisites(qs, dest);
-}
-
-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 (!setup_static_etc(qs)) {
-        free_query(qs);
-        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;
-
-    mflags = MS_NOEXEC | MS_NOSUID | MS_NODEV | MS_NOATIME;
-
-    if (mount("none", FS_ROOT_DIR, "tmpfs", mflags, NULL) == -1) {
-        perror("mount rootfs");
-        return false;
-    }
-
-    if (!bind_mount("/etc", true, false))
-        return false;
-
-    if (!bind_mount("/dev", false, false))
-        return false;
-
-    if (!bind_mount("/proc", false, false))
-        return false;
-
-    if (!bind_mount("/sys", false, false))
-        return false;
-
-    if (!bind_mount("/run", false, false))
-        return false;
-
-    if (!bind_mount("/var/run", false, false))
-        return false;
-
-    if (!bind_mount("/tmp", true, false))
-        return false;
-
-    if (!setup_runtime_paths())
-        return false;
-
-    if (!setup_app_paths())
-        return false;
-
-    if (!setup_xauthority())
-        return false;
-
-    if (chroot(FS_ROOT_DIR) == -1) {
-        perror("chroot");
-        return false;
-    }
-
-    if (chdir("/") == -1) {
-        perror("chdir rootfs");
-        return false;
-    }
-
-    return true;
-}
-
-bool setup_sandbox(void)
-{
-    int sync_pipe[2];
-    char sync_status = '.';
-    int child_status;
-    pid_t pid, parent_pid;
-
-    if (pipe(sync_pipe) == -1) {
-        perror("pipe");
-        return false;
-    }
-
-    parent_pid = getpid();
-
-    switch (pid = fork()) {
-        case -1:
-            perror("fork");
-            return false;
-        case 0:
-            close(sync_pipe[1]);
-            if (read(sync_pipe[0], &sync_status, 1) == -1) {
-                perror("read pipe from parent");
-                _exit(1);
-            } else if (sync_status == 'X')
-                _exit(1);
-            close(sync_pipe[0]);
-            _exit(write_maps(parent_pid) ? 0 : 1);
-        default:
-            if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1) {
-                perror("unshare");
-                if (write(sync_pipe[1], "X", 1) == -1)
-                    perror("signal child exit");
-                waitpid(pid, NULL, 0);
-                return false;
-            }
-
-            close(sync_pipe[1]);
-            waitpid(pid, &child_status, 0);
-            if (WIFEXITED(child_status) && WEXITSTATUS(child_status) == 0)
-                break;
-            return false;
-    }
-
-    cached_paths = new_path_cache();
-
-    if (!setup_chroot()) {
-        free_path_cache(cached_paths);
-        return false;
-    }
-
-    free_path_cache(cached_paths);
-    return true;
-}
diff --git a/pkgs/games/build-support/build-sandbox/src/setup.h b/pkgs/games/build-support/build-sandbox/src/setup.h
deleted file mode 100644
index fe882dc5..00000000
--- a/pkgs/games/build-support/build-sandbox/src/setup.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _SETUP_H
-#define _SETUP_H
-
-#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 is_required);
-bool mount_from_path_var(struct query_state *qs, const char *name);
-bool setup_sandbox(void);
-
-#endif
diff --git a/pkgs/games/build-support/default.nix b/pkgs/games/build-support/default.nix
index 3017fe8e..e739c25f 100644
--- a/pkgs/games/build-support/default.nix
+++ b/pkgs/games/build-support/default.nix
@@ -4,6 +4,7 @@
   buildGame = callPackage ./build-game.nix {
     withPulseAudio = config.pulseaudio or true;
   };
-  buildSandbox = callPackage ./build-sandbox {};
+  # XXX: Pass through from parent scope!
+  buildSandbox = callPackage ../../build-support/build-sandbox {};
   buildUnity = callPackage ./build-unity.nix {};
 }