Added support for .lastupdate files (from pacman 2.9.1)
This commit is contained in:
parent
18db4c168b
commit
72c2439576
|
@ -205,17 +205,31 @@ int alpm_db_unregister(PM_DB *db)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int alpm_db_update(char *treename, char *archive)
|
||||
int alpm_db_getlastupdate(PM_DB *db, char *ts)
|
||||
{
|
||||
/* Sanity checks */
|
||||
ASSERT(handle != NULL, return(-1));
|
||||
ASSERT(treename != NULL && strlen(treename) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
|
||||
ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
|
||||
ASSERT(db != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
|
||||
|
||||
return(db_getlastupdate(db, handle->root, handle->dbpath, ts));
|
||||
}
|
||||
|
||||
int alpm_db_update(PM_DB *db, char *archive, char *ts)
|
||||
{
|
||||
/* Sanity checks */
|
||||
ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
|
||||
ASSERT(db != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
|
||||
|
||||
/* ORE
|
||||
Does it make sense to update the 'local' database, or should we prevent it?
|
||||
stat(archive); */
|
||||
Does it make sense to update the 'local' database, or should we prevent it? */
|
||||
|
||||
return(db_update(handle->root, handle->dbpath, treename, archive));
|
||||
/* ORE
|
||||
check if the database is registered: if not, return an error */
|
||||
|
||||
/* ORE
|
||||
stat() the archive to check it exists */
|
||||
|
||||
return(db_update(db, handle->root, handle->dbpath, archive, ts));
|
||||
}
|
||||
|
||||
PM_PKG *alpm_db_readpkg(PM_DB *db, char *name)
|
||||
|
|
|
@ -98,7 +98,8 @@ int alpm_get_option(unsigned char parm, long *data);
|
|||
int alpm_db_register(char *treename, PM_DB **db);
|
||||
int alpm_db_unregister(PM_DB *db);
|
||||
|
||||
int alpm_db_update(char *treename, char *archive);
|
||||
int alpm_db_getlastupdate(PM_DB *db, char *ts);
|
||||
int alpm_db_update(PM_DB *db, char *archive, char *ts);
|
||||
|
||||
PM_PKG *alpm_db_readpkg(PM_DB *db, char *name);
|
||||
PM_LIST *alpm_db_getpkgcache(PM_DB *db);
|
||||
|
|
|
@ -97,34 +97,92 @@ int db_create(char *root, char *dbpath, char *treename)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int db_update(char *root, char *dbpath, char *treename, char *archive)
|
||||
/* reads dbpath/.lastupdate and populates *ts with the contents.
|
||||
* *ts should be malloc'ed and should be at least 15 bytes.
|
||||
*
|
||||
* Returns 0 on success, 1 on error
|
||||
*
|
||||
*/
|
||||
int db_getlastupdate(pmdb_t *db, char *root, char *dbpath, char *ts)
|
||||
{
|
||||
char ldir[PATH_MAX];
|
||||
FILE *fp;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if(db == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* get the last update time, if it's there */
|
||||
snprintf(path, PATH_MAX, "%s%s/%s/.lastupdate", root, dbpath, db->treename);
|
||||
if((fp = fopen(path, "r")) == NULL) {
|
||||
return(-1);
|
||||
} else {
|
||||
char line[256];
|
||||
if(fgets(line, sizeof(line), fp)) {
|
||||
strncpy(ts, line, 15); /* YYYYMMDDHHMMSS */
|
||||
ts[14] = '\0';
|
||||
} else {
|
||||
fclose(fp);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int db_update(pmdb_t *db, char *root, char *dbpath, char *archive, char *ts)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if(db == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
snprintf(path, PATH_MAX, "%s%s/%s", root, dbpath, db->treename);
|
||||
|
||||
/* ORE
|
||||
if(ts && strlen(ts)) {
|
||||
Should we refuse to update the db if it is already uptodate?
|
||||
if(ts != db_getlastupdate(db)) {
|
||||
RET_ERR(PM_ERR_DB_UPTODATE, -1);
|
||||
}
|
||||
}*/
|
||||
|
||||
snprintf(ldir, PATH_MAX, "%s%s/%s", root, dbpath, treename);
|
||||
/* remove the old dir */
|
||||
/* ORE - do we want to include alpm.h and use the log mechanism from db.c?
|
||||
_alpm_log(PM_LOG_FLOW2, "removing %s (if it exists)\n", ldir);*/
|
||||
_alpm_log(PM_LOG_FLOW2, "removing %s (if it exists)\n", path);*/
|
||||
/* ORE
|
||||
We should only rmrf the database content, and not the top directory, in case
|
||||
a (DIR *) structure is associated with it (i.e a call to db_open). */
|
||||
_alpm_rmrf(ldir);
|
||||
_alpm_rmrf(path);
|
||||
|
||||
/* make the new dir */
|
||||
if(db_create(root, dbpath, treename) != 0) {
|
||||
if(db_create(root, dbpath, db->treename) != 0) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* uncompress the sync database */
|
||||
/* ORE
|
||||
_alpm_log(PM_LOG_FLOW2, "Unpacking %s...\n", archive);*/
|
||||
if(_alpm_unpack(archive, ldir, NULL)) {
|
||||
if(_alpm_unpack(archive, path, NULL)) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* ORE
|
||||
Should we let the the library manage updates only if needed?
|
||||
Create a .lastupdate file in ldir? Ask for a timestamp as db_update argument? */
|
||||
/* writes the db->path/.lastupdate with the contents of *ts */
|
||||
if(ts && strlen(ts)) {
|
||||
FILE *fp;
|
||||
char file[PATH_MAX];
|
||||
|
||||
snprintf(file, PATH_MAX, "%s/.lastupdate", path);
|
||||
if((fp = fopen(file, "w")) == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
if(fputs(ts, fp) <= 0) {
|
||||
fclose(fp);
|
||||
return(-1);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,9 @@ typedef struct __pmdb_t {
|
|||
pmdb_t *db_open(char *root, char *dbpath, char *treename);
|
||||
void db_close(pmdb_t *db);
|
||||
int db_create(char *root, char *dbpath, char *treename);
|
||||
int db_update(char *root, char *dbpath, char *treename, char *archive);
|
||||
|
||||
int db_getlastupdate(pmdb_t *db, char *root, char *dbpath, char *ts);
|
||||
int db_update(pmdb_t *db, char *root, char *dbpath, char *archive, char *ts);
|
||||
|
||||
void db_rewind(pmdb_t *db);
|
||||
pmpkg_t *db_scan(pmdb_t *db, char *target, unsigned int inforeq);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <alpm.h>
|
||||
/* pacman */
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "list.h"
|
||||
#include "download.h"
|
||||
|
@ -126,7 +127,36 @@ static int copyfile(char *src, char *dest)
|
|||
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 (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(list_t *servers, const char *localpath,
|
||||
list_t *files, const char *mtime1, char *mtime2)
|
||||
{
|
||||
int fsz;
|
||||
netbuf *control = NULL;
|
||||
|
@ -145,7 +175,7 @@ int downloadfiles(list_t *servers, const char *localpath, list_t *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;
|
||||
|
@ -174,9 +204,9 @@ int downloadfiles(list_t *servers, const char *localpath, list_t *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);
|
||||
|
@ -296,21 +326,42 @@ int downloadfiles(list_t *servers, const char *localpath, list_t *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 {
|
||||
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);
|
||||
}
|
||||
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];
|
||||
|
@ -367,7 +418,7 @@ int downloadfiles(list_t *servers, const char *localpath, list_t *files)
|
|||
}
|
||||
}
|
||||
|
||||
if(filedone) {
|
||||
if(filedone > 0) {
|
||||
char completefile[PATH_MAX];
|
||||
if(!strcmp(server->protocol, "file")) {
|
||||
char out[56];
|
||||
|
@ -385,6 +436,8 @@ int downloadfiles(list_t *servers, const char *localpath, list_t *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);
|
||||
|
|
|
@ -31,6 +31,9 @@ typedef struct __server_t {
|
|||
} server_t;
|
||||
|
||||
int downloadfiles(list_t *servers, const char *localpath, list_t *files);
|
||||
int downloadfiles_forreal(list_t *servers, const char *localpath,
|
||||
list_t *files, const char *mtime1, char *mtime2);
|
||||
|
||||
char *fetch_pkgurl(char *target);
|
||||
|
||||
#endif /* _PM_DOWNLOAD_H */
|
||||
|
|
|
@ -107,7 +107,10 @@ void vprint(char *fmt, ...)
|
|||
neednl = 0;
|
||||
}
|
||||
va_start(args, fmt);
|
||||
pm_fprintf(stdout, NL, fmt, args);
|
||||
/* ORE
|
||||
commented for now: it produces corruption
|
||||
pm_fprintf(stdout, NL, fmt, args); */
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,43 +159,54 @@ static int sync_cleancache(int level)
|
|||
static int sync_synctree(list_t *syncs)
|
||||
{
|
||||
char *root, *dbpath;
|
||||
char path[PATH_MAX];
|
||||
list_t *i;
|
||||
int ret = 0;
|
||||
int success = 0, ret;
|
||||
|
||||
alpm_get_option(PM_OPT_ROOT, (long *)&root);
|
||||
alpm_get_option(PM_OPT_DBPATH, (long *)&dbpath);
|
||||
|
||||
for(i = syncs; i; i = i->next) {
|
||||
char path[PATH_MAX];
|
||||
list_t *files = NULL;
|
||||
char *mtime = NULL;
|
||||
char newmtime[16] = "";
|
||||
char lastupdate[16] = "";
|
||||
sync_t *sync = (sync_t *)i->data;
|
||||
|
||||
/* get the lastupdate time */
|
||||
snprintf(path, PATH_MAX, "%s/%s", path, sync->treename);
|
||||
if(alpm_db_getlastupdate(sync->db, lastupdate) == -1) {
|
||||
vprint("failed to get lastupdate time for %s (no big deal)\n", sync->treename);
|
||||
}
|
||||
mtime = lastupdate;
|
||||
|
||||
/* build a one-element list */
|
||||
snprintf(path, PATH_MAX, "%s"PM_EXT_DB, sync->treename);
|
||||
files = list_add(files, strdup(path));
|
||||
|
||||
snprintf(path, PATH_MAX, "%s%s", root, dbpath);
|
||||
|
||||
if(downloadfiles(sync->servers, path, files)) {
|
||||
fprintf(stderr, "failed to synchronize %s\n", sync->treename);
|
||||
FREELIST(files);
|
||||
ret--;
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = downloadfiles_forreal(sync->servers, path, files, mtime, newmtime);
|
||||
vprint("sync: new mtime for %s: %s\n", sync->treename, newmtime);
|
||||
FREELIST(files);
|
||||
|
||||
snprintf(path, PATH_MAX, "%s%s/%s"PM_EXT_DB, root, dbpath, sync->treename);
|
||||
if(alpm_db_update(sync->treename, path) == -1) {
|
||||
fprintf(stderr, "error: %s\n", alpm_strerror(pm_errno));
|
||||
ret--;
|
||||
if(ret > 0) {
|
||||
fprintf(stderr, "failed to synchronize %s\n", sync->treename);
|
||||
success--;
|
||||
} else if(ret < 0) {
|
||||
printf(":: %s is up to date\n", sync->treename);
|
||||
} else {
|
||||
snprintf(path, PATH_MAX, "%s%s/%s"PM_EXT_DB, root, dbpath, sync->treename);
|
||||
if(alpm_db_update(sync->db, path, newmtime) == -1) {
|
||||
fprintf(stderr, "error: failed to set database timestamp (%s)\n", alpm_strerror(pm_errno));
|
||||
success--;
|
||||
}
|
||||
/* remove the .tar.gz */
|
||||
unlink(path);
|
||||
}
|
||||
|
||||
/* remove the .tar.gz */
|
||||
unlink(path);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
return(success);
|
||||
}
|
||||
|
||||
static int sync_search(list_t *syncs, list_t *targets)
|
||||
|
@ -375,13 +386,6 @@ int pacman_sync(list_t *targets)
|
|||
return(sync_cleancache(pmo_s_clean));
|
||||
}
|
||||
|
||||
if(pmo_s_sync) {
|
||||
/* grab a fresh package list */
|
||||
MSG(NL, ":: Synchronizing package databases...\n");
|
||||
alpm_logaction("synchronizing package lists");
|
||||
sync_synctree(pmc_syncs);
|
||||
}
|
||||
|
||||
/* open the database(s) */
|
||||
for(i = pmc_syncs; i; i = i->next) {
|
||||
sync_t *sync = i->data;
|
||||
|
@ -391,6 +395,13 @@ int pacman_sync(list_t *targets)
|
|||
}
|
||||
}
|
||||
|
||||
if(pmo_s_sync) {
|
||||
/* grab a fresh package list */
|
||||
MSG(NL, ":: Synchronizing package databases...\n");
|
||||
alpm_logaction("synchronizing package lists");
|
||||
sync_synctree(pmc_syncs);
|
||||
}
|
||||
|
||||
if(pmo_s_search) {
|
||||
return(sync_search(pmc_syncs, targets));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue