diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index fec659ff5fda94f..09a3da6729a9fd8 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 000000000000000..b57664db3c19fb2 --- /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; +}