summary refs log tree commit diff
diff options
context:
space:
mode:
authorRobert Scott <code@humanleg.org.uk>2022-01-16 21:41:41 +0000
committerRobert Scott <code@humanleg.org.uk>2022-01-18 20:20:28 +0000
commit2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0 (patch)
treea8a534237504980b8bc85014f37e1e317d928eb1
parentb3a7dc22d12e8c7007a71e965ee24f6b609fe212 (diff)
downloadnixpkgs-2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0.tar
nixpkgs-2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0.tar.gz
nixpkgs-2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0.tar.bz2
nixpkgs-2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0.tar.lz
nixpkgs-2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0.tar.xz
nixpkgs-2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0.tar.zst
nixpkgs-2185a70fa4eec7a42dc3c0cce61ece4b71b0a7a0.zip
libredirect: add support for mkstemp family of functions
-rw-r--r--pkgs/build-support/libredirect/default.nix4
-rw-r--r--pkgs/build-support/libredirect/libredirect.c65
-rw-r--r--pkgs/build-support/libredirect/test.c40
3 files changed, 108 insertions, 1 deletions
diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix
index 9a35db97c9f..4c344a24b93 100644
--- a/pkgs/build-support/libredirect/default.nix
+++ b/pkgs/build-support/libredirect/default.nix
@@ -57,7 +57,9 @@ else stdenv.mkDerivation rec {
     ''}
 
     if [ -n "$doInstallCheck" ]; then
-      $CC -Wall -std=c99 -D_POSIX_C_SOURCE=200809L -O3 test.c -o test
+      $CC -Wall -std=c99 \
+        ${lib.optionalString (!stdenv.isDarwin) "-D_GNU_SOURCE"} \
+        -O3 test.c -o test
     fi
 
     runHook postBuild
diff --git a/pkgs/build-support/libredirect/libredirect.c b/pkgs/build-support/libredirect/libredirect.c
index e33199402c4..a59bc1bbaa3 100644
--- a/pkgs/build-support/libredirect/libredirect.c
+++ b/pkgs/build-support/libredirect/libredirect.c
@@ -84,6 +84,13 @@ static const char * rewrite(const char * path, char * buf)
     return path;
 }
 
+static char * rewrite_non_const(char * path, char * buf)
+{
+    // as long as the argument `path` is non-const, we can consider discarding
+    // the const qualifier of the return value to be safe.
+    return (char *)rewrite(path, buf);
+}
+
 static int open_needs_mode(int flags)
 {
 #ifdef O_TMPFILE
@@ -378,3 +385,61 @@ WRAPPER(int, rmdir)(const char *path)
     return rmdir_real(rewrite(path, buf));
 }
 WRAPPER_DEF(rmdir)
