Blob Blame History Raw
From 614d7874bfa82cb19b328278590af0f99e1ec682 Mon Sep 17 00:00:00 2001
From: Jonathan Dieter <jdieter@gmail.com>
Date: Fri, 14 Jun 2019 23:13:30 +0100
Subject: [PATCH] Handle webservers that don't support ranges when downloading zck

Make sure we fall back to downloading full zchunk file if a webserver
doesn't support ranges.

Signed-off-by: Jonathan Dieter <jdieter@gmail.com>
---
 librepo/downloader.c     | 37 ++++++++++++++++++++++++++-----------
 librepo/downloadtarget.c |  1 +
 librepo/downloadtarget.h |  4 ++++
 3 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/librepo/downloader.c b/librepo/downloader.c
index 6189681..53161f7 100644
--- a/librepo/downloader.c
+++ b/librepo/downloader.c
@@ -473,7 +473,7 @@ lr_headercb(void *ptr, size_t size, size_t nmemb, void *userdata)
     }
 
     #ifdef WITH_ZCHUNK
-    if(lrtarget->target->is_zchunk)
+    if(lrtarget->target->is_zchunk && lrtarget->mirror->max_ranges > 0)
         return lr_zckheadercb(ptr, size, nmemb, userdata);
     #endif /* WITH_ZCHUNK */
 
@@ -586,7 +586,7 @@ lr_writecb(char *ptr, size_t size, size_t nmemb, void *userdata)
     size_t cur_written;
     LrTarget *target = (LrTarget *) userdata;
     #ifdef WITH_ZCHUNK
-    if(target->target->is_zchunk)
+    if(target->target->is_zchunk && target->mirror->max_ranges > 0)
         return lr_zck_writecb(ptr, size, nmemb, userdata);
     #endif /* WITH_ZCHUNK */
 
@@ -1240,6 +1240,12 @@ check_zck(LrTarget *target, GError **err)
     assert(!err || *err == NULL);
     assert(target && target->f && target->target);
 
+    if(target->mirror->max_ranges == 0) {
+        target->zck_state = LR_ZCK_DL_BODY;
+        target->target->expectedsize = target->target->origsize;
+        return TRUE;
+    }
+
     if(target->target->zck_dl == NULL) {
         target->target->zck_dl = zck_dl_init(NULL);
         if(target->target->zck_dl == NULL) {
@@ -2166,25 +2172,34 @@ check_transfer_statuses(LrDownload *dd, GError **err)
         if (target->target->is_zchunk) {
             zckCtx *zck = NULL;
             if (target->zck_state == LR_ZCK_DL_HEADER) {
-                if(!lr_zck_valid_header(target->target, target->target->path,
+                if(target->mirror->max_ranges > 0 &&
+                   !lr_zck_valid_header(target->target, target->target->path,
                                         fd, &transfer_err))
                     goto transfer_error;
             } else if(target->zck_state == LR_ZCK_DL_BODY) {
-                zckCtx *zck = zck_dl_get_zck(target->target->zck_dl);
-                if(zck == NULL) {
-                    g_set_error(&transfer_err, LR_DOWNLOADER_ERROR, LRE_ZCK,
-                                "Unable to get zchunk file from download context");
-                    goto transfer_error;
+                if(target->mirror->max_ranges > 0) {
+                    zckCtx *zck = zck_dl_get_zck(target->target->zck_dl);
+                    if(zck == NULL) {
+                        g_set_error(&transfer_err, LR_DOWNLOADER_ERROR, LRE_ZCK,
+                                    "Unable to get zchunk file from download context");
+                        goto transfer_error;
+                    }
+                    if(zck_failed_chunks(zck) == 0 && zck_missing_chunks(zck) == 0)
+                        target->zck_state = LR_ZCK_DL_FINISHED;
+                } else {
+                    if(target->range_fail) {
+                        target->range_fail = FALSE;
+                    } else {
+                        target->zck_state = LR_ZCK_DL_FINISHED;
+                    }
                 }
-                if(zck_failed_chunks(zck) == 0 && zck_missing_chunks(zck) == 0)
-                    target->zck_state = LR_ZCK_DL_FINISHED;
             }
             if(target->zck_state == LR_ZCK_DL_FINISHED) {
                 zck = lr_zck_init_read(target->target, target->target->path, fd,
                                        &transfer_err);
                 if(!zck)
                     goto transfer_error;
-                if(!zck_validate_checksums(zck)) {
+                if(zck_validate_checksums(zck) < 1) {
                     zck_free(&zck);
                     g_set_error(&transfer_err, LR_DOWNLOADER_ERROR, LRE_BADCHECKSUM,
                                 "At least one of the zchunk checksums doesn't match in %s",
diff --git a/librepo/downloadtarget.c b/librepo/downloadtarget.c
index d20aa44..40c10f3 100644
--- a/librepo/downloadtarget.c
+++ b/librepo/downloadtarget.c
@@ -100,6 +100,7 @@ lr_downloadtarget_new(LrHandle *handle,
     target->fn              = lr_string_chunk_insert(target->chunk, fn);
     target->checksums       = possiblechecksums;
     target->expectedsize    = expectedsize;
+    target->origsize        = expectedsize;
     target->resume          = resume;
     target->progresscb      = progresscb;
     target->cbdata          = cbdata;
diff --git a/librepo/downloadtarget.h b/librepo/downloadtarget.h
index f4c1f26..c935219 100644
--- a/librepo/downloadtarget.h
+++ b/librepo/downloadtarget.h
@@ -88,6 +88,10 @@ typedef struct {
     gint64 expectedsize; /*!<
         Expected size of the target */
 
+    gint64 origsize; /*!<
+        Original expected size of the target.  Sometimes expectedsize will
+        change, especially if zchunk is in use, but this will never change */
+
     gboolean resume; /*!<
         Resume:
          0  - no resume, download whole file,
--
libgit2 0.28.2