From 35a794c2ed4da7da44d3a04794fc90615e7c52e7 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 4 Jun 2007 14:50:16 -0400 Subject: Allow multiple CacheDirs to be specified This should hopefully allow multiple cache dirs to be specified in pacman.conf and/or on the command line, and allow pacman to test each one for the package file. The first one found to be writeable is used as the download cache. Signed-off-by: Dan McGee --- lib/libalpm/alpm.h | 5 ++- lib/libalpm/handle.c | 24 ++++++++---- lib/libalpm/handle.h | 2 +- lib/libalpm/package.c | 27 ++++++++++++-- lib/libalpm/sync.c | 101 ++++++++++++++++++++++++++++++++++---------------- 5 files changed, 113 insertions(+), 46 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 9f029b2e..d4c584f8 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -97,8 +97,9 @@ void alpm_option_set_root(const char *root); const char *alpm_option_get_dbpath(); void alpm_option_set_dbpath(const char *dbpath); -const char *alpm_option_get_cachedir(); -void alpm_option_set_cachedir(const char *cachedir); +alpm_list_t *alpm_option_get_cachedirs(); +void alpm_option_add_cachedir(const char *cachedir); +void alpm_option_set_cachedirs(alpm_list_t *cachedirs); const char *alpm_option_get_logfile(); void alpm_option_set_logfile(const char *logfile); diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index ae20ef11..6f9e3330 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -80,7 +80,7 @@ pmhandle_t *_alpm_handle_new() #endif handle->root = NULL; handle->dbpath = NULL; - handle->cachedir = NULL; + handle->cachedirs = NULL; handle->lockfile = NULL; handle->logfile = NULL; @@ -109,7 +109,7 @@ void _alpm_handle_free(pmhandle_t *handle) _alpm_trans_free(handle->trans); FREE(handle->root); FREE(handle->dbpath); - FREE(handle->cachedir); + FREELIST(handle->cachedirs); FREE(handle->logfile); FREE(handle->lockfile); FREE(handle->xfercommand); @@ -125,7 +125,7 @@ alpm_cb_log SYMEXPORT alpm_option_get_logcb() { return (handle ? handle->logcb : alpm_cb_download SYMEXPORT alpm_option_get_dlcb() { return (handle ? handle->dlcb : NULL); } const char SYMEXPORT *alpm_option_get_root() { return handle->root; } const char SYMEXPORT *alpm_option_get_dbpath() { return handle->dbpath; } -const char SYMEXPORT *alpm_option_get_cachedir() { return handle->cachedir; } +alpm_list_t SYMEXPORT *alpm_option_get_cachedirs() { return handle->cachedirs; } const char SYMEXPORT *alpm_option_get_logfile() { return handle->logfile; } const char SYMEXPORT *alpm_option_get_lockfile() { return handle->lockfile; } unsigned short SYMEXPORT alpm_option_get_usesyslog() { return handle->usesyslog; } @@ -193,23 +193,31 @@ void SYMEXPORT alpm_option_set_dbpath(const char *dbpath) } } -void SYMEXPORT alpm_option_set_cachedir(const char *cachedir) +void SYMEXPORT alpm_option_add_cachedir(const char *cachedir) { ALPM_LOG_FUNC; - if(handle->cachedir) FREE(handle->cachedir); if(cachedir) { + char *newcachedir; /* verify cachedir ends in a '/' */ int cachedirlen = strlen(cachedir); if(cachedir[cachedirlen-1] != '/') { cachedirlen += 1; } - handle->cachedir = calloc(cachedirlen+1, sizeof(char)); - strncpy(handle->cachedir, cachedir, cachedirlen); - handle->cachedir[cachedirlen-1] = '/'; + newcachedir = calloc(cachedirlen + 1, sizeof(char)); + strncpy(newcachedir, cachedir, cachedirlen); + newcachedir[cachedirlen-1] = '/'; + handle->cachedirs = alpm_list_add(handle->cachedirs, newcachedir); + _alpm_log(PM_LOG_DEBUG, _("option 'cachedir' = %s"), newcachedir); } } +void SYMEXPORT alpm_option_set_cachedirs(alpm_list_t *cachedirs) +{ + if(handle->cachedirs) FREELIST(handle->cachedirs); + if(cachedirs) handle->cachedirs = cachedirs; +} + void SYMEXPORT alpm_option_set_logfile(const char *logfile) { ALPM_LOG_FUNC; diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index 8e6003c0..b0e80338 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -50,7 +50,7 @@ typedef struct _pmhandle_t { alpm_cb_download dlcb; /* Download callback function */ char *root; /* Root path, default '/' */ char *dbpath; /* Base path to pacman's DBs */ - char *cachedir; /* Base path to pacman's cache */ + alpm_list_t *cachedirs; /* Paths to pacman cache directories */ char *logfile; /* Name of the file to log to */ /*TODO is this used?*/ char *lockfile; /* Name of the lock file */ unsigned short usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index e25ecbe4..16166691 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -103,7 +103,9 @@ int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg) int alpm_pkg_checksha1sum(pmpkg_t *pkg) { char path[PATH_MAX]; + struct stat buf; char *sha1sum = NULL; + alpm_list_t *i; int retval = 0; ALPM_LOG_FUNC; @@ -113,8 +115,14 @@ int alpm_pkg_checksha1sum(pmpkg_t *pkg) ASSERT(pkg->origin == PKG_FROM_CACHE, RET_ERR(PM_ERR_PKG_INVALID, -1)); ASSERT(pkg->data != handle->db_local, RET_ERR(PM_ERR_PKG_INVALID, -1)); - snprintf(path, PATH_MAX, "%s/%s-%s" PKGEXT, handle->cachedir, - alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); + /* Loop through the cache dirs until we find a matching file */ + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + snprintf(path, PATH_MAX, "%s%s-%s" PKGEXT, (char*)alpm_list_getdata(i), + alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); + if(stat(path, &buf) == 0) { + break; + } + } sha1sum = alpm_get_sha1sum(path); if(sha1sum == NULL) { @@ -146,7 +154,9 @@ int alpm_pkg_checksha1sum(pmpkg_t *pkg) int alpm_pkg_checkmd5sum(pmpkg_t *pkg) { char path[PATH_MAX]; + struct stat buf; char *md5sum = NULL; + alpm_list_t *i; int retval = 0; ALPM_LOG_FUNC; @@ -156,8 +166,14 @@ int alpm_pkg_checkmd5sum(pmpkg_t *pkg) ASSERT(pkg->origin == PKG_FROM_CACHE, RET_ERR(PM_ERR_PKG_INVALID, -1)); ASSERT(pkg->data != handle->db_local, RET_ERR(PM_ERR_PKG_INVALID, -1)); - snprintf(path, PATH_MAX, "%s/%s-%s" PKGEXT, handle->cachedir, - alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); + /* Loop through the cache dirs until we find a matching file */ + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + snprintf(path, PATH_MAX, "%s%s-%s" PKGEXT, (char*)alpm_list_getdata(i), + alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); + if(stat(path, &buf) == 0) { + break; + } + } md5sum = alpm_get_md5sum(path); if(md5sum == NULL) { @@ -182,6 +198,9 @@ int alpm_pkg_checkmd5sum(pmpkg_t *pkg) return(retval); } + + + /** Compare versions. * @param ver1 first version * @param ver2 secont version diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 632e510b..5d9e1e6c 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -766,8 +766,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) alpm_list_t *i, *j, *files = NULL; pmtrans_t *tr = NULL; int replaces = 0, retval = 0; - const char *cachedir; - int varcache = 1; + int validcache = 0; + const char *maincachedir = NULL; ALPM_LOG_FUNC; @@ -776,8 +776,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) trans->state = STATE_DOWNLOADING; /* group sync records by repository and download */ - cachedir = alpm_option_get_cachedir(); - for(i = handle->dbs_sync; i; i = i->next) { pmdb_t *current = i->data; @@ -795,12 +793,20 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_PRINTURI, (char *)alpm_db_get_url(current), (char *)fname); } else { struct stat buf; - snprintf(path, PATH_MAX, "%s/%s", cachedir, fname); - if(stat(path, &buf)) { + int found = 0; + /* Loop through the cache dirs until we find a matching file */ + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + snprintf(path, PATH_MAX, "%s%s", (char*)alpm_list_getdata(i), + fname); + if(stat(path, &buf) == 0) { + found = 1; + _alpm_log(PM_LOG_DEBUG, _("found cached pkg: %s"), path); + break; + } + } + if(!found) { /* file is not in the cache dir, so add it to the list */ files = alpm_list_add(files, strdup(fname)); - } else { - _alpm_log(PM_LOG_DEBUG, _("%s is already in the cache\n"), fname); } } } @@ -808,24 +814,42 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(files) { struct stat buf; + char *cachedir; EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); - if(stat(cachedir, &buf)) { - /* no cache directory.... try creating it */ - _alpm_log(PM_LOG_WARNING, _("no %s cache exists, creating...\n"), cachedir); - alpm_logaction(_("warning: no %s cache exists, creating..."), cachedir); - if(_alpm_makepath(cachedir)) { - /* couldn't mkdir the cache directory, so fall back to /tmp and unlink - * the package afterwards. - */ - _alpm_log(PM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); - alpm_logaction(_("warning: couldn't create package cache, using /tmp instead")); - alpm_option_set_cachedir("/tmp"); - cachedir = alpm_option_get_cachedir(); - varcache = 0; + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + cachedir = alpm_list_getdata(i); + if(stat(cachedir, &buf) != 0) { + /* cache directory does not exist.... try creating it */ + _alpm_log(PM_LOG_WARNING, _("no %s cache exists, creating...\n"), + cachedir); + alpm_logaction(_("warning: no %s cache exists, creating..."), + cachedir); + if(_alpm_makepath(cachedir) == 0) { + _alpm_log(PM_LOG_DEBUG, _("setting main cachedir: %s"), cachedir); + maincachedir = cachedir; + validcache = 1; + break; + } + } else if(S_ISDIR(buf.st_mode) && (buf.st_mode & S_IWUSR)) { + _alpm_log(PM_LOG_DEBUG, _("setting main cachedir: %s"), cachedir); + maincachedir = cachedir; + validcache = 1; + break; } } - if(_alpm_downloadfiles(current->servers, alpm_option_get_cachedir(), - files)) { + if(!validcache) { + /* we had no valid cache directories, so fall back to /tmp and + * unlink the packages afterwards. */ + alpm_list_t *oldcachedirs = alpm_option_get_cachedirs(); + alpm_list_t *cachetmp = alpm_list_add(NULL, strdup("/tmp/")); + FREELIST(oldcachedirs); + alpm_option_set_cachedirs(cachetmp); + _alpm_log(PM_LOG_DEBUG, _("setting main cachedir: %s"), "/tmp/"); + maincachedir = alpm_list_getdata(cachetmp); + _alpm_log(PM_LOG_WARNING, _("couldn't create package cache, using /tmp instead")); + alpm_logaction(_("warning: couldn't create package cache, using /tmp instead")); + } + if(_alpm_downloadfiles(current->servers, maincachedir, files)) { _alpm_log(PM_LOG_WARNING, _("failed to retrieve some files from %s\n"), current->treename); RET_ERR(PM_ERR_RETRIEVE, -1); } @@ -843,6 +867,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) pmsyncpkg_t *sync = i->data; pmpkg_t *spkg = sync->pkg; char str[PATH_MAX]; + struct stat buf; const char *pkgname; char *md5sum1, *md5sum2, *sha1sum1, *sha1sum2; char *ptr=NULL; @@ -861,9 +886,19 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) retval = 1; continue; } - snprintf(str, PATH_MAX, "%s%s", alpm_option_get_cachedir(), pkgname); - md5sum2 = _alpm_MDFile(str); - sha1sum2 = _alpm_SHAFile(str); + + /* Loop through the cache dirs until we find a matching file */ + for(j = alpm_option_get_cachedirs(); j; j = alpm_list_next(j)) { + snprintf(str, PATH_MAX, "%s%s", (char*)alpm_list_getdata(j), pkgname); + if(stat(str, &buf) == 0) { + _alpm_log(PM_LOG_DEBUG, _("package found for integrity check: %s"), + str); + break; + } + } + + md5sum2 = alpm_get_md5sum(str); + sha1sum2 = alpm_get_sha1sum(str); if(md5sum2 == NULL && sha1sum2 == NULL) { if((ptr = calloc(512, sizeof(char))) == NULL) { RET_ERR(PM_ERR_MEMORY, -1); @@ -884,8 +919,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)pkgname, NULL, NULL, &doremove); } if(doremove) { - char str[PATH_MAX]; - snprintf(str, PATH_MAX, "%s%s", alpm_option_get_cachedir(), pkgname); unlink(str); snprintf(ptr, 512, _("archive %s was corrupted (bad MD5 or SHA1 checksum)\n"), pkgname); } else { @@ -966,12 +999,18 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) for(i = trans->packages; i; i = i->next) { pmsyncpkg_t *sync = i->data; pmpkg_t *spkg = sync->pkg; - + struct stat buf; const char *fname = NULL; char str[PATH_MAX]; fname = alpm_pkg_get_filename(spkg); - snprintf(str, PATH_MAX, "%s%s", alpm_option_get_cachedir(), fname); + /* Loop through the cache dirs until we find a matching file */ + for(j = alpm_option_get_cachedirs(); j; j = alpm_list_next(j)) { + snprintf(str, PATH_MAX, "%s%s", (char*)alpm_list_getdata(j), fname); + if(stat(str, &buf) == 0) { + break; + } + } if(_alpm_trans_addtarget(tr, str) == -1) { goto error; } @@ -1041,7 +1080,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) } } - if(!varcache && !(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY)) { + if(!validcache && !(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY)) { /* delete packages */ for(i = files; i; i = i->next) { unlink(i->data); -- cgit v1.2.3-24-g4f1b