block: Handle curl 7.55.0, 7.85.0 version changes

* 7.55.0 deprecates CURLINFO_CONTENT_LENGTH_DOWNLOAD in favour of a *_T
  version, which returns curl_off_t instead of a double.
* 7.85.0 deprecates CURLOPT_PROTOCOLS and CURLOPT_REDIR_PROTOCOLS in
  favour of *_STR variants, specifying the desired protocols via a
  string.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1440
Signed-off-by: Anton Johansson <anjo@rev.ng>
Message-Id: <20230123201431.23118-1-anjo@rev.ng>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit e7b8d9d038)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
Anton Johansson 2023-01-23 21:14:31 +01:00 committed by Michael Tokarev
parent b05232a256
commit 7c8a67ed46

View File

@ -37,8 +37,15 @@
// #define DEBUG_VERBOSE // #define DEBUG_VERBOSE
/* CURL 7.85.0 switches to a string based API for specifying
* the desired protocols.
*/
#if LIBCURL_VERSION_NUM >= 0x075500
#define PROTOCOLS "HTTP,HTTPS,FTP,FTPS"
#else
#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
CURLPROTO_FTP | CURLPROTO_FTPS) CURLPROTO_FTP | CURLPROTO_FTPS)
#endif
#define CURL_NUM_STATES 8 #define CURL_NUM_STATES 8
#define CURL_NUM_ACB 8 #define CURL_NUM_ACB 8
@ -509,9 +516,18 @@ static int curl_init_state(BDRVCURLState *s, CURLState *state)
* obscure protocols. For example, do not allow POP3/SMTP/IMAP see * obscure protocols. For example, do not allow POP3/SMTP/IMAP see
* CVE-2013-0249. * CVE-2013-0249.
* *
* Restricting protocols is only supported from 7.19.4 upwards. * Restricting protocols is only supported from 7.19.4 upwards. Note:
* version 7.85.0 deprecates CURLOPT_*PROTOCOLS in favour of a string
* based CURLOPT_*PROTOCOLS_STR API.
*/ */
#if LIBCURL_VERSION_NUM >= 0x071304 #if LIBCURL_VERSION_NUM >= 0x075500
if (curl_easy_setopt(state->curl,
CURLOPT_PROTOCOLS_STR, PROTOCOLS) ||
curl_easy_setopt(state->curl,
CURLOPT_REDIR_PROTOCOLS_STR, PROTOCOLS)) {
goto err;
}
#elif LIBCURL_VERSION_NUM >= 0x071304
if (curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS) || if (curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS) ||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS)) { curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS)) {
goto err; goto err;
@ -669,7 +685,12 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
const char *file; const char *file;
const char *cookie; const char *cookie;
const char *cookie_secret; const char *cookie_secret;
double d; /* CURL >= 7.55.0 uses curl_off_t for content length instead of a double */
#if LIBCURL_VERSION_NUM >= 0x073700
curl_off_t cl;
#else
double cl;
#endif
const char *secretid; const char *secretid;
const char *protocol_delimiter; const char *protocol_delimiter;
int ret; int ret;
@ -796,27 +817,36 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
} }
if (curl_easy_perform(state->curl)) if (curl_easy_perform(state->curl))
goto out; goto out;
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) { /* CURL 7.55.0 deprecates CURLINFO_CONTENT_LENGTH_DOWNLOAD in favour of
* the *_T version which returns a more sensible type for content length.
*/
#if LIBCURL_VERSION_NUM >= 0x073700
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl)) {
goto out; goto out;
} }
#else
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl)) {
goto out;
}
#endif
/* Prior CURL 7.19.4 return value of 0 could mean that the file size is not /* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
* know or the size is zero. From 7.19.4 CURL returns -1 if size is not * know or the size is zero. From 7.19.4 CURL returns -1 if size is not
* known and zero if it is really zero-length file. */ * known and zero if it is really zero-length file. */
#if LIBCURL_VERSION_NUM >= 0x071304 #if LIBCURL_VERSION_NUM >= 0x071304
if (d < 0) { if (cl < 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE, pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Server didn't report file size."); "Server didn't report file size.");
goto out; goto out;
} }
#else #else
if (d <= 0) { if (cl <= 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE, pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Unknown file size or zero-length file."); "Unknown file size or zero-length file.");
goto out; goto out;
} }
#endif #endif
s->len = d; s->len = cl;
if ((!strncasecmp(s->url, "http://", strlen("http://")) if ((!strncasecmp(s->url, "http://", strlen("http://"))
|| !strncasecmp(s->url, "https://", strlen("https://"))) || !strncasecmp(s->url, "https://", strlen("https://")))