From 859ac3602159ef3df77ac4cb1ae191b069ff1b5b Mon Sep 17 00:00:00 2001 From: Gisle Vanem Date: Sun, 17 Dec 2017 17:26:10 -0500 Subject: [PATCH] tool_getparam: Support size modifiers for --max-filesize - Move the size modifier detection code from limit-rate to its own function so that it can also be used with max-filesize. Size modifiers are the suffixes such as G (gigabyte), M (megabyte) etc. For example --max-filesize 1G Ref: https://curl.haxx.se/mail/archive-2017-12/0000.html Closes https://github.com/curl/curl/pull/2179 --- docs/cmdline-opts/limit-rate.d | 2 +- docs/cmdline-opts/max-filesize.d | 4 ++ src/tool_getparam.c | 99 +++++++++++++++++++++----------- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/docs/cmdline-opts/limit-rate.d b/docs/cmdline-opts/limit-rate.d index 8784a84d3..06c456e3e 100644 --- a/docs/cmdline-opts/limit-rate.d +++ b/docs/cmdline-opts/limit-rate.d @@ -8,7 +8,7 @@ your transfer not to use your entire bandwidth. To make it slower than it otherwise would be. The given speed is measured in bytes/second, unless a suffix is appended. -Appending 'k' or 'K' will count the number as kilobytes, 'm' or M' makes it +Appending 'k' or 'K' will count the number as kilobytes, 'm' or 'M' makes it megabytes, while 'g' or 'G' makes it gigabytes. Examples: 200K, 3m and 1G. If you also use the --speed-limit option, that option will take precedence and diff --git a/docs/cmdline-opts/max-filesize.d b/docs/cmdline-opts/max-filesize.d index e92ef5837..50d5266e1 100644 --- a/docs/cmdline-opts/max-filesize.d +++ b/docs/cmdline-opts/max-filesize.d @@ -7,6 +7,10 @@ Specify the maximum size (in bytes) of a file to download. If the file requested is larger than this value, the transfer will not start and curl will return with exit code 63. +A size modifier may be used. For example, Appending 'k' or 'K' will count the +number as kilobytes, 'm' or 'M' makes it megabytes, while 'g' or 'G' makes it +gigabytes. Examples: 200K, 3m and 1G. (Added in 7.58.0) + \fBNOTE:\fP The file size is not always known prior to download, and for such files this option has no effect even if the file transfer ends up being larger than this given limit. This concerns both FTP and HTTP transfers. diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 12e3abd55..3f4046417 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -424,6 +424,58 @@ GetFileAndPassword(char *nextarg, char **file, char **password) cleanarg(nextarg); } +/* Get a size parameter for '--limit-rate' or '--max-filesize'. + * We support a 'G', 'M' or 'K' suffix too. + */ +static ParameterError GetSizeParameter(struct GlobalConfig *global, + const char *arg, + const char *which, + curl_off_t *value_out) +{ + char *unit; + curl_off_t value; + + if(curlx_strtoofft(arg, &unit, 0, &value)) { + warnf(global, "invalid number specified for %s\n", which); + return PARAM_BAD_USE; + } + + if(!*unit) + unit = (char *)"b"; + else if(strlen(unit) > 1) + unit = (char *)"w"; /* unsupported */ + + switch(*unit) { + case 'G': + case 'g': + if(value > (CURL_OFF_T_MAX / (1024*1024*1024))) + return PARAM_NUMBER_TOO_LARGE; + value *= 1024*1024*1024; + break; + case 'M': + case 'm': + if(value > (CURL_OFF_T_MAX / (1024*1024))) + return PARAM_NUMBER_TOO_LARGE; + value *= 1024*1024; + break; + case 'K': + case 'k': + if(value > (CURL_OFF_T_MAX / 1024)) + return PARAM_NUMBER_TOO_LARGE; + value *= 1024; + break; + case 'b': + case 'B': + /* for plain bytes, leave as-is */ + break; + default: + warnf(global, "unsupported %s unit. Use G, M, K or B!\n", which); + return PARAM_BAD_USE; + } + *value_out = value; + return PARAM_OK; +} + ParameterError getparameter(const char *flag, /* f or -long-flag */ char *nextarg, /* NULL if unset */ bool *usedarg, /* set to TRUE if the arg @@ -589,40 +641,11 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ break; case 'i': /* --limit-rate */ { - /* We support G, M, K too */ - char *unit; curl_off_t value; - if(curlx_strtoofft(nextarg, &unit, 0, &value)) { - warnf(global, "unsupported rate\n"); - return PARAM_BAD_USE; - } + ParameterError pe = GetSizeParameter(global, nextarg, "rate", &value); - if(!*unit) - unit = (char *)"b"; - else if(strlen(unit) > 1) - unit = (char *)"w"; /* unsupported */ - - switch(*unit) { - case 'G': - case 'g': - value *= 1024*1024*1024; - break; - case 'M': - case 'm': - value *= 1024*1024; - break; - case 'K': - case 'k': - value *= 1024; - break; - case 'b': - case 'B': - /* for plain bytes, leave as-is */ - break; - default: - warnf(global, "unsupported rate unit. Use G, M, K or B!\n"); - return PARAM_BAD_USE; - } + if(pe != PARAM_OK) + return pe; config->recvpersecond = value; config->sendpersecond = value; } @@ -753,9 +776,15 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ return PARAM_LIBCURL_DOESNT_SUPPORT; break; case 'y': /* --max-filesize */ - err = str2offset(&config->max_filesize, nextarg); - if(err) - return err; + { + curl_off_t value; + ParameterError pe = + GetSizeParameter(global, nextarg, "max-filesize", &value); + + if(pe != PARAM_OK) + return pe; + config->max_filesize = value; + } break; case 'z': /* --disable-eprt */ config->disable_eprt = toggle;