]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_cb_wrt: fix no-clobber error handling
authorDaniel Stenberg <daniel@haxx.se>
Mon, 16 Mar 2026 13:51:52 +0000 (14:51 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 16 Mar 2026 14:31:44 +0000 (15:31 +0100)
When saving a file with --no-clobber, make sure the existing file name
remains set when creating the name fails. In a retry scenario, it comes
back and uses that variable again.

Add test 3036 to verify.

Reported-by: James Fuller
Closes #20939

src/tool_cb_wrt.c
tests/data/Makefile.am
tests/data/test3036 [new file with mode: 0644]

index 1d2b81ea7cacb6e3bb09260687f50d464465cb66..d412a1ea88d70b18a8ecc076b5e772d6396ffced 100644 (file)
@@ -61,6 +61,7 @@ bool tool_create_output_file(struct OutStruct *outs,
     if(config->file_clobber_mode == CLOBBER_NEVER && fd == -1) {
       int next_num = 1;
       struct dynbuf fbuffer;
+      char *newfile;
       curlx_dyn_init(&fbuffer, 1025);
       /* !checksrc! disable ERRNOVAR 1 */
       while(fd == -1 && /* have not successfully opened a file */
@@ -78,8 +79,11 @@ bool tool_create_output_file(struct OutStruct *outs,
           /* Keep retrying in the hope that it is not interrupted sometime */
         } while(fd == -1 && errno == EINTR);
       }
-      outs->filename = curlx_dyn_ptr(&fbuffer); /* remember the new one */
-      outs->alloc_filename = TRUE;
+      newfile = curlx_dyn_ptr(&fbuffer); /* remember the new one */
+      if(newfile) {
+        outs->filename = newfile;
+        outs->alloc_filename = TRUE;
+      }
     }
     /* An else statement to not overwrite existing files and not retry with
        new numbered names (which would cover
index 52bee86739c60c8723693af8605eddac14364555..97bb7b3bbeea1f6dfc621146ca671ddfb085d000 100644 (file)
@@ -277,7 +277,7 @@ test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \
 test3008 test3009 test3010 test3011 test3012 test3013 test3014 test3015 \
 test3016 test3017 test3018 test3019 test3020 test3021 test3022 test3023 \
 test3024 test3025 test3026 test3027 test3028 test3029 test3030 test3031 \
-test3032 test3033 test3034 test3035 \
+test3032 test3033 test3034 test3035 test3036 \
 \
 test3100 test3101 test3102 test3103 test3104 test3105 \
 \
diff --git a/tests/data/test3036 b/tests/data/test3036
new file mode 100644 (file)
index 0000000..cac51c7
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+-O
+-J
+--output-dir
+--retry
+--no-clobber
+</keywords>
+</info>
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Content-Length: 6
+Connection: close
+Content-Disposition: inline; filename="MMM%TESTNUMBERMMM"
+Content-Type: text/html
+
+-foo-
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+http
+</features>
+<name>
+--no-clobber, --retry and --output-dir identifying a file
+</name>
+<command option="no-output">
+http://%HOSTIP:%HTTPPORT/ --no-clobber --output-dir %LOGDIR/present -OJ --retry 1 --retry-all-errors
+</command>
+<file name="%LOGDIR/present">
+present
+</file>
+</client>
+
+<verify>
+<protocol crlf="headers">
+GET / HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET / HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+# it fails because it cannot create the output file
+<errorcode>
+23
+</errorcode>
+</verify>
+</testcase>