diff options
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r-- | lib/libalpm/sync.c | 305 |
1 files changed, 164 insertions, 141 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index f83b0ef9..7a33bc97 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -26,11 +26,9 @@ #include <sys/types.h> /* off_t */ #include <stdlib.h> #include <stdio.h> -#include <fcntl.h> #include <string.h> #include <stdint.h> /* intmax_t */ #include <unistd.h> -#include <time.h> #include <limits.h> /* libalpm */ @@ -50,13 +48,17 @@ #include "delta.h" #include "remove.h" #include "diskspace.h" +#include "signing.h" + +/* global handle variable */ +extern pmhandle_t *handle; /** Check for new version of pkg in sync repos * (only the first occurrence is considered in sync) */ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) { - ASSERT(pkg != NULL, return(NULL)); + ASSERT(pkg != NULL, return NULL); alpm_list_t *i; pmpkg_t *spkg = NULL; @@ -68,7 +70,7 @@ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) if(spkg == NULL) { _alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n", alpm_pkg_get_name(pkg)); - return(NULL); + return NULL; } /* compare versions and see if spkg is an upgrade */ @@ -76,15 +78,13 @@ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) _alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg), alpm_pkg_get_version(spkg)); - return(spkg); + return spkg; } /* spkg is not an upgrade */ - return(NULL); + return NULL; } -/** Search for packages to upgrade and add them to the transaction. - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ +/** Search for packages to upgrade and add them to the transaction. */ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) { alpm_list_t *i, *j, *k; @@ -92,8 +92,6 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) pmdb_t *db_local; alpm_list_t *dbs_sync; - ALPM_LOG_FUNC; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); trans = handle->trans; db_local = handle->db_local; @@ -116,7 +114,8 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) pmdb_t *sdb = j->data; /* Check sdb */ pmpkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); - if(spkg) { /* 1. literal was found in sdb */ + if(spkg) { + /* 1. literal was found in sdb */ int cmp = _alpm_pkg_compare_versions(spkg, lpkg); if(cmp > 0) { _alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", @@ -146,8 +145,10 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) lpkg->name, lpkg->version, sdb->treename, spkg->version); } } - break; /* jump to next local package */ - } else { /* 2. search for replacers in sdb */ + /* jump to next local package */ + break; + } else { + /* 2. search for replacers in sdb */ int found = 0; for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { spkg = k->data; @@ -183,7 +184,8 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) if(alpm_pkg_get_reason(lpkg) == PM_PKG_REASON_EXPLICIT) { tpkg->reason = PM_PKG_REASON_EXPLICIT; } - } else { /* add spkg to the target list */ + } else { + /* add spkg to the target list */ /* copy over reason */ spkg->reason = alpm_pkg_get_reason(lpkg); spkg->removes = alpm_list_add(NULL, lpkg); @@ -200,7 +202,7 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) } } - return(0); + return 0; } /** Find group members across a list of databases. @@ -231,7 +233,7 @@ alpm_list_t SYMEXPORT *alpm_find_grp_pkgs(alpm_list_t *dbs, if(_alpm_pkg_should_ignore(pkg)) { ignorelist = alpm_list_add(ignorelist, pkg); int install = 0; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, + QUESTION(db->handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); if(!install) continue; @@ -242,7 +244,7 @@ alpm_list_t SYMEXPORT *alpm_find_grp_pkgs(alpm_list_t *dbs, } } alpm_list_free(ignorelist); - return(pkgs); + return pkgs; } /** Compute the size of the files that will be downloaded to install a @@ -258,7 +260,7 @@ static int compute_download_size(pmpkg_t *newpkg) if(newpkg->origin != PKG_FROM_SYNCDB) { newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = 0; - return(0); + return 0; } fname = alpm_pkg_get_filename(newpkg); @@ -268,7 +270,7 @@ static int compute_download_size(pmpkg_t *newpkg) if(fpath) { FREE(fpath); size = 0; - } else if(handle->usedelta) { + } else if(newpkg->handle->usedelta) { off_t dltsize; off_t pkgsize = alpm_pkg_get_size(newpkg); @@ -295,21 +297,18 @@ static int compute_download_size(pmpkg_t *newpkg) newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = size; - return(0); + return 0; } -int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data) +int _alpm_sync_prepare(pmhandle_t *handle, alpm_list_t **data) { alpm_list_t *deps = NULL; alpm_list_t *unresolvable = NULL; alpm_list_t *i, *j; alpm_list_t *remove = NULL; int ret = 0; - - ALPM_LOG_FUNC; - - ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + pmtrans_t *trans = handle->trans; + pmdb_t *db_local = handle->db_local; if(data) { *data = NULL; @@ -340,7 +339,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { pmpkg_t *pkg = i->data; - if(_alpm_resolvedeps(localpkgs, dbs_sync, pkg, trans->add, + if(_alpm_resolvedeps(localpkgs, handle->dbs_sync, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } @@ -355,7 +354,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync int remove_unresolvable = 0; QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); - if (remove_unresolvable) { + if(remove_unresolvable) { /* User wants to remove the unresolvable packages from the transaction. The packages will be removed from the actual transaction when the transaction packages are replaced with a @@ -551,7 +550,7 @@ cleanup: alpm_list_free(unresolvable); alpm_list_free(remove); - return(ret); + return ret; } /** Returns the size of the files that will be downloaded to install a @@ -564,13 +563,13 @@ off_t SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg) if(!(newpkg->infolevel & INFRQ_DSIZE)) { compute_download_size(newpkg); } - return(newpkg->download_size); + return newpkg->download_size; } static int endswith(const char *filename, const char *extension) { const char *s = filename + strlen(filename) - strlen(extension); - return(strcmp(s, extension) == 0); + return strcmp(s, extension) == 0; } /** Applies delta files to create an upgraded package file. @@ -650,13 +649,14 @@ static int apply_deltas(pmtrans_t *trans) if(retval != 0) { /* one delta failed for this package, cancel the remaining ones */ EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL); + pm_errno = PM_ERR_DLT_PATCHFAILED; ret = 1; break; } } } - return(ret); + return ret; } /** Compares the md5sum of a file to the expected value. @@ -665,50 +665,74 @@ static int apply_deltas(pmtrans_t *trans) * should be deleted. * * @param trans the transaction - * @param filename the filename of the file to test + * @param filename the absolute path of the file to test * @param md5sum the expected md5sum of the file * * @return 0 if the md5sum matched, 1 if not, -1 in case of errors */ -static int test_md5sum(pmtrans_t *trans, const char *filename, +static int test_md5sum(pmtrans_t *trans, const char *filepath, const char *md5sum) { - char *filepath; - int ret; - - filepath = _alpm_filecache_find(filename); - - ret = _alpm_test_md5sum(filepath, md5sum); - + int ret = _alpm_test_md5sum(filepath, md5sum); if(ret == 1) { int doremove = 0; - QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)filename, + QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)filepath, NULL, NULL, &doremove); if(doremove) { unlink(filepath); } } - FREE(filepath); - - return(ret); + return ret; } -int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) +static int validate_deltas(pmtrans_t *trans, alpm_list_t *deltas, + alpm_list_t **data) { - alpm_list_t *i, *j, *files = NULL; - alpm_list_t *deltas = NULL; - size_t numtargs, current = 0, replaces = 0; - int errors = 0; - const char *cachedir = NULL; - int ret = -1; + int errors = 0, ret = 0; + alpm_list_t *i; - ALPM_LOG_FUNC; + if(!deltas) { + return 0; + } - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + /* Check integrity of deltas */ + EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL); + + for(i = deltas; i; i = i->next) { + pmdelta_t *d = alpm_list_getdata(i); + const char *filename = alpm_delta_get_filename(d); + char *filepath = _alpm_filecache_find(filename); + const char *md5sum = alpm_delta_get_md5sum(d); + + if(test_md5sum(trans, filepath, md5sum) != 0) { + errors++; + *data = alpm_list_add(*data, strdup(filename)); + } + FREE(filepath); + } + if(errors) { + pm_errno = PM_ERR_DLT_INVALID; + return -1; + } + EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL); + + /* Use the deltas to generate the packages */ + EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL); + ret = apply_deltas(trans); + EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL); + return ret; +} + +static int download_files(pmhandle_t *handle, alpm_list_t **deltas) +{ + const char *cachedir; + alpm_list_t *i, *j; + alpm_list_t *files = NULL; + int errors = 0; cachedir = _alpm_filecache_setup(); - trans->state = STATE_DOWNLOADING; + handle->trans->state = STATE_DOWNLOADING; /* Total progress - figure out the total download size if required to * pass to the callback. This function is called once, and it is up to the @@ -716,7 +740,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { off_t total_size = (off_t)0; /* sum up the download size for each package and store total */ - for(i = trans->add; i; i = i->next) { + for(i = handle->trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; total_size += spkg->download_size; } @@ -727,7 +751,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) for(i = handle->dbs_sync; i; i = i->next) { pmdb_t *current = i->data; - for(j = trans->add; j; j = j->next) { + for(j = handle->trans->add; j; j = j->next) { pmpkg_t *spkg = j->data; if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { @@ -738,48 +762,63 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) alpm_list_t *delta_path = spkg->delta_path; if(delta_path) { /* using deltas */ - alpm_list_t *dlts = NULL; - + alpm_list_t *dlts; for(dlts = delta_path; dlts; dlts = dlts->next) { - pmdelta_t *d = dlts->data; - - if(d->download_size != 0) { - /* add the delta filename to the download list if needed */ - files = alpm_list_add(files, strdup(d->delta)); + pmdelta_t *delta = dlts->data; + if(delta->download_size != 0) { + files = alpm_list_add(files, strdup(delta->delta)); } - /* keep a list of all the delta files for md5sums */ - deltas = alpm_list_add(deltas, d); + *deltas = alpm_list_add(*deltas, delta); } - } else { - /* not using deltas */ - if(spkg->download_size != 0) { - /* add the filename to the download list if needed */ - files = alpm_list_add(files, strdup(fname)); - } + } else if(spkg->download_size != 0) { + files = alpm_list_add(files, strdup(fname)); } } } if(files) { - EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); - errors = _alpm_download_files(files, current->servers, cachedir); + EVENT(handle->trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); + for(j = files; j; j = j->next) { + const char *filename = j->data; + alpm_list_t *server; + int ret = -1; + for(server = current->servers; server; server = server->next) { + const char *server_url = server->data; + char *fileurl; + size_t len; + + /* print server + filename into a buffer */ + len = strlen(server_url) + strlen(filename) + 2; + CALLOC(fileurl, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); + snprintf(fileurl, len, "%s/%s", server_url, filename); + + ret = _alpm_download(fileurl, cachedir, 0, 1, 0); + FREE(fileurl); + if(ret != -1) { + break; + } + } + if(ret == -1) { + errors++; + } + } - if (errors) { + FREELIST(files); + if(errors) { _alpm_log(PM_LOG_WARNING, _("failed to retrieve some files from %s\n"), current->treename); if(pm_errno == 0) { pm_errno = PM_ERR_RETRIEVE; } - goto error; + return -1; } - FREELIST(files); } } - for(j = trans->add; j; j = j->next) { + for(j = handle->trans->add; j; j = j->next) { pmpkg_t *pkg = j->data; pkg->infolevel &= ~INFRQ_DSIZE; pkg->download_size = 0; @@ -789,70 +828,58 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { handle->totaldlcb(0); } + return 0; +} - /* if we have deltas to work with */ - if(handle->usedelta && deltas) { - int ret = 0; - errors = 0; - /* Check integrity of deltas */ - EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL); - - for(i = deltas; i; i = i->next) { - pmdelta_t *d = alpm_list_getdata(i); - const char *filename = alpm_delta_get_filename(d); - const char *md5sum = alpm_delta_get_md5sum(d); - - if(test_md5sum(trans, filename, md5sum) != 0) { - errors++; - *data = alpm_list_add(*data, strdup(filename)); - } - } - if(errors) { - pm_errno = PM_ERR_DLT_INVALID; - goto error; - } - EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL); +int _alpm_sync_commit(pmhandle_t *handle, alpm_list_t **data) +{ + alpm_list_t *i; + alpm_list_t *deltas = NULL; + size_t numtargs, current = 0, replaces = 0; + int errors; + pmtrans_t *trans = handle->trans; - /* Use the deltas to generate the packages */ - EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL); - ret = apply_deltas(trans); - EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL); + if(download_files(handle, &deltas)) { + alpm_list_free(deltas); + return -1; + } - if(ret) { - pm_errno = PM_ERR_DLT_PATCHFAILED; - goto error; - } + if(validate_deltas(trans, deltas, data)) { + alpm_list_free(deltas); + return -1; } + alpm_list_free(deltas); /* Check integrity of packages */ numtargs = alpm_list_count(trans->add); EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL); errors = 0; + for(i = trans->add; i; i = i->next, current++) { pmpkg_t *spkg = i->data; int percent = (current * 100) / numtargs; + const char *filename; + char *filepath; + pgp_verify_t check_sig; + + PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", percent, + numtargs, current); if(spkg->origin == PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } - PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", percent, - numtargs, current); - const char *filename = alpm_pkg_get_filename(spkg); - const char *md5sum = alpm_pkg_get_md5sum(spkg); + filename = alpm_pkg_get_filename(spkg); + filepath = _alpm_filecache_find(filename); + pmdb_t *sdb = alpm_pkg_get_db(spkg); + check_sig = _alpm_db_get_sigverify_level(sdb); - if(test_md5sum(trans, filename, md5sum) != 0) { - errors++; - *data = alpm_list_add(*data, strdup(filename)); - continue; - } /* load the package file and replace pkgcache entry with it in the target list */ /* TODO: alpm_pkg_get_db() will not work on this target anymore */ _alpm_log(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name); - char *filepath = _alpm_filecache_find(filename); - pmpkg_t *pkgfile; - if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) { - _alpm_pkg_free(pkgfile); + pmpkg_t *pkgfile =_alpm_pkg_load_internal(filepath, 1, spkg->md5sum, + spkg->base64_sig, check_sig); + if(!pkgfile) { errors++; *data = alpm_list_add(*data, strdup(filename)); FREE(filepath); @@ -863,17 +890,18 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) i->data = pkgfile; _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } + PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", 100, numtargs, current); EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); + + if(errors) { - pm_errno = PM_ERR_PKG_INVALID; - goto error; + RET_ERR(PM_ERR_PKG_INVALID, -1); } if(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY) { - ret = 0; - goto error; + return 0; } trans->state = STATE_COMMITING; @@ -885,17 +913,16 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans, - trans->add, trans->remove); + alpm_list_t *conflict = _alpm_db_find_fileconflicts(handle, + trans->add, trans->remove); if(conflict) { - pm_errno = PM_ERR_FILE_CONFLICTS; if(data) { *data = conflict; } else { alpm_list_free_inner(conflict, (alpm_list_fn_free)_alpm_fileconflict_free); alpm_list_free(conflict); } - goto error; + RET_ERR(PM_ERR_FILE_CONFLICTS, -1); } EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); @@ -906,9 +933,9 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_DISKSPACE_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "checking available disk space\n"); - if(_alpm_check_diskspace(trans, handle->db_local) == -1) { + if(_alpm_check_diskspace(handle) == -1) { _alpm_log(PM_LOG_ERROR, "%s\n", _("not enough free disk space")); - goto error; + return -1; } EVENT(trans, PM_TRANS_EVT_DISKSPACE_DONE, NULL, NULL); @@ -918,24 +945,20 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(replaces) { _alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); /* we want the frontend to be aware of commit details */ - if(_alpm_remove_packages(trans, handle->db_local) == -1) { + if(_alpm_remove_packages(handle) == -1) { _alpm_log(PM_LOG_ERROR, _("could not commit removal transaction\n")); - goto error; + return -1; } } /* install targets */ _alpm_log(PM_LOG_DEBUG, "installing packages\n"); - if(_alpm_upgrade_packages(trans, handle->db_local) == -1) { + if(_alpm_upgrade_packages(handle) == -1) { _alpm_log(PM_LOG_ERROR, _("could not commit transaction\n")); - goto error; + return -1; } - ret = 0; -error: - FREELIST(files); - alpm_list_free(deltas); - return(ret); + return 0; } /* vim: set ts=2 sw=2 noet: */ |