diff options
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r-- | lib/libalpm/sync.c | 239 |
1 files changed, 143 insertions, 96 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index e500d90f..ca6b507e 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -1,7 +1,7 @@ /* * sync.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <sys/types.h> /* off_t */ #include <stdlib.h> #include <stdio.h> @@ -251,7 +249,7 @@ alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs, for(i = dbs; i; i = i->next) { alpm_db_t *db = i->data; - alpm_group_t *grp = alpm_db_readgroup(db, name); + alpm_group_t *grp = alpm_db_get_group(db, name); if(!grp) continue; @@ -291,7 +289,7 @@ static int compute_download_size(alpm_pkg_t *newpkg) alpm_handle_t *handle = newpkg->handle; int ret = 0; - if(newpkg->origin != PKG_FROM_SYNCDB) { + if(newpkg->origin != ALPM_PKG_FROM_SYNCDB) { newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = 0; return 0; @@ -321,13 +319,13 @@ static int compute_download_size(alpm_pkg_t *newpkg) /* tell the caller that we have a partial */ ret = 1; - } else if(handle->usedelta) { + } else if(handle->deltaratio > 0.0) { off_t dltsize; dltsize = _alpm_shortest_delta_path(handle, newpkg->deltas, newpkg->filename, &newpkg->delta_path); - if(newpkg->delta_path && (dltsize < newpkg->size * MAX_DELTA_RATIO)) { + if(newpkg->delta_path && (dltsize < newpkg->size * handle->deltaratio)) { _alpm_log(handle, ALPM_LOG_DEBUG, "using delta size\n"); size = dltsize; } else { @@ -368,7 +366,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; - from_sync += (spkg->origin == PKG_FROM_SYNCDB); + from_sync += (spkg->origin == ALPM_PKG_FROM_SYNCDB); } /* ensure all sync database are valid if we will be using them */ @@ -424,7 +422,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { int remove_unresolvable = 0; - enum _alpm_errno_t saved_err = handle->pm_errno; + alpm_errno_t saved_err = handle->pm_errno; QUESTION(handle, ALPM_QUESTION_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); if(remove_unresolvable) { @@ -696,11 +694,11 @@ static int apply_deltas(alpm_handle_t *handle) } else { /* len = cachedir len + from len + '/' + null */ len = strlen(cachedir) + strlen(d->from) + 2; - CALLOC(from, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1)); + MALLOC(from, len, RET_ERR(handle, ALPM_ERR_MEMORY, 1)); snprintf(from, len, "%s/%s", cachedir, d->from); } len = strlen(cachedir) + strlen(d->to) + 2; - CALLOC(to, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1)); + MALLOC(to, len, RET_ERR(handle, ALPM_ERR_MEMORY, 1)); snprintf(to, len, "%s/%s", cachedir, d->to); /* build the patch command */ @@ -758,7 +756,7 @@ static int apply_deltas(alpm_handle_t *handle) * @return 1 if file was removed, 0 otherwise */ static int prompt_to_delete(alpm_handle_t *handle, const char *filepath, - enum _alpm_errno_t reason) + alpm_errno_t reason) { int doremove = 0; QUESTION(handle, ALPM_QUESTION_CORRUPTED_PKG, (char *)filepath, @@ -783,7 +781,7 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas) alpm_delta_t *d = i->data; char *filepath = _alpm_filecache_find(handle, d->delta); - if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_CSUM_MD5)) { + if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_PKG_VALIDATION_MD5SUM)) { errors = alpm_list_add(errors, filepath); } else { FREE(filepath); @@ -804,11 +802,96 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas) return 0; } +static struct dload_payload *build_payload(alpm_handle_t *handle, + const char *filename, size_t size, alpm_list_t *servers) +{ + struct dload_payload *payload; + + CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + STRDUP(payload->remote_name, filename, RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + payload->max_size = size; + payload->servers = servers; + return payload; +} + +static int find_dl_candidates(alpm_db_t *repo, alpm_list_t **files, alpm_list_t **deltas) +{ + alpm_list_t *i; + alpm_handle_t *handle = repo->handle; + + for(i = handle->trans->add; i; i = i->next) { + alpm_pkg_t *spkg = i->data; + + if(spkg->origin != ALPM_PKG_FROM_FILE && repo == spkg->origin_data.db) { + alpm_list_t *delta_path = spkg->delta_path; + + if(!repo->servers) { + handle->pm_errno = ALPM_ERR_SERVER_NONE; + _alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n", + alpm_strerror(handle->pm_errno), repo->treename); + return 1; + } + + if(delta_path) { + /* using deltas */ + alpm_list_t *dlts; + for(dlts = delta_path; dlts; dlts = dlts->next) { + alpm_delta_t *delta = dlts->data; + if(delta->download_size != 0) { + struct dload_payload *payload = build_payload( + handle, delta->delta, delta->delta_size, repo->servers); + ASSERT(payload, return -1); + *files = alpm_list_add(*files, payload); + } + /* keep a list of all the delta files for md5sums */ + *deltas = alpm_list_add(*deltas, delta); + } + + } else if(spkg->download_size != 0) { + struct dload_payload *payload; + ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); + payload = build_payload(handle, spkg->filename, spkg->size, repo->servers); + ASSERT(payload, return -1); + *files = alpm_list_add(*files, payload); + } + } + } + + return 0; +} + +static int download_single_file(alpm_handle_t *handle, struct dload_payload *payload, + const char *cachedir) +{ + const alpm_list_t *server; + + payload->handle = handle; + payload->allow_resume = 1; + + for(server = payload->servers; server; server = server->next) { + const char *server_url = server->data; + size_t len; + + /* print server + filename into a buffer */ + len = strlen(server_url) + strlen(payload->remote_name) + 2; + MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name); + + if(_alpm_download(payload, cachedir, NULL) != -1) { + return 0; + } + + FREE(payload->fileurl); + payload->unlink_on_fail = 0; + } + + return -1; +} + static int download_files(alpm_handle_t *handle, alpm_list_t **deltas) { const char *cachedir; - alpm_list_t *i, *j; - alpm_list_t *files = NULL; + alpm_list_t *i, *files = NULL; int errors = 0; cachedir = _alpm_filecache_setup(handle); @@ -827,93 +910,53 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas) handle->totaldlcb(total_size); } - /* group sync records by repository and download */ for(i = handle->dbs_sync; i; i = i->next) { - alpm_db_t *current = i->data; - - for(j = handle->trans->add; j; j = j->next) { - alpm_pkg_t *spkg = j->data; - - if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { - alpm_list_t *delta_path = spkg->delta_path; - if(delta_path) { - /* using deltas */ - alpm_list_t *dlts; - for(dlts = delta_path; dlts; dlts = dlts->next) { - alpm_delta_t *delta = dlts->data; - if(delta->download_size != 0) { - struct dload_payload *dpayload; - - CALLOC(dpayload, 1, sizeof(*dpayload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - STRDUP(dpayload->remote_name, delta->delta, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - dpayload->max_size = delta->delta_size; - - files = alpm_list_add(files, dpayload); - } - /* keep a list of all the delta files for md5sums */ - *deltas = alpm_list_add(*deltas, delta); - } + errors += find_dl_candidates(i->data, &files, deltas); + } - } else if(spkg->download_size != 0) { - struct dload_payload *payload; + if(files) { + /* check for necessary disk space for download */ + if(handle->checkspace) { + off_t *file_sizes; + size_t idx, num_files; + int ret; - ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); - CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - STRDUP(payload->remote_name, spkg->filename, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - payload->max_size = spkg->size; + _alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space for download\n"); - files = alpm_list_add(files, payload); - } + num_files = alpm_list_count(files); + CALLOC(file_sizes, num_files, sizeof(off_t), goto finish); + for(i = files, idx = 0; i; i = i->next, idx++) { + const struct dload_payload *payload = i->data; + file_sizes[idx] = payload->max_size; } - } - if(files) { - if(!current->servers) { - handle->pm_errno = ALPM_ERR_SERVER_NONE; - _alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n", - alpm_strerror(handle->pm_errno), current->treename); + ret = _alpm_check_downloadspace(handle, cachedir, num_files, file_sizes); + free(file_sizes); + + if(ret != 0) { errors++; - continue; + goto finish; } + } - EVENT(handle, ALPM_EVENT_RETRIEVE_START, current->treename, NULL); - for(j = files; j; j = j->next) { - struct dload_payload *payload = j->data; - alpm_list_t *server; - int ret = -1; - for(server = current->servers; server; server = server->next) { - const char *server_url = server->data; - size_t len; - - /* print server + filename into a buffer */ - len = strlen(server_url) + strlen(payload->remote_name) + 2; - MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name); - payload->handle = handle; - payload->allow_resume = 1; - - ret = _alpm_download(payload, cachedir, NULL); - if(ret != -1) { - break; - } - FREE(payload->fileurl); - payload->unlink_on_fail = 0; - } - if(ret == -1) { - errors++; - _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files from %s\n"), - current->treename); - } + EVENT(handle, ALPM_EVENT_RETRIEVE_START, NULL, NULL); + for(i = files; i; i = i->next) { + if(download_single_file(handle, i->data, cachedir) == -1) { + errors++; + _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n")); } - - alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset); - FREELIST(files); } } - for(j = handle->trans->add; j; j = j->next) { - alpm_pkg_t *pkg = j->data; +finish: + if(files) { + alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset); + FREELIST(files); + } + + for(i = handle->trans->add; i; i = i->next) { + alpm_pkg_t *pkg = i->data; pkg->infolevel &= ~INFRQ_DSIZE; pkg->download_size = 0; } @@ -934,7 +977,8 @@ static int check_validity(alpm_handle_t *handle, char *path; alpm_siglist_t *siglist; alpm_siglevel_t level; - enum _alpm_errno_t error; + alpm_pkgvalidation_t validation; + alpm_errno_t error; }; size_t current = 0, current_bytes = 0; alpm_list_t *i, *errors = NULL; @@ -943,12 +987,12 @@ static int check_validity(alpm_handle_t *handle, EVENT(handle, ALPM_EVENT_INTEGRITY_START, NULL, NULL); for(i = handle->trans->add; i; i = i->next, current++) { - struct validity v = { i->data, NULL, NULL, 0, 0 }; + struct validity v = { i->data, NULL, NULL, 0, 0, 0 }; int percent = (int)(((double)current_bytes / total_bytes) * 100); PROGRESS(handle, ALPM_PROGRESS_INTEGRITY_START, "", percent, total, current); - if(v.pkg->origin == PKG_FROM_FILE) { + if(v.pkg->origin == ALPM_PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } @@ -957,7 +1001,7 @@ static int check_validity(alpm_handle_t *handle, v.level = alpm_db_get_siglevel(alpm_pkg_get_db(v.pkg)); if(_alpm_pkg_validate_internal(handle, v.path, v.pkg, - v.level, &v.siglist) == -1) { + v.level, &v.siglist, &v.validation) == -1) { v.error = handle->pm_errno; struct validity *invalid = malloc(sizeof(struct validity)); memcpy(invalid, &v, sizeof(struct validity)); @@ -966,6 +1010,7 @@ static int check_validity(alpm_handle_t *handle, alpm_siglist_cleanup(v.siglist); free(v.siglist); free(v.path); + v.pkg->validation = v.validation; } } @@ -1023,7 +1068,7 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data, PROGRESS(handle, ALPM_PROGRESS_LOAD_START, "", percent, total, current); - if(spkg->origin == PKG_FROM_FILE) { + if(spkg->origin == ALPM_PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } @@ -1045,6 +1090,8 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data, free(filepath); /* copy over the install reason */ pkgfile->reason = spkg->reason; + /* copy over validation method */ + pkgfile->validation = spkg->validation; i->data = pkgfile; /* spkg has been removed from the target list, so we can free the * sync-specific fields */ @@ -1091,7 +1138,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) * realistically if there are small and huge packages involved */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; - if(spkg->origin != PKG_FROM_FILE) { + if(spkg->origin != ALPM_PKG_FROM_FILE) { total_bytes += spkg->size; } total++; @@ -1120,7 +1167,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) trans->state = STATE_COMMITING; /* fileconflict check */ - if(!(trans->flags & ALPM_TRANS_FLAG_FORCE)) { + if(!(trans->flags & (ALPM_TRANS_FLAG_FORCE|ALPM_TRANS_FLAG_DBONLY))) { EVENT(handle, ALPM_EVENT_FILECONFLICTS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n"); @@ -1145,7 +1192,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) _alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space\n"); if(_alpm_check_diskspace(handle) == -1) { - _alpm_log(handle, ALPM_LOG_ERROR, "%s\n", _("not enough free disk space")); + _alpm_log(handle, ALPM_LOG_ERROR, _("not enough free disk space\n")); return -1; } |