+
+static void copy_temp_wildcard(char * dest, char * src, int suffixlen) {
+    int dest_len = strnlen(dest, PATH_MAX);
+    int src_len = strnlen(src, PATH_MAX);
+    memcpy(dest + dest_len - (6 + suffixlen), src + src_len - (6 + suffixlen), 6);
+}
+
+WRAPPER(int, mkstemp)(char *template)
+{
+    int (*mkstemp_real) (char *template) = LOOKUP_REAL(mkstemp);
+    char buf[PATH_MAX];
+    char * rewritten = rewrite_non_const(template, buf);
+    int retval = mkstemp_real(rewritten);
+    if (retval >= 0 && rewritten != template) {
+        copy_temp_wildcard(template, rewritten, 0);
+    }
+    return retval;
+}
+WRAPPER_DEF(mkstemp)
+
+WRAPPER(int, mkostemp)(char *template, int flags)
+{
+    int (*mkostemp_real) (char *template, int flags) = LOOKUP_REAL(mkostemp);
+    char buf[PATH_MAX];
+    char * rewritten = rewrite_non_const(template, buf);
+    int retval = mkostemp_real(rewritten, flags);
+    if (retval >= 0 && rewritten != template) {
+        copy_temp_wildcard(template, rewritten, 0);
+    }
+    return retval;
+}
+WRAPPER_DEF(mkostemp)
+
+WRAPPER(int, mkstemps)(char *template, int suffixlen)
+{
+    int (*mkstemps_real) (char *template, int suffixlen) = LOOKUP_REAL(mkstemps);
+    char buf[PATH_MAX];
+    char * rewritten = rewrite_non_const(template, buf);
+    int retval = mkstemps_real(rewritten, suffixlen);
+    if (retval >= 0 && rewritten != template) {
+        copy_temp_wildcard(template, rewritten, suffixlen);
+    }
+    return retval;
+}
+WRAPPER_DEF(mkstemps)
+
+WRAPPER(int, mkostemps)(char *template, int suffixlen, int flags)
+{
+    int (*mkostemps_real) (char *template, int suffixlen, int flags) = LOOKUP_REAL(mkostemps);
+    char buf[PATH_MAX];
+    char * rewritten = rewrite_non_const(template, buf);
+    int retval = mkostemps_real(rewritten, suffixlen, flags);
+    if (retval >= 0 && rewritten != template) {
+        copy_temp_wildcard(template, rewritten, suffixlen);
+    }
+    return retval;
+}
+WRAPPER_DEF(mkostemps)
diff --git a/pkgs/build-support/libredirect/test.c b/pkgs/build-support/libredirect/test.c
index c546a895828..f15b44ff3d8 100644
--- a/pkgs/build-support/libredirect/test.c
+++ b/pkgs/build-support/libredirect/test.c
@@ -1,9 +1,11 @@
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <spawn.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 #include <sys/stat.h>
@@ -43,11 +45,25 @@ void test_subprocess(void) {
     assert(system(SUBTEST) == 0);
 }
 
+void assert_mktemp_path(
+    const char * orig_prefix,
+    const char * orig_suffix,
+    const char * updated
+) {
+    // prefix unchanged
+    assert(strncmp(updated, orig_prefix, strlen(orig_prefix)) == 0);
+    // wildcards replaced
+    assert(strcmp(updated + strlen(orig_prefix), "XXXXXX") != 0);
+    // suffix unchanged
+    assert(strcmp(updated + strlen(orig_prefix) + 6, orig_suffix) == 0);
+}
+
 int main(int argc, char *argv[])
 {
     FILE *testfp;
     int testfd;
     struct stat testsb;
+    char buf[PATH_MAX];
 
     testfp = fopen(TESTPATH, "r");
     assert(testfp != NULL);
@@ -77,6 +93,30 @@ int main(int argc, char *argv[])
 #endif
     assert(unlinkat(123, TESTDIR "/dir-mkdirat", AT_REMOVEDIR) == 0);
 
+    strncpy(buf, TESTDIR "/tempXXXXXX", PATH_MAX);
+    testfd = mkstemp(buf);
+    assert(testfd > 0);
+    assert_mktemp_path(TESTDIR "/temp", "", buf);
+    close(testfd);
+
+    strncpy(buf, TESTDIR "/tempXXXXXX", PATH_MAX);
+    testfd = mkostemp(buf, 0);
+    assert(testfd > 0);
+    assert_mktemp_path(TESTDIR "/temp", "", buf);
+    close(testfd);
+
+    strncpy(buf, TESTDIR "/tempXXXXXX.test", PATH_MAX);
+    testfd = mkstemps(buf, strlen(".test"));
+    assert(testfd > 0);
+    assert_mktemp_path(TESTDIR "/temp", ".test", buf);
+    close(testfd);
+
+    strncpy(buf, TESTDIR "/tempXXXXXX.test", PATH_MAX);
+    testfd = mkostemps(buf, strlen(".test"), 0);
+    assert(testfd > 0);
+    assert_mktemp_path(TESTDIR "/temp", ".test", buf);
+    close(testfd);
+
     test_spawn();
     test_system();