summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2022-02-24 10:30:10 +0100
committerDaniel Stenberg <daniel@haxx.se>2022-03-10 19:57:55 +0100
commit08a96c6e4e6cf6a1917a117db1b5394713e3f01f (patch)
tree5c4692cc312e191f61e27c3f45077d92951f0d69
parent7b0fd39db21a9291b4189d6e5b05ade40b3dce58 (diff)
downloadcurl-08a96c6e4e6cf6a1917a117db1b5394713e3f01f.tar.gz
curl: add --remove-on-error
If a transfer returns an error, using this option makes curl remove the leftover downloded (partial) local file before exiting. Added test 376 to verify Closes #8503
-rw-r--r--docs/cmdline-opts/Makefile.inc1
-rw-r--r--docs/cmdline-opts/remove-on-error.d12
-rw-r--r--docs/options-in-versions1
-rw-r--r--src/tool_cfgable.h2
-rw-r--r--src/tool_getparam.c6
-rw-r--r--src/tool_listhelp.c3
-rw-r--r--src/tool_operate.c4
-rw-r--r--tests/data/Makefile.inc2
-rw-r--r--tests/data/test37664
9 files changed, 93 insertions, 2 deletions
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index afa3d7931..3f6d00831 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -203,6 +203,7 @@ DPAGES = \
remote-name-all.d \
remote-name.d \
remote-time.d \
+ remove-on-error.d \
request-target.d \
request.d \
resolve.d \
diff --git a/docs/cmdline-opts/remove-on-error.d b/docs/cmdline-opts/remove-on-error.d
new file mode 100644
index 000000000..7c4b83a5c
--- /dev/null
+++ b/docs/cmdline-opts/remove-on-error.d
@@ -0,0 +1,12 @@
+Long: remove-on-error
+Help: Remove output file on errors
+See-also: fail
+Category: curl
+Example: --remove-on-error -o output $URL
+Added: 7.83.0
+---
+When curl returns an error when told to save output in a local file, this
+option removes that saved file before exiting. This prevevents curl from
+leaving a partial file in the case of an error during transfer.
+
+If the output is not a file, this option has no effect.
diff --git a/docs/options-in-versions b/docs/options-in-versions
index 5d242b8ff..559a33276 100644
--- a/docs/options-in-versions
+++ b/docs/options-in-versions
@@ -191,6 +191,7 @@
--remote-name (-O) 4.0
--remote-name-all 7.19.0
--remote-time (-R) 7.9
+--remove-on-error 7.83.0
--request (-X) 6.0
--request-target 7.55.0
--resolve 7.21.3
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index a06ef6028..4a420db32 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -294,6 +294,8 @@ struct OperationConfig {
struct OperationConfig *prev;
struct OperationConfig *next; /* Always last in the struct */
struct State state; /* for create_transfer() */
+ bool rm_partial; /* on error, remove partially written output
+ files */
};
struct GlobalConfig {
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index 56964394b..b31583299 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -284,6 +284,7 @@ static const struct LongShort aliases[]= {
{"fb", "styled-output", ARG_BOOL},
{"fc", "mail-rcpt-allowfails", ARG_BOOL},
{"fd", "fail-with-body", ARG_BOOL},
+ {"fe", "remove-on-error", ARG_BOOL},
{"F", "form", ARG_STRING},
{"Fs", "form-string", ARG_STRING},
{"g", "globoff", ARG_BOOL},
@@ -1830,7 +1831,10 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
case 'd': /* --fail-with-body */
config->failwithbody = toggle;
break;
- default: /* --fail (hard on errors) */
+ case 'e': /* --remove-on-error */
+ config->rm_partial = toggle;
+ break;
+ default: /* --fail (hard on errors) */
config->failonerror = toggle;
break;
}
diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c
index 3bca52c0e..33ebda25f 100644
--- a/src/tool_listhelp.c
+++ b/src/tool_listhelp.c
@@ -574,6 +574,9 @@ const struct helptxt helptext[] = {
{"-R, --remote-time",
"Set the remote file's time on the local output",
CURLHELP_OUTPUT},
+ {" --remove-on-error",
+ "Remove output file on errors",
+ CURLHELP_CURL},
{"-X, --request <method>",
"Specify request method to use",
CURLHELP_CONNECTION},
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 37ff44795..2e576d0d0 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -595,6 +595,10 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
if(global->showerror)
fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
}
+ if(result && config->rm_partial) {
+ notef(global, "Removing output file: %s", per->outfile);
+ unlink(per->outfile);
+ }
}
/* File time can only be set _after_ the file has been closed */
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 80901c771..6a32dd678 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -61,7 +61,7 @@ test334 test335 test336 test337 test338 test339 test340 test341 test342 \
test343 test344 test345 test346 test347 test348 test349 test350 test351 \
test352 test353 test354 test355 test356 test357 test358 test359 test360 \
test361 test362 test363 test364 test365 test366 test367 test368 test369 \
-test370 test371 test372 test373 test374 test375 \
+test370 test371 test372 test373 test374 test375 test376 \
\
test380 test381 test383 test384 test385 test386 \
\
diff --git a/tests/data/test376 b/tests/data/test376
new file mode 100644
index 000000000..7406d5b24
--- /dev/null
+++ b/tests/data/test376
@@ -0,0 +1,64 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+
+#
+# Crafted to cause error 18
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK swsclose
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 75
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP GET
+ </name>
+ <command option="no-output">
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/save-%TESTNUMBER --remove-on-error
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot". hyper doesn't do error 18
+<verify>
+<errorcode>
+%if hyper
+56
+%else
+18
+%endif
+</errorcode>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+
+# the file should be empty now
+<file name="log/save-%TESTNUMBER">
+</file>
+</verify>
+</testcase>