summaryrefslogtreecommitdiffstats
path: root/src/pacsync.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacsync.c')
-rw-r--r--src/pacsync.c165
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);