From: Christian Hesse <[email protected]>

If the server redirects from ${repo}.db to ${repo}.db.tar.gz pacman gets
this wrong: It saves to new filename and fails when accessing
${repo}.db.

We need the remote filename only when downloading remote files with
pacman's -U operation. This introduces a new field 'trust_remote_name'
to payload. If set pacman downloads to the filename given by the server.

The field trust_remote_name is set in alpm_fetch_pkgurl().

Fixes FS#36791 ([pacman] downloads to wrong filename with redirect).
---
 lib/libalpm/dload.c | 40 +++++++++++++++++++++++-----------------
 lib/libalpm/dload.h |  1 +
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 8537b3d..c12f259 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -547,25 +547,29 @@ static int curl_download_internal(struct dload_payload 
*payload,
                goto cleanup;
        }
 
-       if(payload->content_disp_name) {
-               /* content-disposition header has a better name for our file */
-               free(payload->destfile_name);
-               payload->destfile_name = get_fullpath(localpath, 
payload->content_disp_name, "");
-       } else {
-               const char *effective_filename = strrchr(effective_url, '/');
-               if(effective_filename && strlen(effective_filename) > 2) {
-                       effective_filename++;
-
-                       /* if destfile was never set, we wrote to a tempfile. 
even if destfile is
-                        * set, we may have followed some redirects and the 
effective url may
-                        * have a better suggestion as to what to name our 
file. in either case,
-                        * refactor destfile to this newly derived name. */
-                       if(!payload->destfile_name || strcmp(effective_filename,
-                                               strrchr(payload->destfile_name, 
'/') + 1) != 0) {
-                               free(payload->destfile_name);
-                               payload->destfile_name = 
get_fullpath(localpath, effective_filename, "");
+       if (payload->trust_remote_name) {
+               if(payload->content_disp_name) {
+                       /* content-disposition header has a better name for our 
file */
+                       free(payload->destfile_name);
+                       payload->destfile_name = get_fullpath(localpath, 
payload->content_disp_name, "");
+               } else {
+                       const char *effective_filename = strrchr(effective_url, 
'/');
+                       if(effective_filename && strlen(effective_filename) > 
2) {
+                               effective_filename++;
+
+                               /* if destfile was never set, we wrote to a 
tempfile. even if destfile is
+                                * set, we may have followed some redirects and 
the effective url may
+                                * have a better suggestion as to what to name 
our file. in either case,
+                                * refactor destfile to this newly derived 
name. */
+                               if(!payload->destfile_name || 
strcmp(effective_filename,
+                                                       
strrchr(payload->destfile_name, '/') + 1) != 0) {
+                                       free(payload->destfile_name);
+                                       payload->destfile_name = 
get_fullpath(localpath, effective_filename, "");
+                               }
                        }
                }
+       } else {
+               payload->destfile_name = get_fullpath(localpath, 
payload->remote_name, "");
        }
 
        ret = 0;
@@ -678,6 +682,7 @@ char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, 
const char *url)
                STRDUP(payload.fileurl, url, RET_ERR(handle, ALPM_ERR_MEMORY, 
NULL));
                payload.allow_resume = 1;
                payload.handle = handle;
+               payload.trust_remote_name = 1;
 
                /* download the file */
                ret = _alpm_download(&payload, cachedir, &final_file, 
&final_pkg_url);
@@ -702,6 +707,7 @@ char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, 
const char *url)
                sig_filepath = filecache_find_url(handle, payload.fileurl);
                if(sig_filepath == NULL) {
                        payload.handle = handle;
+                       payload.trust_remote_name = 1;
                        payload.force = 1;
                        payload.errors_ok = (handle->siglevel & 
ALPM_SIG_PACKAGE_OPTIONAL);
 
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index 95bb91a..6c9f7a7 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -38,6 +38,7 @@ struct dload_payload {
        int allow_resume;
        int errors_ok;
        int unlink_on_fail;
+       int trust_remote_name;
        alpm_list_t *servers;
 #ifdef HAVE_LIBCURL
        CURLcode curlerr;       /* last error produced by curl */
-- 
1.8.4


Reply via email to