diff options
Diffstat (limited to 'lib/libalpm/add.c')
-rw-r--r-- | lib/libalpm/add.c | 131 |
1 files changed, 76 insertions, 55 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index f39a0ecf..d4c56def 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -1,7 +1,7 @@ /* * add.c * - * Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -40,7 +40,6 @@ #include "alpm_list.h" #include "trans.h" #include "util.h" -#include "cache.h" #include "log.h" #include "backup.h" #include "package.h" @@ -54,7 +53,7 @@ * @param target the name of the file target to add * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_add_target(char *target) +int SYMEXPORT alpm_add_target(const char *target) { pmpkg_t *pkg = NULL; const char *pkgname, *pkgver; @@ -110,6 +109,31 @@ error: return(-1); } +static int perform_extraction(struct archive *archive, + struct archive_entry *entry, const char *filename, const char *origname) +{ + int ret; + const int archive_flags = ARCHIVE_EXTRACT_OWNER | + ARCHIVE_EXTRACT_PERM | + ARCHIVE_EXTRACT_TIME; + + archive_entry_set_pathname(entry, filename); + + ret = archive_read_extract(archive, entry, archive_flags); + if(ret == ARCHIVE_WARN && archive_errno(archive) != ENOSPC) { + /* operation succeeded but a "non-critical" error was encountered */ + _alpm_log(PM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), + origname, archive_error_string(archive)); + } else if(ret != ARCHIVE_OK) { + _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), + origname, archive_error_string(archive)); + alpm_logaction("error: could not extract %s (%s)\n", + origname, archive_error_string(archive)); + return(1); + } + return(0); +} + static int extract_single_file(struct archive *archive, struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg, pmtrans_t *trans, pmdb_t *db) @@ -120,9 +144,6 @@ static int extract_single_file(struct archive *archive, int needbackup = 0, notouch = 0; char *hash_orig = NULL; char *entryname_orig = NULL; - const int archive_flags = ARCHIVE_EXTRACT_OWNER | - ARCHIVE_EXTRACT_PERM | - ARCHIVE_EXTRACT_TIME; int errors = 0; entryname = archive_entry_pathname(entry); @@ -277,18 +298,10 @@ static int extract_single_file(struct archive *archive, int ret; snprintf(checkfile, PATH_MAX, "%s.paccheck", filename); - archive_entry_set_pathname(entry, checkfile); - - ret = archive_read_extract(archive, entry, archive_flags); - if(ret == ARCHIVE_WARN) { - /* operation succeeded but a non-critical error was encountered */ - _alpm_log(PM_LOG_DEBUG, "warning extracting %s (%s)\n", - entryname_orig, archive_error_string(archive)); - } else if(ret != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), - entryname_orig, archive_error_string(archive)); - alpm_logaction("error: could not extract %s (%s)\n", - entryname_orig, archive_error_string(archive)); + + ret = perform_extraction(archive, entry, checkfile, entryname_orig); + if(ret == 1) { + /* error */ FREE(hash_orig); FREE(entryname_orig); return(1); @@ -430,18 +443,9 @@ static int extract_single_file(struct archive *archive, unlink(filename); } - archive_entry_set_pathname(entry, filename); - - ret = archive_read_extract(archive, entry, archive_flags); - if(ret == ARCHIVE_WARN) { - /* operation succeeded but a non-critical error was encountered */ - _alpm_log(PM_LOG_DEBUG, "warning extracting %s (%s)\n", - entryname_orig, archive_error_string(archive)); - } else if(ret != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), - entryname_orig, archive_error_string(archive)); - alpm_logaction("error: could not extract %s (%s)\n", - entryname_orig, archive_error_string(archive)); + ret = perform_extraction(archive, entry, filename, entryname_orig); + if(ret == 1) { + /* error */ FREE(entryname_orig); return(1); } @@ -473,8 +477,8 @@ static int extract_single_file(struct archive *archive, return(errors); } -static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, - pmtrans_t *trans, pmdb_t *db) +static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, + size_t pkg_count, pmtrans_t *trans, pmdb_t *db) { int i, ret = 0, errors = 0; char scriptlet[PATH_MAX+1]; @@ -498,7 +502,7 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, oldpkg = _alpm_pkg_dup(local); /* make sure all infos are loaded because the database entry * will be removed soon */ - _alpm_db_read(oldpkg->origin_data.db, oldpkg, INFRQ_ALL); + _alpm_local_db_read(oldpkg->origin_data.db, oldpkg, INFRQ_ALL); EVENT(trans, PM_TRANS_EVT_UPGRADE_START, newpkg, oldpkg); _alpm_log(PM_LOG_DEBUG, "upgrading package %s-%s\n", @@ -544,7 +548,7 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, /* prepare directory for database entries so permission are correct after changelog/install script installation (FS#12263) */ - if(_alpm_db_prepare(db, newpkg)) { + if(_alpm_local_db_prepare(db, newpkg)) { alpm_logaction("error: could not create database entry %s-%s\n", alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); pm_errno = PM_ERR_DB_WRITE; @@ -556,6 +560,7 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, struct archive *archive; struct archive_entry *entry; char cwd[PATH_MAX] = ""; + int restore_cwd = 0; _alpm_log(PM_LOG_DEBUG, "extracting files\n"); @@ -579,11 +584,16 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, /* save the cwd so we can restore it later */ if(getcwd(cwd, PATH_MAX) == NULL) { _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); - cwd[0] = 0; + } else { + restore_cwd = 1; } /* libarchive requires this for extracting hard links */ - chdir(handle->root); + if(chdir(handle->root) != 0) { + _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), handle->root, strerror(errno)); + ret = -1; + goto cleanup; + } /* call PROGRESS once with 0 percent, as we sort-of skip that here */ if(is_upgrade) { @@ -595,31 +605,31 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, } for(i = 0; archive_read_next_header(archive, &entry) == ARCHIVE_OK; i++) { - double percent; + int percent; if(newpkg->size != 0) { /* Using compressed size for calculations here, as newpkg->isize is not * exact when it comes to comparing to the ACTUAL uncompressed size * (missing metadata sizes) */ int64_t pos = archive_position_compressed(archive); - percent = (double)pos / (double)newpkg->size; + percent = (pos * 100) / newpkg->size; _alpm_log(PM_LOG_DEBUG, "decompression progress: " - "%f%% (%"PRId64" / %jd)\n", - percent*100.0, pos, (intmax_t)newpkg->size); - if(percent >= 1.0) { - percent = 1.0; + "%d%% (%"PRId64" / %jd)\n", + percent, pos, (intmax_t)newpkg->size); + if(percent >= 100) { + percent = 100; } } else { - percent = 0.0; + percent = 0; } if(is_upgrade) { PROGRESS(trans, PM_TRANS_PROGRESS_UPGRADE_START, - alpm_pkg_get_name(newpkg), (int)(percent * 100), pkg_count, + alpm_pkg_get_name(newpkg), percent, pkg_count, pkg_current); } else { PROGRESS(trans, PM_TRANS_PROGRESS_ADD_START, - alpm_pkg_get_name(newpkg), (int)(percent * 100), pkg_count, + alpm_pkg_get_name(newpkg), percent, pkg_count, pkg_current); } @@ -629,9 +639,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, } archive_read_finish(archive); - /* restore the old cwd is we have it */ - if(strlen(cwd)) { - chdir(cwd); + /* restore the old cwd if we have it */ + if(restore_cwd && chdir(cwd) != 0) { + _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); } if(errors) { @@ -656,7 +666,7 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, _alpm_log(PM_LOG_DEBUG, "updating database\n"); _alpm_log(PM_LOG_DEBUG, "adding database entry '%s'\n", newpkg->name); - if(_alpm_db_write(db, newpkg, INFRQ_ALL)) { + if(_alpm_local_db_write(db, newpkg, INFRQ_ALL)) { _alpm_log(PM_LOG_ERROR, _("could not update database entry %s-%s\n"), alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); alpm_logaction("error: could not update database entry %s-%s\n", @@ -705,7 +715,8 @@ cleanup: int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) { - int pkg_count, pkg_current; + size_t pkg_count, pkg_current; + int skip_ldconfig = 0, ret = 0; alpm_list_t *targ; ALPM_LOG_FUNC; @@ -723,18 +734,28 @@ int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) /* loop through our package list adding/upgrading one at a time */ for(targ = trans->add; targ; targ = targ->next) { if(handle->trans->state == STATE_INTERRUPTED) { - return(0); + return(ret); } pmpkg_t *newpkg = (pmpkg_t *)targ->data; - commit_single_pkg(newpkg, pkg_current, pkg_count, trans, db); + if(commit_single_pkg(newpkg, pkg_current, pkg_count, trans, db)) { + /* something screwed up on the commit, abort the trans */ + trans->state = STATE_INTERRUPTED; + pm_errno = PM_ERR_TRANS_ABORT; + /* running ldconfig at this point could possibly screw system */ + skip_ldconfig = 1; + ret = -1; + } + pkg_current++; } - /* run ldconfig if it exists */ - _alpm_ldconfig(handle->root); + if(!skip_ldconfig) { + /* run ldconfig if it exists */ + _alpm_ldconfig(handle->root); + } - return(0); + return(ret); } /* vim: set ts=2 sw=2 noet: */ |