]> git.ipfire.org Git - pakfire.git/commitdiff
downloader: Handle download errors
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 12 Mar 2021 10:12:38 +0000 (10:12 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 12 Mar 2021 10:12:38 +0000 (10:12 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/downloader.c

index b9ed4b41db5bbcd24186a59c0d3a5b550bd0a2e7..1e6c0c2979cf9c883fb814ede228029d0ec3c01c 100644 (file)
@@ -345,15 +345,58 @@ static const char* curl_http_version(long v) {
        return "unknown";
 }
 
+static int pakfire_transfer_save(struct pakfire_downloader* downloader,
+               struct pakfire_transfer* transfer) {
+       struct utimbuf times;
+
+       // Remove destination (if it exists)
+       unlink(transfer->path);
+
+       // Move the temporary file to its destination
+       int r = link(transfer->tempfile, transfer->path);
+       if (r) {
+               ERROR(downloader->pakfire, "Could not link destination file %s: %s\n",
+                       transfer->path, strerror(errno));
+               return r;
+       }
+
+       // Filetime
+       curl_easy_getinfo(transfer->handle, CURLINFO_FILETIME_T, &times.modtime);
+       r = utime(transfer->path, &times);
+       if (r) {
+               ERROR(downloader->pakfire, "Could not set mtime of %s: %s\n",
+                       transfer->path, strerror(errno));
+       }
+
+       return 0;
+}
+
+static int pakfire_transfer_fail(struct pakfire_downloader* downloader,
+               struct pakfire_transfer* transfer) {
+       int r;
+
+       DEBUG(downloader->pakfire, "Transfer failed\n");
+
+       // Get file descriptor
+       int fd = fileno(transfer->f);
+
+       // Truncate downloaded data
+       r = ftruncate(fd, 0);
+       if (r)
+               return r;
+
+       return 0;
+}
+
 static int pakfire_transfer_done(struct pakfire_downloader* downloader,
                struct pakfire_transfer* transfer, CURLMsg* msg) {
        CURL* h = transfer->handle;
 
        int r;
+       long protocol;
        const char* url;
        long response_code;
        long http_version;
-       struct utimbuf times;
        double total_time;
        curl_off_t download_size;
        curl_off_t speed;
@@ -361,6 +404,9 @@ static int pakfire_transfer_done(struct pakfire_downloader* downloader,
        DEBUG(downloader->pakfire, "cURL transfer done: %d - %s\n",
                msg->data.result, curl_easy_strerror(msg->data.result));
 
+       // Protocol
+       curl_easy_getinfo(h, CURLINFO_PROTOCOL, &protocol);
+
        // Effective URL
        curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &url);
        if (url)
@@ -390,25 +436,36 @@ static int pakfire_transfer_done(struct pakfire_downloader* downloader,
        if (speed)
                DEBUG(downloader->pakfire, "  Download Speed: %ld bps\n", speed);
 
-       // Remove destination (if it exists)
-       unlink(transfer->path);
-
-       // Move the temporary file to its destination
-       r = link(transfer->tempfile, transfer->path);
-       if (r) {
-               ERROR(downloader->pakfire, "Could not link destination file %s: %s\n",
-                       transfer->path, strerror(errno));
-               return r;
-       }
+       switch (protocol) {
+               case CURLPROTO_FILE:
+                       r = pakfire_transfer_save(downloader, transfer);
+                       if (r)
+                               return r;
+                       break;
 
-       // Filetime
-       curl_easy_getinfo(h, CURLINFO_FILETIME_T, &times.modtime);
-       r = utime(transfer->path, &times);
-       if (r) {
-               ERROR(downloader->pakfire, "Could not set mtime of %s: %s\n",
-                       transfer->path, strerror(errno));
+               case CURLPROTO_HTTPS:
+               case CURLPROTO_HTTP:
+                       switch (response_code) {
+                               // 200 - OK
+                               case 200:
+                                       r = pakfire_transfer_save(downloader, transfer);
+                                       if (r)
+                                               return r;
+                                       break;
+
+                               // Treat all other response codes as an error
+                               default:
+                                       r = pakfire_transfer_fail(downloader, transfer);
+                                       if (r)
+                                               return r;
+
+                                       // Error
+                                       return 1;
+                       }
+                       break;
        }
 
+       // Success
        return 0;
 }
 
@@ -452,6 +509,7 @@ int pakfire_downloader_run(struct pakfire_downloader* downloader) {
        int r;
        int still_running;
        int msgs_left = -1;
+       int success = 0;
 
        do {
                // Make sure that we have up to parallel transfers active
@@ -480,7 +538,9 @@ int pakfire_downloader_run(struct pakfire_downloader* downloader) {
                                curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &transfer);
 
                                // Handle whatever comes after the transfer
-                               pakfire_transfer_done(downloader, transfer, msg);
+                               r = pakfire_transfer_done(downloader, transfer, msg);
+                               if (r)
+                                       success = r;
 
                                // Remove and destroy the handle
                                curl_multi_remove_handle(downloader->curl, transfer->handle);
@@ -498,5 +558,5 @@ int pakfire_downloader_run(struct pakfire_downloader* downloader) {
        } while (still_running || !TAILQ_EMPTY(&downloader->transfers));
 
        // Success
-       return 0;
+       return success;
 }