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.
This commit is contained in:
parent
bb5bfc37b3
commit
791e683e01
@ -173,6 +173,9 @@ xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri, const char *filen
|
|||||||
if (fetchLastErrCode == FETCH_UNCHANGED) {
|
if (fetchLastErrCode == FETCH_UNCHANGED) {
|
||||||
/* Last-Modified matched */
|
/* Last-Modified matched */
|
||||||
goto fetch_file_out;
|
goto fetch_file_out;
|
||||||
|
} else if (fetchLastErrCode == FETCH_PROTO && url_st.size == stp->st_size) {
|
||||||
|
/* 413, requested offset == length */
|
||||||
|
goto rename_file;
|
||||||
}
|
}
|
||||||
rv = -1;
|
rv = -1;
|
||||||
goto fetch_file_out;
|
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,
|
xbps_set_cb_fetch(xhp, url_st.size, url->offset, bytes_dload,
|
||||||
filename, false, false, true);
|
filename, false, false, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update mtime in local file to match remote file if transfer
|
* Update mtime in local file to match remote file if transfer
|
||||||
* was successful.
|
* was successful.
|
||||||
@ -271,6 +275,7 @@ xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri, const char *filen
|
|||||||
(void)close(fd);
|
(void)close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
|
rename_file:
|
||||||
/* File downloaded successfully, rename to destfile */
|
/* File downloaded successfully, rename to destfile */
|
||||||
if (rename(tempfile, filename) == -1) {
|
if (rename(tempfile, filename) == -1) {
|
||||||
xbps_dbg_printf(xhp, "failed to rename %s to %s: %s",
|
xbps_dbg_printf(xhp, "failed to rename %s to %s: %s",
|
||||||
|
@ -1133,6 +1133,12 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
|
|||||||
goto ouch;
|
goto ouch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fill in stats */
|
||||||
|
if (us) {
|
||||||
|
us->size = size;
|
||||||
|
us->atime = us->mtime = mtime;
|
||||||
|
}
|
||||||
|
|
||||||
/* check for inconsistencies */
|
/* check for inconsistencies */
|
||||||
if (clength != -1 && length != -1 && clength != length) {
|
if (clength != -1 && length != -1 && clength != length) {
|
||||||
http_seterr(HTTP_PROTOCOL_ERROR);
|
http_seterr(HTTP_PROTOCOL_ERROR);
|
||||||
@ -1142,6 +1148,7 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
|
|||||||
clength = length;
|
clength = length;
|
||||||
if (clength != -1)
|
if (clength != -1)
|
||||||
length = offset + clength;
|
length = offset + clength;
|
||||||
|
|
||||||
if (length != -1 && size != -1 && length != size) {
|
if (length != -1 && size != -1 && length != size) {
|
||||||
http_seterr(HTTP_PROTOCOL_ERROR);
|
http_seterr(HTTP_PROTOCOL_ERROR);
|
||||||
goto ouch;
|
goto ouch;
|
||||||
@ -1149,12 +1156,6 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
|
|||||||
if (size == -1)
|
if (size == -1)
|
||||||
size = length;
|
size = length;
|
||||||
|
|
||||||
/* fill in stats */
|
|
||||||
if (us) {
|
|
||||||
us->size = size;
|
|
||||||
us->atime = us->mtime = mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* too far? */
|
/* too far? */
|
||||||
if (URL->offset > 0 && offset > URL->offset) {
|
if (URL->offset > 0 && offset > URL->offset) {
|
||||||
http_seterr(HTTP_PROTOCOL_ERROR);
|
http_seterr(HTTP_PROTOCOL_ERROR);
|
||||||
|
Loading…
Reference in New Issue
Block a user