summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan McRae <allan@archlinux.org>2019-11-15 14:29:20 +0100
committerAndrew Gregory <andrew@archlinux.org>2020-06-18 10:25:50 +0200
commit76c50e34393d68a740f825a6af9df8b7ac677303 (patch)
treea78dd7db47cf3662e0039ea735efe818a3c5420b
parentc2fa9f85cccc4b576816330762fb55167a1ba78c (diff)
downloadpacman-76c50e34393d68a740f825a6af9df8b7ac677303.tar.gz
pacman-76c50e34393d68a740f825a6af9df8b7ac677303.tar.xz
Handle .part files that are the size of the correct package
In rare cases, likely due to a well timed Ctrl+C, but possibly due to a broken mirror, a ".part" file may have size at least that of the correct package size. When encountering this issue, currently pacman fails in different ways depending on where the package falls in the list to download. If last, "wrong or NULL argument passed" error is reported, or a "invalid or corrupt package" issue if not. Capture these .part files, and remove the extension. This lets pacman either use the package if valid, or offer to remove it if it fails checksum or signature verification. Signed-off-by: Allan McRae <allan@archlinux.org> (cherry picked from commit e6a6d3079315ce722fec39604fddbab1c7ac79b3)
-rw-r--r--lib/libalpm/dload.c6
-rw-r--r--lib/libalpm/sync.c14
2 files changed, 18 insertions, 2 deletions
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index ddcc45f6..40a1d07d 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -414,6 +414,12 @@ static int curl_download_internal(struct dload_payload *payload,
curl_set_handle_opts(payload, curl, error_buffer);
+ if(payload->max_size == payload->initial_size) {
+ /* .part file is complete */
+ ret = 0;
+ goto cleanup;
+ }
+
if(localf == NULL) {
localf = fopen(payload->tempfile_name, payload->tempfile_openmode);
if(localf == NULL) {
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 70c37890..97a351fe 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -731,6 +731,8 @@ static int find_dl_candidates(alpm_db_t *repo, alpm_list_t **files)
alpm_pkg_t *spkg = i->data;
if(spkg->origin != ALPM_PKG_FROM_FILE && repo == spkg->origin_data.db) {
+ char *fpath = NULL;
+
if(!repo->servers) {
handle->pm_errno = ALPM_ERR_SERVER_NONE;
_alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n",
@@ -738,13 +740,21 @@ static int find_dl_candidates(alpm_db_t *repo, alpm_list_t **files)
return 1;
}
- if(spkg->download_size != 0) {
+ ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
+
+ if(spkg->download_size == 0) {
+ /* check for file in cache - allows us to handle complete .part files */
+ fpath = _alpm_filecache_find(handle, spkg->filename);
+ }
+
+ if(spkg->download_size != 0 || !fpath) {
struct dload_payload *payload;
- ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
payload = build_payload(handle, spkg->filename, spkg->size, repo->servers);
ASSERT(payload, return -1);
*files = alpm_list_add(*files, payload);
}
+
+ FREE(fpath);
}
}