about summary refs log tree commit diff
path: root/pkgs/games/build-support
diff options
context:
space:
mode:
authoraszlig <aszlig@nix.build>2017-11-21 07:06:08 +0100
committeraszlig <aszlig@nix.build>2017-11-21 07:44:50 +0100
commitaf83c63ef1926a7571943926fbbd08c6c129d737 (patch)
treedd3a8158009a0fafe933531e6ce04bb940ad8a84 /pkgs/games/build-support
parentd7fe5d2fa0909f8cf59fc7cc54dda00fe38a28a6 (diff)
pkgs/sandbox: Handle non-existing paths
We now distinguish between paths that have to exist and paths that are
fine to skip during bind mounting.

So far we had hard failures whenever a path that needed to be mounted
didn't exist, for example something like $XDG_CONFIG_HOME/unity3d failed
whenever the directory didn't exist.

Apart from that we now have a more clean attribute structure for sandbox
parameters, which are now:

  * paths.required: Created prior to bind-mounting
  * paths.wanted: Skipped if it doesn't exist
  * paths.runtimeVars: Extracted from PATH-like environment variables

Signed-off-by: aszlig <aszlig@nix.build>
Diffstat (limited to 'pkgs/games/build-support')
-rw-r--r--pkgs/games/build-support/build-game.nix18
-rw-r--r--pkgs/games/build-support/build-sandbox/default.nix31
-rw-r--r--pkgs/games/build-support/build-sandbox/src/setup.c29
-rw-r--r--pkgs/games/build-support/build-sandbox/src/setup.h2
-rw-r--r--pkgs/games/build-support/build-unity.nix11
5 files changed, 59 insertions, 32 deletions
diff --git a/pkgs/games/build-support/build-game.nix b/pkgs/games/build-support/build-game.nix
index 51d3c7d5..b04309a5 100644
--- a/pkgs/games/build-support/build-game.nix
+++ b/pkgs/games/build-support/build-game.nix
@@ -12,8 +12,7 @@ assert withPulseAudio -> libpulseaudio != null;
 , setSourceRoot ? ""
 , installCheckPhase ? ""
 , runtimeDependencies ? []
-, extraSandboxPaths ? [ "$XDG_DATA_HOME" "$XDG_CONFIG_HOME" ]
-, extraRuntimePathVars ? []
+, sandbox ? {}
 , ...
 }@attrs:
 
@@ -73,9 +72,12 @@ buildSandbox (stdenv.mkDerivation ({
   dontPatchELF = true;
 } // removeAttrs attrs [
   "buildInputs" "nativeBuildInputs" "preUnpack" "setSourceRoot"
-  "installCheckPhase" "runtimeDependencies" "extraSandboxPaths"
-  "extraRuntimePathVars"
-])) {
-  inherit extraSandboxPaths;
-  runtimePathVars = lib.singleton "LD_LIBRARY_PATH" ++ extraRuntimePathVars;
-}
+  "installCheckPhase" "runtimeDependencies" "sandbox"
+])) (sandbox // {
+  paths = let
+    paths = sandbox.paths or {};
+  in paths // {
+    required = paths.required or [ "$XDG_DATA_HOME" "$XDG_CONFIG_HOME" ];
+    runtimeVars = [ "LD_LIBRARY_PATH" ] ++ paths.runtimeVars or [];
+  };
+})
diff --git a/pkgs/games/build-support/build-sandbox/default.nix b/pkgs/games/build-support/build-sandbox/default.nix
index e4826405..fa4bac57 100644
--- a/pkgs/games/build-support/build-sandbox/default.nix
+++ b/pkgs/games/build-support/build-sandbox/default.nix
@@ -1,8 +1,23 @@
 { stdenv, lib, pkgconfig, nix }:
 
