From 753743c37b11e263283f5dfcf408553c32051902 Mon Sep 17 00:00:00 2001 From: aszlig Date: Sun, 11 Nov 2018 19:29:12 +0100 Subject: [PATCH 1/5] libredirect: Add support for Darwin The library can be used also on Darwin using it like this: NIX_REDIRECTS='foo=bar' \ DYLD_INSERT_LIBRARIES=${libredirect}/lib/libredirect.so \ DYLD_FORCE_FLAT_NAMESPACE=1 \ some_program So let's actually not hardcade gcc and add Darwin to meta.platforms. No other changes seem to be required. Signed-off-by: aszlig --- pkgs/build-support/libredirect/default.nix | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index d13cdd681a21..389abec982e0 100644 --- a/pkgs/build-support/libredirect/default.nix +++ b/pkgs/build-support/libredirect/default.nix @@ -5,15 +5,14 @@ stdenv.mkDerivation { unpackPhase = "cp ${./libredirect.c} libredirect.c"; - buildPhase = - '' - gcc -Wall -std=c99 -O3 -shared libredirect.c -o libredirect.so -fPIC -ldl - ''; + buildPhase = '' + cc -Wall -std=c99 -O3 -shared libredirect.c -o libredirect.so -fPIC -ldl + ''; installPhase = "mkdir -p $out/lib; cp libredirect.so $out/lib"; meta = { - platforms = stdenv.lib.platforms.linux; + platforms = stdenv.lib.platforms.linux ++ stdenv.lib.platforms.darwin; description = "An LD_PRELOAD library to intercept and rewrite the paths in glibc calls"; longDescription = '' libredirect is an LD_PRELOAD library to intercept and rewrite the paths in From d76ec523bb78af1f4c651025b27b6e9152c10662 Mon Sep 17 00:00:00 2001 From: zimbatm Date: Mon, 12 Nov 2018 00:08:18 +0100 Subject: [PATCH 2/5] use for cross-compilation --- pkgs/build-support/libredirect/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index 389abec982e0..0c24dbeb2070 100644 --- a/pkgs/build-support/libredirect/default.nix +++ b/pkgs/build-support/libredirect/default.nix @@ -6,7 +6,7 @@ stdenv.mkDerivation { unpackPhase = "cp ${./libredirect.c} libredirect.c"; buildPhase = '' - cc -Wall -std=c99 -O3 -shared libredirect.c -o libredirect.so -fPIC -ldl + $CC -Wall -std=c99 -O3 -shared libredirect.c -o libredirect.so -fPIC -ldl ''; installPhase = "mkdir -p $out/lib; cp libredirect.so $out/lib"; From 9ef52352bdce530e00372078e43d46dfebf5e91d Mon Sep 17 00:00:00 2001 From: zimbatm Date: Mon, 12 Nov 2018 00:09:36 +0100 Subject: [PATCH 3/5] assume that it works on all unix platforms --- pkgs/build-support/libredirect/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index 0c24dbeb2070..d3de805b2f92 100644 --- a/pkgs/build-support/libredirect/default.nix +++ b/pkgs/build-support/libredirect/default.nix @@ -12,7 +12,7 @@ stdenv.mkDerivation { installPhase = "mkdir -p $out/lib; cp libredirect.so $out/lib"; meta = { - platforms = stdenv.lib.platforms.linux ++ stdenv.lib.platforms.darwin; + platforms = stdenv.lib.platforms.unix; description = "An LD_PRELOAD library to intercept and rewrite the paths in glibc calls"; longDescription = '' libredirect is an LD_PRELOAD library to intercept and rewrite the paths in From ba1fddb31535c5721cf2c3913e704f0b258f656b Mon Sep 17 00:00:00 2001 From: aszlig Date: Mon, 12 Nov 2018 09:59:39 +0100 Subject: [PATCH 4/5] libredirect: Use extensions.sharedLibrary This is to make sure we get the correct shared library suffix of the target platform. While for example on Darwin it would even work with the hardcoded .so prefix it's IMHO a bit nicer to have the actual native extension. Signed-off-by: aszlig --- pkgs/build-support/libredirect/default.nix | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index d3de805b2f92..fec659ff5fda 100644 --- a/pkgs/build-support/libredirect/default.nix +++ b/pkgs/build-support/libredirect/default.nix @@ -5,11 +5,16 @@ stdenv.mkDerivation { unpackPhase = "cp ${./libredirect.c} libredirect.c"; + shlibext = stdenv.targetPlatform.extensions.sharedLibrary; + buildPhase = '' - $CC -Wall -std=c99 -O3 -shared libredirect.c -o libredirect.so -fPIC -ldl + $CC -Wall -std=c99 -O3 -shared libredirect.c \ + -o "libredirect$shlibext" -fPIC -ldl ''; - installPhase = "mkdir -p $out/lib; cp libredirect.so $out/lib"; + installPhase = '' + install -vD "libredirect$shlibext" "$out/lib/libredirect$shlibext" + ''; meta = { platforms = stdenv.lib.platforms.unix; From 34dd1c68f877912290fcad4bb8d4d3c0035ef5e6 Mon Sep 17 00:00:00 2001 From: aszlig Date: Mon, 12 Nov 2018 10:48:15 +0100 Subject: [PATCH 5/5] libredirect: Add a small test This is just a sanity check on whether the library correctly wraps the syscalls and it's using the "true" executable for posix_spawn() and execv(). The installCheckPhase is not executed if we are cross-compiling, so this shouldn't break cross-compilation. One thing I'm not actually sure is whether ${coreutils}/bin/true is universally available on all the platforms, nor whether all the functions we use in the test are available, but we can still fix that after we've found out about that. Signed-off-by: aszlig --- pkgs/build-support/libredirect/default.nix | 22 +++++++- pkgs/build-support/libredirect/test.c | 59 ++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 pkgs/build-support/libredirect/test.c diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index fec659ff5fda..09a3da6729a9 100644 --- a/pkgs/build-support/libredirect/default.nix +++ b/pkgs/build-support/libredirect/default.nix @@ -1,21 +1,39 @@ -{ stdenv }: +{ stdenv, coreutils }: stdenv.mkDerivation { name = "libredirect-0"; - unpackPhase = "cp ${./libredirect.c} libredirect.c"; + unpackPhase = '' + cp ${./libredirect.c} libredirect.c + cp ${./test.c} test.c + ''; shlibext = stdenv.targetPlatform.extensions.sharedLibrary; buildPhase = '' $CC -Wall -std=c99 -O3 -shared libredirect.c \ -o "libredirect$shlibext" -fPIC -ldl + + if [ -n "$doInstallCheck" ]; then + $CC -Wall -std=c99 -O3 test.c -o test + fi ''; installPhase = '' install -vD "libredirect$shlibext" "$out/lib/libredirect$shlibext" ''; + doInstallCheck = true; + + installCheckPhase = if stdenv.isDarwin then '' + NIX_REDIRECTS="/foo/bar/test=${coreutils}/bin/true" \ + DYLD_INSERT_LIBRARIES="$out/lib/libredirect$shlibext" \ + DYLD_FORCE_FLAT_NAMESPACE=1 ./test + '' else '' + NIX_REDIRECTS="/foo/bar/test=${coreutils}/bin/true" \ + LD_PRELOAD="$out/lib/libredirect$shlibext" ./test + ''; + meta = { platforms = stdenv.lib.platforms.unix; description = "An LD_PRELOAD library to intercept and rewrite the paths in glibc calls"; diff --git a/pkgs/build-support/libredirect/test.c b/pkgs/build-support/libredirect/test.c new file mode 100644 index 000000000000..b57664db3c19 --- /dev/null +++ b/pkgs/build-support/libredirect/test.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TESTPATH "/foo/bar/test" + +extern char **environ; + +void test_spawn(void) { + pid_t pid; + int ret; + posix_spawn_file_actions_t file_actions; + char *argv[] = {"true", NULL}; + + assert(posix_spawn_file_actions_init(&file_actions) == 0); + + ret = posix_spawn(&pid, TESTPATH, &file_actions, NULL, argv, environ); + + assert(ret == 0); + assert(waitpid(pid, NULL, 0) != -1); +} + +void test_execv(void) { + char *argv[] = {"true", NULL}; + assert(execv(TESTPATH, argv) == 0); +} + +int main(void) +{ + FILE *testfp; + int testfd; + struct stat testsb; + + testfp = fopen(TESTPATH, "r"); + assert(testfp != NULL); + fclose(testfp); + + testfd = open(TESTPATH, O_RDONLY); + assert(testfd != -1); + close(testfd); + + assert(access(TESTPATH, X_OK) == 0); + + assert(stat(TESTPATH, &testsb) != -1); + + test_spawn(); + test_execv(); + + /* If all goes well, this is never reached because test_execv() replaces + * the current process. + */ + return 0; +}