diff --git a/gnu/packages/aux-files/run-in-namespace.c b/gnu/packages/aux-files/run-in-namespace.c index 7f7e5c6885..436c0b6286 100644 --- a/gnu/packages/aux-files/run-in-namespace.c +++ b/gnu/packages/aux-files/run-in-namespace.c @@ -441,10 +441,23 @@ exec_with_loader (const char *store, int argc, char *argv[]) char *new_root = mkdtemp (strdup ("/tmp/guix-exec-XXXXXX")); mirror_directory ("/", new_root, make_symlink); + /* 'mirror_directory' created a symlink for the ancestor of ORIGINAL_STORE, + typically "/gnu". Remove that entry so we can create NEW_STORE + below. */ + const char *slash = strchr (original_store + 1, '/'); + const char *top = slash != NULL + ? strndupa (original_store, slash - original_store) + : original_store; + char *new_store_top = concat (new_root, top); + unlink (new_store_top); + + /* Now create the store under NEW_ROOT. */ char *new_store = concat (new_root, original_store); char *new_store_parent = dirname (strdup (new_store)); mkdir_p (new_store_parent); - symlink (store, new_store); + err = symlink (store, new_store); + if (err < 0) + assert_perror (errno); #ifdef GCONV_DIRECTORY /* Tell libc where to find its gconv modules. This is necessary because diff --git a/tests/guix-pack-relocatable.sh b/tests/guix-pack-relocatable.sh index 1ba3889036..b8d36a02c6 100644 --- a/tests/guix-pack-relocatable.sh +++ b/tests/guix-pack-relocatable.sh @@ -90,7 +90,7 @@ case "`uname -m`" in # Try '-RR' and PRoot. tarball="`guix pack -RR -S /Bin=bin sed`" tar tvf "$tarball" | grep /bin/proot - (cd "$test_directory"; tar xvf "$tarball") + (cd "$test_directory"; tar xf "$tarball") run_without_store GUIX_EXECUTION_ENGINE="proot" \ "$test_directory/Bin/sed" --version > "$test_directory/output" grep 'GNU sed' "$test_directory/output" @@ -101,6 +101,29 @@ case "`uname -m`" in grep 'GNU sed' "$test_directory/output" chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* + + if unshare -r true + then + # Check whether the store contains everything it should. Check + # once when erasing $STORE_PARENT ("/gnu") and once when erasing + # $NIX_STORE_DIR ("/gnu/store"). + tarball="`guix pack -RR -S /bin=bin bash-minimal`" + (cd "$test_directory"; tar xf "$tarball") + + STORE_PARENT="`dirname $NIX_STORE_DIR`" + export STORE_PARENT + + for engine in userns proot fakechroot + do + for i in $(guix gc -R $(guix build bash-minimal | grep -v -e '-doc$')) + do + unshare -mrf sh -c "mount -t tmpfs none \"$NIX_STORE_DIR\"; GUIX_EXECUTION_ENGINE=$engine $test_directory/bin/sh -c 'echo $NIX_STORE_DIR/*'" | grep $(basename $i) + unshare -mrf sh -c "mount -t tmpfs none \"$STORE_PARENT\"; GUIX_EXECUTION_ENGINE=$engine $test_directory/bin/sh -c 'echo $NIX_STORE_DIR/*'" | grep $(basename $i) + done + done + + chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* + fi ;; *) echo "skipping PRoot and Fakechroot tests" >&2 @@ -109,7 +132,7 @@ esac # Ensure '-R' works with outputs other than "out". tarball="`guix pack -R -S /share=share groff:doc`" -(cd "$test_directory"; tar xvf "$tarball") +(cd "$test_directory"; tar xf "$tarball") test -d "$test_directory/share/doc/groff/html" # Ensure '-R' applies to propagated inputs. Failing to do that, it would fail