-drv: { extraSandboxPaths ? [], runtimePathVars ? [], ... }@attrs:
-
-stdenv.mkDerivation ({
+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;
@@ -37,10 +52,8 @@ stdenv.mkDerivation ({
       echo 'if (!bind_mount("'"$dep"'", true, true)) return false;' >> params.c
     done
 
-    ${lib.concatMapStringsSep "\n" (extra: let
-      escaped = lib.escapeShellArg (lib.escape ["\\" "\""] extra);
-      result = "echo 'if (!extra_mount(\"'${escaped}'\")) return false;'";
-    in "${result} >> params.c") extraSandboxPaths}
+    ${mkExtraMountParams true  pathsRequired}
+    ${mkExtraMountParams false pathsWanted}
 
     echo 'return true; }' >> params.c
 
@@ -50,7 +63,7 @@ stdenv.mkDerivation ({
       escaped = lib.escapeShellArg (lib.escape ["\\" "\""] pathvar);
       fun = "mount_from_path_var";
       result = "echo 'if (!${fun}(qs, \"'${escaped}'\")) return false;'";
-    in "${result} >> params.c") runtimePathVars}
+    in "${result} >> params.c") pathsRuntimeVars}
 
     echo 'return true; }' >> params.c
   '';
@@ -59,4 +72,4 @@ stdenv.mkDerivation ({
   buildInputs = [ nix ];
   makeFlags = [ "BINDIR=${drv}/bin" ];
 
-} // removeAttrs attrs [ "extraSandboxPaths" "runtimePathVars" ])
+} // removeAttrs attrs [ "paths" ])
diff --git a/pkgs/games/build-support/build-sandbox/src/setup.c b/pkgs/games/build-support/build-sandbox/src/setup.c
index 0b582e92..f351ce19 100644
--- a/pkgs/games/build-support/build-sandbox/src/setup.c
+++ b/pkgs/games/build-support/build-sandbox/src/setup.c
@@ -91,7 +91,7 @@ bool write_maps(pid_t parent_pid)
     return true;
 }
 
-static bool makedirs(const char *path)
+static bool makedirs(const char *path, bool do_cache)
 {
     char *tmp, *segment;
 
@@ -103,13 +103,13 @@ static bool makedirs(const char *path)
     segment = dirname(tmp);
 
     if (!(segment[0] == '/' && segment[1] == '\0')) {
-        if (!makedirs(segment)) {
+        if (!makedirs(segment, do_cache)) {
             free(tmp);
             return false;
         }
     }
 
-    if (cache_path(cached_paths, path))
+    if (!do_cache || cache_path(cached_paths, path))
         (void)mkdir(path, 0755);
     free(tmp);
     return true;
@@ -138,17 +138,14 @@ bool bind_mount(const char *path, bool restricted, bool resolve)
     if (restricted)
         mflags |= MS_NOSUID | MS_NODEV | MS_NOATIME;
 
-    if (resolve) {
-        if (realpath(path, src) == NULL) {
-            fprintf(stderr, "realpath of %s: %s\n", path, strerror(errno));
-            return false;
-        }
-    }
+    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)) {
+    if (!makedirs(target, false)) {
         free(target);
         return false;
     }
@@ -173,6 +170,10 @@ 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;
 
@@ -182,7 +183,7 @@ static bool bind_file(const char *path)
         return false;
     }
 
-    if (!makedirs(dirname(tmp))) {
+    if (!makedirs(dirname(tmp), true)) {
         free(target);
         free(tmp);
         return false;
@@ -452,12 +453,16 @@ static char *replace_env(const char *path)
     return replace_env_offset_free(path, base);
 }
 
-bool extra_mount(const char *path)
+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;
diff --git a/pkgs/games/build-support/build-sandbox/src/setup.h b/pkgs/games/build-support/build-sandbox/src/setup.h
index c3b69699..fe882dc5 100644
--- a/pkgs/games/build-support/build-sandbox/src/setup.h
+++ b/pkgs/games/build-support/build-sandbox/src/setup.h
@@ -7,7 +7,7 @@
 
 bool write_maps(pid_t parent_pid);
 bool bind_mount(const char *path, bool restricted, bool resolve);
-bool extra_mount(const char *path);
+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);
 
diff --git a/pkgs/games/build-support/build-unity.nix b/pkgs/games/build-support/build-unity.nix
index 596c65be..6d7a6cb1 100644
--- a/pkgs/games/build-support/build-unity.nix
+++ b/pkgs/games/build-support/build-unity.nix
@@ -6,6 +6,7 @@
 , nativeBuildInputs ? []
 , buildInputs ? []
 , runtimeDependencies ? []
+, sandbox ? {}
 , ...
 }@attrs:
 
@@ -27,7 +28,13 @@ in buildGame ({
     mesa xorg.libX11 xorg.libXcursor xorg.libXrandr libudev zlib
   ];
 
-  extraSandboxPaths = [ "$XDG_CONFIG_HOME/unity3d" ];
+  sandbox = sandbox // {
+    paths = (sandbox.paths or {}) // {
+      required = (sandbox.paths.required or []) ++ [
+        "$XDG_CONFIG_HOME/unity3d"
+      ];
+    };
+  };
 
   installPhase = ''
     runHook preInstall
@@ -62,5 +69,5 @@ in buildGame ({
   '';
 } // removeAttrs attrs [
   "name" "version" "fullName" "nativeBuildInputs" "buildInputs"
-  "runtimeDependencies"
+  "runtimeDependencies" "sandbox"
 ])