summaryrefslogtreecommitdiff
path: root/src/pacman/download.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman/download.c')
-rw-r--r--src/pacman/download.c483
1 files changed, 22 insertions, 461 deletions
diff --git a/src/pacman/download.c b/src/pacman/download.c
index b59aeada..63d2ccbf 100644
--- a/src/pacman/download.c
+++ b/src/pacman/download.c
@@ -40,35 +40,42 @@
#include "conf.h"
/* progress bar */
-static char sync_fnm[25];
-static int offset;
-static struct timeval t0, t;
-static float rate;
-static int xfered1;
-static unsigned char eta_h, eta_m, eta_s;
+char sync_fnm[25];
+int offset;
+struct timeval t0, t;
+float rate;
+int xfered1;
+unsigned char eta_h, eta_m, eta_s;
/* pacman options */
extern config_t *config;
-extern int maxcols;
+extern unsigned int maxcols;
-static int log_progress(netbuf *ctl, int xfered, void *arg)
+int log_progress(netbuf *ctl, int xfered, void *arg)
{
int fsz = *(int*)arg;
int pct = ((float)(xfered+offset) / fsz) * 100;
- int i, cur;
+ static int lastpct=0;
+ unsigned int i, cur;
struct timeval t1;
float timediff;
/* a little hard to conceal easter eggs in open-source software, but
* they're still fun. ;)
*/
+ int chomp;
static unsigned short mouth;
static unsigned int lastcur = 0;
- if(config->noprogressbar) {
+ /* we don't need that parameter */
+ ctl=NULL;
+
+ if(config->noprogressbar || (pct == 100 && lastpct == 100)) {
return(1);
}
+ alpm_get_option(PM_OPT_CHOMP, (long *)&chomp);
+
gettimeofday(&t1, NULL);
if(xfered+offset == fsz) {
t = t0;
@@ -100,7 +107,7 @@ static int log_progress(netbuf *ctl, int xfered, void *arg)
printf(" %s [", sync_fnm);
cur = (int)((maxcols-64)*pct/100);
for(i = 0; i < maxcols-64; i++) {
- if(config->chomp) {
+ if(chomp) {
if(i < cur) {
printf("-");
} else {
@@ -132,459 +139,13 @@ static int log_progress(netbuf *ctl, int xfered, void *arg)
} else {
printf("] %3d%% %6dK %6.1fK/s %02d:%02d:%02d\r", pct, ((xfered+offset) / 1024), rate, eta_h, eta_m, eta_s);
}
+ if(lastpct != 100 && pct == 100) {
+ printf("\n");
+ }
lastcur = cur;
+ lastpct = pct;
fflush(stdout);
return(1);
}
-static int copyfile(char *src, char *dest)
-{
- FILE *in, *out;
- size_t len;
- char buf[4097];
-
- in = fopen(src, "r");
- if(in == NULL) {
- return(1);
- }
- out = fopen(dest, "w");
- if(out == NULL) {
- return(1);
- }
-
- while((len = fread(buf, 1, 4096, in))) {
- fwrite(buf, 1, len, out);
- }
-
- fclose(in);
- fclose(out);
- return(0);
-}
-
-/*
- * Download a list of files from a list of servers
- * - if one server fails, we try the next one in the list
- *
- * RETURN: 0 for successful download, 1 on error
- */
-int downloadfiles(list_t *servers, const char *localpath, list_t *files)
-{
- return(!!downloadfiles_forreal(servers, localpath, files, NULL, NULL));
-}
-
-/*
- * This is the real downloadfiles, used directly by sync_synctree() to check
- * modtimes on remote files.
- * - if *mtime1 is non-NULL, then only download files
- * if they are different than *mtime1. String should be in the form
- * "YYYYMMDDHHMMSS" to match the form of ftplib's FtpModDate() function.
- * - if *mtime2 is non-NULL, then it will be filled with the mtime
- * of the remote file (from MDTM FTP cmd or Last-Modified HTTP header).
- *
- * RETURN: 0 for successful download
- * -1 if the mtimes are identical
- * 1 on error
- */
-int downloadfiles_forreal(list_t *servers, const char *localpath,
- list_t *files, const char *mtime1, char *mtime2)
-{
- int fsz;
- netbuf *control = NULL;
- list_t *lp;
- int done = 0;
- list_t *complete = NULL;
- list_t *i;
-
- if(files == NULL) {
- return(0);
- }
-
- for(i = servers; i && !done; i = i->next) {
- server_t *server = (server_t*)i->data;
-
- if(!config->xfercommand && strcmp(server->protocol, "file")) {
- if(!strcmp(server->protocol, "ftp") && !config->proxyhost) {
- FtpInit();
- vprint(_("connecting to %s:21\n"), server->server);
- if(!FtpConnect(server->server, &control)) {
- ERR(NL, _("cannot connect to %s\n"), server->server);
- continue;
- }
- if(!FtpLogin("anonymous", "arch@guest", control)) {
- ERR(NL, _("anonymous login failed\n"));
- FtpQuit(control);
- continue;
- }
- if(!FtpChdir(server->path, control)) {
- ERR(NL, _("could not cwd to %s: %s\n"), server->path, FtpLastResponse(control));
- FtpQuit(control);
- continue;
- }
- if(!config->nopassiveftp) {
- if(!FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, control)) {
- WARN(NL, _("failed to set passive mode\n"));
- }
- } else {
- vprint(_("FTP passive mode not set\n"));
- }
- } else if(config->proxyhost) {
- char *host;
- unsigned port;
- host = (config->proxyhost) ? config->proxyhost : server->server;
- port = (config->proxyport) ? config->proxyport : 80;
- if(strchr(host, ':')) {
- vprint(_("connecting to %s\n"), host);
- } else {
- vprint(_("connecting to %s:%u\n"), host, port);
- }
- if(!HttpConnect(host, port, &control)) {
- ERR(NL, _("cannot connect to %s\n"), host);
- continue;
- }
- }
-
- /* set up our progress bar's callback (and idle timeout) */
- if(strcmp(server->protocol, "file") && control) {
- FtpOptions(FTPLIB_CALLBACK, (long)log_progress, control);
- FtpOptions(FTPLIB_IDLETIME, (long)1000, control);
- FtpOptions(FTPLIB_CALLBACKARG, (long)&fsz, control);
- FtpOptions(FTPLIB_CALLBACKBYTES, (10*1024), control);
- }
- }
-
- /* get each file in the list */
- for(lp = files; lp; lp = lp->next) {
- char *fn = (char *)lp->data;
-
- if(list_is_strin(fn, complete)) {
- continue;
- }
-
- if(config->xfercommand && strcmp(server->protocol, "file")) {
- int ret;
- int usepart = 0;
- char *ptr1, *ptr2;
- char origCmd[PATH_MAX];
- char parsedCmd[PATH_MAX] = "";
- char url[PATH_MAX];
- char cwd[PATH_MAX];
- /* build the full download url */
- snprintf(url, PATH_MAX, "%s://%s%s%s", server->protocol, server->server,
- server->path, fn);
- /* replace all occurrences of %o with fn.part */
- strncpy(origCmd, config->xfercommand, sizeof(origCmd));
- ptr1 = origCmd;
- while((ptr2 = strstr(ptr1, "%o"))) {
- usepart = 1;
- ptr2[0] = '\0';
- strcat(parsedCmd, ptr1);
- strcat(parsedCmd, fn);
- strcat(parsedCmd, ".part");
- ptr1 = ptr2 + 2;
- }
- strcat(parsedCmd, ptr1);
- /* replace all occurrences of %u with the download URL */
- strncpy(origCmd, parsedCmd, sizeof(origCmd));
- parsedCmd[0] = '\0';
- ptr1 = origCmd;
- while((ptr2 = strstr(ptr1, "%u"))) {
- ptr2[0] = '\0';
- strcat(parsedCmd, ptr1);
- strcat(parsedCmd, url);
- ptr1 = ptr2 + 2;
- }
- strcat(parsedCmd, ptr1);
- /* cwd to the download directory */
- getcwd(cwd, PATH_MAX);
- if(chdir(localpath)) {
- ERR(NL, _("could not chdir to %s\n"), localpath);
- return(1);
- }
- /* execute the parsed command via /bin/sh -c */
- vprint(_("running command: %s\n"), parsedCmd);
- ret = system(parsedCmd);
- if(ret == -1) {
- ERR(NL, _("running XferCommand: fork failed!\n"));
- return(1);
- } else if(ret != 0) {
- /* download failed */
- vprint(_("XferCommand command returned non-zero status code (%d)\n"), ret);
- } else {
- /* download was successful */
- complete = list_add(complete, fn);
- if(usepart) {
- char fnpart[PATH_MAX];
- /* rename "output.part" file to "output" file */
- snprintf(fnpart, PATH_MAX, "%s.part", fn);
- rename(fnpart, fn);
- }
- }
- chdir(cwd);
- } else {
- char output[PATH_MAX];
- int j, filedone = 0;
- char *ptr;
- struct stat st;
- snprintf(output, PATH_MAX, "%s/%s.part", localpath, fn);
- strncpy(sync_fnm, fn, 24);
- /* drop filename extension */
- ptr = strstr(fn, PM_EXT_DB);
- if(ptr && (ptr-fn) < 24) {
- sync_fnm[ptr-fn] = '\0';
- }
- ptr = strstr(fn, PM_EXT_PKG);
- if(ptr && (ptr-fn) < 24) {
- sync_fnm[ptr-fn] = '\0';
- }
- for(j = strlen(sync_fnm); j < 24; j++) {
- sync_fnm[j] = ' ';
- }
- sync_fnm[24] = '\0';
- offset = 0;
-
- /* ETA setup */
- gettimeofday(&t0, NULL);
- t = t0;
- rate = 0;
- xfered1 = 0;
- eta_h = 0;
- eta_m = 0;
- eta_s = 0;
-
- if(!strcmp(server->protocol, "ftp") && !config->proxyhost) {
- if(!FtpSize(fn, &fsz, FTPLIB_IMAGE, control)) {
- WARN(NL, _("failed to get filesize for %s\n"), fn);
- }
- /* check mtimes */
- if(mtime1) {
- char fmtime[64];
- if(!FtpModDate(fn, fmtime, sizeof(fmtime)-1, control)) {
- WARN(NL, _("failed to get mtime for %s\n"), fn);
- } else {
- strtrim(fmtime);
- if(mtime1 && !strcmp(mtime1, fmtime)) {
- /* mtimes are identical, skip this file */
- vprint(_("mtimes are identical, skipping %s\n"), fn);
- filedone = -1;
- complete = list_add(complete, fn);
- } else {
- if(mtime2) {
- strncpy(mtime2, fmtime, 15); /* YYYYMMDDHHMMSS (=14b) */
- mtime2[14] = '\0';
- }
- }
- }
- }
- if(!filedone) {
- if(!stat(output, &st)) {
- offset = (int)st.st_size;
- if(!FtpRestart(offset, control)) {
- WARN(NL, _("failed to resume download -- restarting\n"));
- /* can't resume: */
- /* unlink the file in order to restart download from scratch */
- unlink(output);
- }
- }
- if(!FtpGet(output, fn, FTPLIB_IMAGE, control)) {
- ERR(NL, _("\nfailed downloading %s from %s: %s\n"), fn, server->server, FtpLastResponse(control));
- /* we leave the partially downloaded file in place so it can be resumed later */
- } else {
- filedone = 1;
- }
- }
- } else if(!strcmp(server->protocol, "http") || (config->proxyhost && strcmp(server->protocol, "file"))) {
- char src[PATH_MAX];
- char *host;
- unsigned port;
- struct tm fmtime1;
- struct tm fmtime2;
- memset(&fmtime1, 0, sizeof(struct tm));
- memset(&fmtime2, 0, sizeof(struct tm));
- if(!strcmp(server->protocol, "http") && !config->proxyhost) {
- /* HTTP servers hang up after each request (but not proxies), so
- * we have to re-connect for each file.
- */
- host = (config->proxyhost) ? config->proxyhost : server->server;
- port = (config->proxyhost) ? config->proxyport : 80;
- if(strchr(host, ':')) {
- vprint(_("connecting to %s\n"), host);
- } else {
- vprint(_("connecting to %s:%u\n"), host, port);
- }
- if(!HttpConnect(host, port, &control)) {
- ERR(NL, _("cannot connect to %s\n"), host);
- continue;
- }
- /* set up our progress bar's callback (and idle timeout) */
- if(strcmp(server->protocol, "file") && control) {
- FtpOptions(FTPLIB_CALLBACK, (long)log_progress, control);
- FtpOptions(FTPLIB_IDLETIME, (long)1000, control);
- FtpOptions(FTPLIB_CALLBACKARG, (long)&fsz, control);
- FtpOptions(FTPLIB_CALLBACKBYTES, (10*1024), control);
- }
- }
-
- if(!stat(output, &st)) {
- offset = (int)st.st_size;
- }
- if(!config->proxyhost) {
- snprintf(src, PATH_MAX, "%s%s", server->path, fn);
- } else {
- snprintf(src, PATH_MAX, "%s://%s%s%s", server->protocol, server->server, server->path, fn);
- }
- if(mtime1 && strlen(mtime1)) {
- struct tm tmref;
- time_t t, tref;
- int diff;
- /* date conversion from YYYYMMDDHHMMSS to "rfc1123-date" */
- sscanf(mtime1, "%4d%2d%2d%2d%2d%2d",
- &fmtime1.tm_year, &fmtime1.tm_mon, &fmtime1.tm_mday,
- &fmtime1.tm_hour, &fmtime1.tm_min, &fmtime1.tm_sec);
- fmtime1.tm_year -= 1900;
- fmtime1.tm_mon--;
- /* compute the week day because some web servers (like lighttpd) need them. */
- /* we set tmref to "Thu, 01 Jan 1970 00:00:00" */
- memset(&tmref, 0, sizeof(struct tm));
- tmref.tm_mday = 1;
- tref = mktime(&tmref);
- /* then we compute the difference with mtime1 */
- t = mktime(&fmtime1);
- diff = ((t-tref)/3600/24)%7;
- fmtime1.tm_wday = diff+(diff >= 3 ? -3 : 4);
-
- }
- fmtime2.tm_year = 0;
- if(!HttpGet(server->server, output, src, &fsz, control, offset,
- (mtime1) ? &fmtime1 : NULL, (mtime2) ? &fmtime2 : NULL)) {
- if(strstr(FtpLastResponse(control), "304")) {
- vprint(_("mtimes are identical, skipping %s\n"), fn);
- filedone = -1;
- complete = list_add(complete, fn);
- } else {
- ERR(NL, _("\nfailed downloading %s from %s: %s\n"), src, server->server, FtpLastResponse(control));
- /* we leave the partially downloaded file in place so it can be resumed later */
- }
- } else {
- if(mtime2) {
- if(fmtime2.tm_year) {
- /* date conversion from "rfc1123-date" to YYYYMMDDHHMMSS */
- sprintf(mtime2, "%4d%02d%02d%02d%02d%02d",
- fmtime2.tm_year+1900, fmtime2.tm_mon+1, fmtime2.tm_mday,
- fmtime2.tm_hour, fmtime2.tm_min, fmtime2.tm_sec);
- } else {
- WARN(NL, _("failed to get mtime for %s\n"), fn);
- }
- }
- filedone = 1;
- }
- } else if(!strcmp(server->protocol, "file")) {
- char src[PATH_MAX];
- snprintf(src, PATH_MAX, "%s%s", server->path, fn);
- vprint(_("copying %s to %s/%s\n"), src, localpath, fn);
- /* local repository, just copy the file */
- if(copyfile(src, output)) {
- ERR(NL, _("failed copying %s\n"), src);
- } else {
- filedone = 1;
- }
- }
-
- if(filedone > 0) {
- char completefile[PATH_MAX];
- if(!strcmp(server->protocol, "file")) {
- char out[56];
- printf(" %s [", sync_fnm);
- STRNCPY(out, server->path, 33);
- printf("%s", out);
- for(j = strlen(out); j < maxcols-64; j++) {
- printf(" ");
- }
- fputs(_("] 100% LOCAL "), stdout);
- } else {
- log_progress(control, fsz-offset, &fsz);
- }
- complete = list_add(complete, fn);
- /* rename "output.part" file to "output" file */
- snprintf(completefile, PATH_MAX, "%s/%s", localpath, fn);
- rename(output, completefile);
- } else if(filedone < 0) {
- return(-1);
- }
- printf("\n");
- fflush(stdout);
- }
- }
- if(!config->xfercommand) {
- if(!strcmp(server->protocol, "ftp") && !config->proxyhost) {
- FtpQuit(control);
- } else if(!strcmp(server->protocol, "http") || (config->proxyhost && strcmp(server->protocol, "file"))) {
- HttpQuit(control);
- }
- }
-
- if(list_count(complete) == list_count(files)) {
- done = 1;
- }
- }
-
- return(!done);
-}
-
-char *fetch_pkgurl(char *target)
-{
- char spath[PATH_MAX];
- char url[PATH_MAX];
- char *host, *path, *fn;
- struct stat buf;
-
- strncpy(url, target, PATH_MAX);
- host = strstr(url, "://");
- *host = '\0';
- host += 3;
- path = strchr(host, '/');
- *path = '\0';
- path++;
- fn = strrchr(path, '/');
- if(fn) {
- *fn = '\0';
- if(path[0] == '/') {
- snprintf(spath, PATH_MAX, "%s/", path);
- } else {
- snprintf(spath, PATH_MAX, "/%s/", path);
- }
- fn++;
- } else {
- fn = path;
- strcpy(spath, "/");
- }
-
- /* do not download the file if it exists in the current dir
- */
- if(stat(fn, &buf) == 0) {
- vprint(_(" %s is already in the current directory\n"), fn);
- } else {
- server_t *server;
- list_t *servers = NULL;
- list_t *files;
-
- MALLOC(server, sizeof(server_t));
- server->protocol = url;
- server->server = host;
- server->path = spath;
- servers = list_add(servers, server);
-
- files = list_add(NULL, fn);
- if(downloadfiles(servers, ".", files)) {
- ERR(NL, _("failed to download %s\n"), target);
- return(NULL);
- }
- FREELISTPTR(files);
-
- FREELIST(servers);
- }
-
- /* return the target with the raw filename, no URL */
- return(strndup(fn, PATH_MAX));
-}
-
/* vim: set ts=2 sw=2 noet: */