index : pacman | |
Archlinux32 fork of pacman | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | lib/libalpm/dload.c | 68 |
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index ca13652e..5b0a691f 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -24,6 +24,7 @@ #include <errno.h> #include <string.h> #include <unistd.h> +#include <signal.h> #include <limits.h> /* the following two are needed on BSD for libfetch */ #if defined(HAVE_SYS_SYSLIMITS_H) @@ -33,16 +34,8 @@ #include <sys/param.h> /* MAXHOSTNAMELEN */ #endif -#if defined(HAVE_LIBDOWNLOAD) -#include <download.h> -#elif defined(HAVE_LIBFETCH) +#if defined(INTERNAL_DOWNLOAD) #include <fetch.h> -#define downloadFreeURL fetchFreeURL -#define downloadLastErrCode fetchLastErrCode -#define downloadLastErrString fetchLastErrString -#define downloadParseURL fetchParseURL -#define downloadTimeout fetchTimeout -#define downloadXGet fetchXGet #endif /* libalpm */ @@ -86,7 +79,7 @@ static char *get_tempfile(const char *path, const char *filename) { static struct url *url_for_string(const char *url) { struct url *ret = NULL; - ret = downloadParseURL(url); + ret = fetchParseURL(url); if(!ret) { _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); RET_ERR(PM_ERR_SERVER_BAD_URL, NULL); @@ -108,12 +101,14 @@ static struct url *url_for_string(const char *url) static int download_internal(const char *url, const char *localpath, time_t mtimeold, time_t *mtimenew) { - FILE *dlf, *localf = NULL; + fetchIO *dlf = NULL; + FILE *localf = NULL; struct url_stat ust; struct stat st; int chk_resume = 0, ret = 0; size_t dl_thisfile = 0, nread = 0; char *tempfile, *destfile, *filename; + struct sigaction new_action, old_action; struct url *fileurl = url_for_string(url); char buffer[PM_DLBUF_LEN]; @@ -148,23 +143,29 @@ static int download_internal(const char *url, const char *localpath, _alpm_log(PM_LOG_DEBUG, "FTP_PROXY: %s\n", getenv("FTP_PROXY")); _alpm_log(PM_LOG_DEBUG, "ftp_proxy: %s\n", getenv("ftp_proxy")); - /* libdownload does not reset the error code, reset it in - * the case of previous errors */ - downloadLastErrCode = 0; + /* libfetch does not reset the error code */ + fetchLastErrCode = 0; /* 10s timeout - TODO make a config option */ - downloadTimeout = 10000; + fetchTimeout = 10000; + + /* ignore any SIGPIPE signals- these may occur if our FTP socket dies or + * something along those lines. Store the old signal handler first. */ + new_action.sa_handler = SIG_IGN; + sigemptyset(&new_action.sa_mask); + sigaction(SIGPIPE, NULL, &old_action); + sigaction(SIGPIPE, &new_action, NULL); - dlf = downloadXGet(fileurl, &ust, (handle->nopassiveftp ? "" : "p")); + dlf = fetchXGet(fileurl, &ust, (handle->nopassiveftp ? "" : "p")); - if(downloadLastErrCode != 0 || dlf == NULL) { + if(fetchLastErrCode != 0 || dlf == NULL) { const char *host = _("disk"); if(strcmp(SCHEME_FILE, fileurl->scheme) != 0) { host = fileurl->host; } - pm_errno = PM_ERR_LIBDOWNLOAD; + pm_errno = PM_ERR_LIBFETCH; _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), - filename, host, downloadLastErrString); + filename, host, fetchLastErrString); ret = -1; goto cleanup; } else { @@ -206,16 +207,8 @@ static int download_internal(const char *url, const char *localpath, handle->dlcb(filename, 0, ust.size); } - while((nread = fread(buffer, 1, PM_DLBUF_LEN, dlf)) > 0) { + while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) { size_t nwritten = 0; - if(ferror(dlf)) { - pm_errno = PM_ERR_LIBDOWNLOAD; - _alpm_log(PM_LOG_ERROR, _("error downloading '%s': %s\n"), - filename, downloadLastErrString); - ret = -1; - goto cleanup; - } - while(nwritten < nread) { nwritten += fwrite(buffer, 1, (nread - nwritten), localf); if(ferror(localf)) { @@ -231,27 +224,40 @@ static int download_internal(const char *url, const char *localpath, handle->dlcb(filename, dl_thisfile, ust.size); } } + + /* did the transfer complete normally? */ + if (ust.size != -1 && dl_thisfile < ust.size) { + pm_errno = PM_ERR_LIBFETCH; + _alpm_log(PM_LOG_ERROR, _("%s appears to be truncated: %jd/%jd bytes\n"), + filename, (intmax_t)dl_thisfile, (intmax_t)ust.size); + ret = -1; + goto cleanup; + } + /* probably safer to close the file descriptors now before renaming the file, * for example to make sure the buffers are flushed. */ fclose(localf); localf = NULL; - fclose(dlf); + fetchIO_close(dlf); dlf = NULL; rename(tempfile, destfile); ret = 0; cleanup: + /* restore any existing SIGPIPE signal handler */ + sigaction(SIGPIPE, &old_action, NULL); + FREE(tempfile); FREE(destfile); if(localf != NULL) { fclose(localf); } if(dlf != NULL) { - fclose(dlf); + fetchIO_close(dlf); } - downloadFreeURL(fileurl); + fetchFreeURL(fileurl); return(ret); } #endif |