diff options
Diffstat (limited to 'src/pacsync.c')
-rw-r--r-- | src/pacsync.c | 165 |
1 files changed, 121 insertions, 44 deletions
diff --git a/src/pacsync.c b/src/pacsync.c index 342f6c9c..bb1ad2ac 100644 --- a/src/pacsync.c +++ b/src/pacsync.c @@ -57,57 +57,111 @@ extern unsigned short pmo_nopassiveftp; extern PMList *pmc_syncs; extern int maxcols; +/* + * Download fresh package lists for each repository + * + */ int sync_synctree() { - char ldir[PATH_MAX] = ""; char path[PATH_MAX]; + char ldir[PATH_MAX] = ""; mode_t oldmask; PMList *files = NULL; PMList *i; - int success = 0; + int success = 0, ret; for(i = pmc_syncs; i; i = i->next) { - sync_t *sync = (sync_t*)i->data; + char *mtime = NULL; + char newmtime[16] = ""; + char lastupdate[16] = ""; + sync_t *sync = (sync_t*)i->data; snprintf(ldir, PATH_MAX, "%s%s", pmo_root, pmo_dbpath); + /* get the lastupdate time */ + snprintf(path, PATH_MAX, "%s/%s", ldir, sync->treename); + if(db_getlastupdate(path, lastupdate)) { + vprint("failed to get lastupdate time for %s (no big deal)\n", sync->treename); + } else { + mtime = lastupdate; + } + /* build a one-element list */ snprintf(path, PATH_MAX, "%s.db.tar.gz", sync->treename); files = list_add(files, strdup(path)); success = 1; - if(downloadfiles(sync->servers, ldir, files)) { + ret = downloadfiles_forreal(sync->servers, ldir, files, mtime, newmtime); + vprint("pacsync: new mtime for %s: %s\n", sync->treename, newmtime); + FREELIST(files); + if(ret > 0) { fprintf(stderr, "failed to synchronize %s\n", sync->treename); success = 0; - } - FREELIST(files); - snprintf(path, PATH_MAX, "%s/%s.db.tar.gz", ldir, sync->treename); - - if(success) { - snprintf(ldir, PATH_MAX, "%s%s/%s", pmo_root, pmo_dbpath, sync->treename); - /* remove the old dir */ - vprint("removing %s (if it exists)\n", ldir); - rmrf(ldir); - - /* make the new dir */ - oldmask = umask(0000); - mkdir(ldir, 0755); - umask(oldmask); - - /* uncompress the sync database */ - vprint("Unpacking %s...\n", path); - if(unpack(path, ldir, NULL)) { - return(1); + } else if(ret < 0) { + printf(":: %s is up to date\n", sync->treename); + } else { + snprintf(path, PATH_MAX, "%s/%s.db.tar.gz", ldir, sync->treename); + + if(success) { + snprintf(ldir, PATH_MAX, "%s%s/%s", pmo_root, pmo_dbpath, sync->treename); + /* remove the old dir */ + vprint("removing %s (if it exists)\n", ldir); + rmrf(ldir); + + /* make the new dir */ + oldmask = umask(0000); + mkdir(ldir, 0755); + umask(oldmask); + + /* uncompress the sync database */ + vprint("unpacking %s...\n", path); + if(unpack(path, ldir, NULL)) { + return(1); + } + + if(strlen(newmtime)) { + db_setlastupdate(ldir, newmtime); + } } + /* remove the .tar.gz */ + unlink(path); } - /* remove the .tar.gz */ - unlink(path); } return(!success); } +/* + * 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(PMList *servers, const char *localpath, PMList *files) { + return(!!downloadfiles_forreal(servers, localpath, files, NULL, NULL)); +} + + +/* + * This is the real downloadfiles, used directly by sync_synctree() to check + * modtimes on remote (ftp only) 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 FTP file (from MDTM). + * + * NOTE: the *mtime option only works for FTP repositories, and won't work + * if XferCommand is used. We only use it to check mtimes on the + * repo db files. + * + * RETURN: 0 for successful download + * -1 if the mtimes are identical + * 1 on error + */ +int downloadfiles_forreal(PMList *servers, const char *localpath, + PMList *files, const char *mtime1, char *mtime2) +{ int fsz; netbuf *control = NULL; PMList *lp; @@ -125,7 +179,7 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) if(!pmo_xfercommand && strcmp(server->protocol, "file")) { if(!strcmp(server->protocol, "ftp") && !pmo_proxyhost) { FtpInit(); - vprint("Connecting to %s:21\n", server->server); + vprint("connecting to %s:21\n", server->server); if(!FtpConnect(server->server, &control)) { fprintf(stderr, "error: cannot connect to %s\n", server->server); continue; @@ -153,9 +207,9 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) host = (pmo_proxyhost) ? pmo_proxyhost : server->server; port = (pmo_proxyhost) ? pmo_proxyport : 80; if(strchr(host, ':')) { - vprint("Connecting to %s\n", host); + vprint("connecting to %s\n", host); } else { - vprint("Connecting to %s:%u\n", host, port); + vprint("connecting to %s:%u\n", host, port); } if(!HttpConnect(host, port, &control)) { fprintf(stderr, "error: cannot connect to %s\n", host); @@ -275,21 +329,42 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) if(!FtpSize(fn, &fsz, FTPLIB_IMAGE, control)) { fprintf(stderr, "warning: failed to get filesize for %s\n", fn); } - if(!stat(output, &st)) { - offset = (int)st.st_size; - if(!FtpRestart(offset, control)) { - fprintf(stderr, "warning: failed to resume download -- restarting\n"); - /* can't resume: */ - /* unlink the file in order to restart download from scratch */ - unlink(output); + /* check mtimes */ + if(mtime1 || mtime2) { + char fmtime[64]; + if(!FtpModDate(fn, fmtime, sizeof(fmtime)-1, control)) { + fprintf(stderr, "warning: failed to get mtime for %s\n", fn); + } else { + trim(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); + } + if(mtime2) { + strncpy(mtime2, fmtime, 15); /* YYYYMMDDHHMMSS (=14b) */ + mtime2[14] = '\0'; + } } } - if(!FtpGet(output, fn, FTPLIB_IMAGE, control)) { - fprintf(stderr, "\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; + if(!filedone) { + if(!stat(output, &st)) { + offset = (int)st.st_size; + if(!FtpRestart(offset, control)) { + fprintf(stderr, "warning: 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)) { + fprintf(stderr, "\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") || (pmo_proxyhost && strcmp(server->protocol, "file"))) { char src[PATH_MAX]; @@ -302,9 +377,9 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) host = (pmo_proxyhost) ? pmo_proxyhost : server->server; port = (pmo_proxyhost) ? pmo_proxyport : 80; if(strchr(host, ':')) { - vprint("Connecting to %s\n", host); + vprint("connecting to %s\n", host); } else { - vprint("Connecting to %s:%u\n", host, port); + vprint("connecting to %s:%u\n", host, port); } if(!HttpConnect(host, port, &control)) { fprintf(stderr, "error: cannot connect to %s\n", host); @@ -346,7 +421,7 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) } } - if(filedone) { + if(filedone > 0) { char completefile[PATH_MAX]; if(!strcmp(server->protocol, "file")) { char out[56]; @@ -364,6 +439,8 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) /* 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); |