[pacman-dev] [PATCH] dload: avoid showing progress bars on some redirects

Dave Reisner dreisner at archlinux.org
Tue Jan 15 21:10:04 EST 2013


RFC 2616 doesn't forbid a 301 or 302 repsonse from having a body, and
servers exist in the wild that show this behavior. In order to prevent
pacman from showing a progress bar when we aren't actually downloading a
package (and merely following one of these pain in the butt redirects),
capture the server response code in the response header, rather than
waiting to peel it off the handle after the download has finished.

Signed-off-by: Dave Reisner <dreisner at archlinux.org>
Reported-by: Alexandre Filgueira <alexfilgueira at cinnarch.com>
---
 lib/libalpm/dload.c | 21 ++++++++++++++++-----
 lib/libalpm/dload.h |  1 +
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index ee19adb..83d2051 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -96,6 +96,11 @@ static int dload_progress_cb(void *file, double dltotal, double dlnow,
 	struct dload_payload *payload = (struct dload_payload *)file;
 	off_t current_size, total_size;
 
+	/* avoid displaying progress bar for redirects with a body */
+	if(payload->respcode >= 300) {
+		return 0;
+	}
+
 	/* SIGINT sent, abort by alerting curl */
 	if(dload_interrupted) {
 		return 1;
@@ -199,6 +204,7 @@ static size_t dload_parseheader_cb(void *ptr, size_t size, size_t nmemb, void *u
 	const char * const cd_header = "Content-Disposition:";
 	const char * const fn_key = "filename=";
 	struct dload_payload *payload = (struct dload_payload *)user;
+	long respcode;
 
 	if(_alpm_raw_ncmp(cd_header, ptr, strlen(cd_header)) == 0) {
 		if((fptr = strstr(ptr, fn_key))) {
@@ -220,6 +226,11 @@ static size_t dload_parseheader_cb(void *ptr, size_t size, size_t nmemb, void *u
 		}
 	}
 
+	curl_easy_getinfo(payload->handle->curl, CURLINFO_RESPONSE_CODE, &respcode);
+	if(payload->respcode != respcode) {
+		payload->respcode = respcode;
+	}
+
 	return realsize;
 }
 
@@ -383,7 +394,7 @@ static int curl_download_internal(struct dload_payload *payload,
 	char hostname[HOSTNAME_SIZE];
 	char error_buffer[CURL_ERROR_SIZE] = {0};
 	struct stat st;
-	long timecond, respcode = 0, remote_time = -1;
+	long timecond, remote_time = -1;
 	double remote_size, bytes_dl;
 	struct sigaction orig_sig_pipe, orig_sig_int;
 	/* shortcut to our handle within the payload */
@@ -463,13 +474,12 @@ static int curl_download_internal(struct dload_payload *payload,
 	switch(payload->curlerr) {
 		case CURLE_OK:
 			/* get http/ftp response code */
-			curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respcode);
-			_alpm_log(handle, ALPM_LOG_DEBUG, "response code: %ld\n", respcode);
-			if(respcode >= 400) {
+			_alpm_log(handle, ALPM_LOG_DEBUG, "response code: %ld\n", payload->respcode);
+			if(payload->respcode >= 400) {
 				payload->unlink_on_fail = 1;
 				/* non-translated message is same as libcurl */
 				snprintf(error_buffer, sizeof(error_buffer),
-						"The requested URL returned error: %ld", respcode);
+						"The requested URL returned error: %ld", payload->respcode);
 				_alpm_log(handle, ALPM_LOG_ERROR,
 						_("failed retrieving file '%s' from %s : %s\n"),
 						payload->remote_name, hostname, error_buffer);
@@ -725,6 +735,7 @@ void _alpm_dload_payload_reset(struct dload_payload *payload)
 	FREE(payload->destfile_name);
 	FREE(payload->content_disp_name);
 	FREE(payload->fileurl);
+	memset(payload, '\0', sizeof(*payload));
 }
 
 /* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index ca17200..70e3479 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -42,6 +42,7 @@ struct dload_payload {
 #ifdef HAVE_LIBCURL
 	CURLcode curlerr;       /* last error produced by curl */
 #endif
+	long respcode;
 };
 
 void _alpm_dload_payload_reset(struct dload_payload *payload);
-- 
1.8.1.1



More information about the pacman-dev mailing list