tool_cb_wrt: fix no-clobber error handling

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
This commit is contained in:
Daniel Stenberg 2026-03-16 14:51:52 +01:00
parent 3525ed9b2f
commit 29cb750fc2
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 69 additions and 3 deletions

View 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

View 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 \
\

62
tests/data/test3036 Normal file
View file

@ -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>