From 14252cb4a8b8b1a6486ac015db5fa2881512ca17 Mon Sep 17 00:00:00 2001 From: FireFly Date: Sat, 5 Apr 2025 17:44:30 +0200 Subject: [PATCH] libstore: move away from deprecated curl calls CURLINFO_PROTOCOL [1] is deprecated in favour of CURLINFO_SCHEME, which unfortunately requires a case-insensitive string check to tell the URL scheme used. While we're here, also cache the status code returned from `getHTTPStatus`. CURLOPT_PROGRESSFUNCTION [2] is deprecated in favour of CURLOPT_XFERINFOFUNCTION, which simply uses more appropriate types for the parameters of the callback. Another step toward fg#744 [1]: https://curl.se/libcurl/c/CURLINFO_PROTOCOL.html [2]: https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html Change-Id: Icd1feacad45ab5df71d95f4ef370df41ee1393ea --- lix/libstore/filetransfer.cc | 44 ++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/lix/libstore/filetransfer.cc b/lix/libstore/filetransfer.cc index cfc340874..243781561 100644 --- a/lix/libstore/filetransfer.cc +++ b/lix/libstore/filetransfer.cc @@ -79,15 +79,41 @@ struct curlFileTransfer : public FileTransfer char errbuf[CURL_ERROR_SIZE]; inline static const std::set successfulStatuses {200, 201, 204, 206, 304, 0 /* other protocol */}; + + std::optional httpStatusCode; + + /* Get the scheme for the current curl handle, or none if curl returns NULL. + * Ensures the scheme is always casefolded to lowercase */ + std::optional getCurlScheme() { + char *scheme_raw = nullptr; + if (curl_easy_getinfo(req.get(), CURLINFO_SCHEME, &scheme_raw) != CURLE_OK) { + throw nix::Error("could not get scheme used from curl handle"); + } + if (scheme_raw) { + return toLower(std::string(scheme_raw)); + } else { + return {}; + } + } + /* Get the HTTP status code, or 0 for other protocols. */ long getHTTPStatus() { - long httpStatus = 0; - long protocol = 0; - curl_easy_getinfo(req.get(), CURLINFO_PROTOCOL, &protocol); - if (protocol == CURLPROTO_HTTP || protocol == CURLPROTO_HTTPS) - curl_easy_getinfo(req.get(), CURLINFO_RESPONSE_CODE, &httpStatus); - return httpStatus; + if (httpStatusCode) { + return *httpStatusCode; + } + + long statusCode = 0; + + std::optional scheme = getCurlScheme(); + if (scheme == "http" || scheme == "https") { + if (curl_easy_getinfo(req.get(), CURLINFO_RESPONSE_CODE, &statusCode) != CURLE_OK) { + throw nix::Error("could not get response code from curl handle"); + } + } + + httpStatusCode = statusCode; + return statusCode; } std::string verb() const @@ -156,7 +182,7 @@ struct curlFileTransfer : public FileTransfer curl_easy_setopt(req.get(), CURLOPT_HEADERFUNCTION, TransferItem::headerCallbackWrapper); curl_easy_setopt(req.get(), CURLOPT_HEADERDATA, this); - curl_easy_setopt(req.get(), CURLOPT_PROGRESSFUNCTION, progressCallbackWrapper); + curl_easy_setopt(req.get(), CURLOPT_XFERINFOFUNCTION, progressCallbackWrapper); curl_easy_setopt(req.get(), CURLOPT_PROGRESSDATA, this); curl_easy_setopt(req.get(), CURLOPT_NOPROGRESS, 0); @@ -328,7 +354,7 @@ struct curlFileTransfer : public FileTransfer return static_cast(userp)->headerCallback(contents, size, nmemb); } - int progressCallback(double dltotal, double dlnow) + int progressCallback(curl_off_t dltotal, curl_off_t dlnow) { try { act.progress(dlnow, dltotal); @@ -338,7 +364,7 @@ struct curlFileTransfer : public FileTransfer return _isInterrupted; } - static int progressCallbackWrapper(void * userp, double dltotal, double dlnow, double ultotal, double ulnow) + static int progressCallbackWrapper(void * userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { return static_cast(userp)->progressCallback(dltotal, dlnow); }