From 791e683e0150e0f3bc82416e6ecbf711bfd949c4 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sun, 28 Jun 2015 04:28:55 +0200 Subject: [PATCH] fetch: handle GET with offset == length. While xbps_fetch_file() creates the .part file and for whatever reason it did not finish properly to rename the file, it could request the server to restart the download with offset set to file size, resulting in HTTP 416 return code. Handle this case by checking if the server returns 416 and then checking if the returned file size matches the requested offset and just rename the file. Thanks to @beefcurtains for the test case. --- lib/download.c | 5 +++++ lib/fetch/http.c | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/download.c b/lib/download.c index f2cd4a64..7dc67295 100644 --- a/lib/download.c +++ b/lib/download.c @@ -173,6 +173,9 @@ xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri, const char *filen if (fetchLastErrCode == FETCH_UNCHANGED) { /* Last-Modified matched */ goto fetch_file_out; + } else if (fetchLastErrCode == FETCH_PROTO && url_st.size == stp->st_size) { + /* 413, requested offset == length */ + goto rename_file; } rv = -1; goto fetch_file_out; @@ -257,6 +260,7 @@ xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri, const char *filen */ xbps_set_cb_fetch(xhp, url_st.size, url->offset, bytes_dload, filename, false, false, true); + /* * Update mtime in local file to match remote file if transfer * was successful. @@ -271,6 +275,7 @@ xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri, const char *filen (void)close(fd); fd = -1; +rename_file: /* File downloaded successfully, rename to destfile */ if (rename(tempfile, filename) == -1) { xbps_dbg_printf(xhp, "failed to rename %s to %s: %s", diff --git a/lib/fetch/http.c b/lib/fetch/http.c index 25840a4c..f2d80bbe 100644 --- a/lib/fetch/http.c +++ b/lib/fetch/http.c @@ -1133,6 +1133,12 @@ http_request(struct url *URL, const char *op, struct url_stat *us, goto ouch; } + /* fill in stats */ + if (us) { + us->size = size; + us->atime = us->mtime = mtime; + } + /* check for inconsistencies */ if (clength != -1 && length != -1 && clength != length) { http_seterr(HTTP_PROTOCOL_ERROR); @@ -1142,6 +1148,7 @@ http_request(struct url *URL, const char *op, struct url_stat *us, clength = length; if (clength != -1) length = offset + clength; + if (length != -1 && size != -1 && length != size) { http_seterr(HTTP_PROTOCOL_ERROR); goto ouch; @@ -1149,12 +1156,6 @@ http_request(struct url *URL, const char *op, struct url_stat *us, if (size == -1) size = length; - /* fill in stats */ - if (us) { - us->size = size; - us->atime = us->mtime = mtime; - } - /* too far? */ if (URL->offset > 0 && offset > URL->offset) { http_seterr(HTTP_PROTOCOL_ERROR);