From 92ad5565128d4e6546437b2f28e90cced7c11e03 Mon Sep 17 00:00:00 2001 From: Aaron Griffin Date: Sat, 17 Feb 2007 08:55:05 +0000 Subject: * A whole mess of backup changes - the code should be clearer, more organized, commented, and have worthwhile variable names now - proactive backup=()s now work. That is, adding a file to a backup array does what it should on the upgrade to that package, no longer forcing you to wait a full upgrade cycle for it to take effect * ldconfig was being run twice on an upgrade operation - fixed * fixed another pm_fprintf/printf output corruption with the progress bars * refactored some duplicate code for adjusting 'requiredby' lists * Added config.rpath to .cvsignore --- lib/libalpm/add.c | 670 +++++++++++++++++++++++++----------------------------- 1 file changed, 316 insertions(+), 354 deletions(-) (limited to 'lib/libalpm/add.c') diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 9a683b39..ac53ace9 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -130,8 +130,7 @@ int SYMHIDDEN _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) /* TODO FS#5120 we need a better way to check if a package is a valid package, * and read the metadata instead of relying on the filename for package name - * and version - */ + * and version */ if(stat(name, &buf)) { pm_errno = PM_ERR_NOT_A_FILE; goto error; @@ -352,11 +351,9 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) { int i, ret = 0, errors = 0, pkg_count = 0; - register struct archive *archive; + struct archive *archive; struct archive_entry *entry; - char expath[PATH_MAX], cwd[PATH_MAX] = "", *what; - pmtransprog_t cb_state; - time_t t; + char cwd[PATH_MAX] = ""; alpm_list_t *targ, *lp; ALPM_LOG_FUNC; @@ -371,11 +368,9 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) pkg_count = alpm_list_count(trans->targets); for(targ = trans->packages; targ; targ = targ->next) { - int targ_count = 0; + int targ_count = 0, is_upgrade = 0, use_md5 = 0; double percent = 0.0; - unsigned short pmo_upgrade; - char pm_install[PATH_MAX]; - pmpkg_t *info = (pmpkg_t *)targ->data; + pmpkg_t *newpkg = (pmpkg_t *)targ->data; pmpkg_t *oldpkg = NULL; errors = 0; @@ -383,87 +378,97 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) break; } - pmo_upgrade = (trans->type == PM_TRANS_TYPE_UPGRADE) ? 1 : 0; + /* check if we have a valid sha1sum, if not, use MD5 */ + if(strlen(newpkg->sha1sum) == 0) { + use_md5 = 1; + } /* see if this is an upgrade. if so, remove the old package first */ - if(pmo_upgrade) { - pmpkg_t *local = _alpm_db_get_pkgfromcache(db, info->name); - if(local) { - EVENT(trans, PM_TRANS_EVT_UPGRADE_START, info, NULL); - cb_state = PM_TRANS_PROGRESS_UPGRADE_START; - _alpm_log(PM_LOG_DEBUG, _("upgrading package %s-%s"), info->name, info->version); - if((what = (char *)malloc(strlen(info->name)+1)) == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - STRNCPY(what, info->name, strlen(info->name)+1); - - /* we'll need to save some record for backup checks later */ - oldpkg = _alpm_pkg_new(local->name, local->version); - if(oldpkg) { - oldpkg->backup = alpm_list_strdup(alpm_pkg_get_backup(local)); - strncpy(oldpkg->name, local->name, PKG_NAME_LEN); - strncpy(oldpkg->version, local->version, PKG_VERSION_LEN); - } + pmpkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name); + if(local) { + is_upgrade = 1; + + EVENT(trans, PM_TRANS_EVT_UPGRADE_START, newpkg, NULL); + _alpm_log(PM_LOG_DEBUG, _("upgrading package %s-%s"), newpkg->name, newpkg->version); + + /* we'll need to save some record for backup checks later */ + oldpkg = _alpm_pkg_new(local->name, local->version); + if(oldpkg) { + oldpkg->backup = alpm_list_strdup(alpm_pkg_get_backup(local)); + strncpy(oldpkg->name, local->name, PKG_NAME_LEN); + strncpy(oldpkg->version, local->version, PKG_VERSION_LEN); + } else { + RET_ERR(PM_ERR_MEMORY, -1); + } - /* copy over the install reason */ - info->reason = alpm_pkg_get_reason(local); + /* copy over the install reason */ + newpkg->reason = alpm_pkg_get_reason(local); - /* pre_upgrade scriptlet */ - if(info->scriptlet && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, info->data, "pre_upgrade", info->version, oldpkg ? oldpkg->version : NULL, - trans); - } + /* pre_upgrade scriptlet */ + if(newpkg->scriptlet && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle->root, newpkg->data, "pre_upgrade", newpkg->version, oldpkg->version, trans); + } + } else { + is_upgrade = 0; - if(oldpkg) { - pmtrans_t *tr; - _alpm_log(PM_LOG_DEBUG, _("removing old package first (%s-%s)"), oldpkg->name, oldpkg->version); - tr = _alpm_trans_new(); - if(tr == NULL) { - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - if(_alpm_trans_init(tr, PM_TRANS_TYPE_UPGRADE, trans->flags, NULL, NULL, NULL) == -1) { - FREETRANS(tr); - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - if(_alpm_remove_loadtarget(tr, db, info->name) == -1) { - FREETRANS(tr); - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - /* copy the skiplist over */ - tr->skiplist = alpm_list_strdup(trans->skiplist); - if(_alpm_remove_commit(tr, db) == -1) { - FREETRANS(tr); - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - FREETRANS(tr); - } - } else { - /* no previous package version is installed, so this is actually - * just an install. */ - pmo_upgrade = 0; + EVENT(trans, PM_TRANS_EVT_ADD_START, newpkg, NULL); + _alpm_log(PM_LOG_DEBUG, _("adding package %s-%s"), newpkg->name, newpkg->version); + + /* pre_install scriptlet */ + if(newpkg->scriptlet && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle->root, newpkg->data, "pre_install", newpkg->version, NULL, trans); } } - if(!pmo_upgrade) { - EVENT(trans, PM_TRANS_EVT_ADD_START, info, NULL); - cb_state = PM_TRANS_PROGRESS_ADD_START; - _alpm_log(PM_LOG_DEBUG, _("adding package %s-%s"), info->name, info->version); - if((what = (char *)malloc(strlen(info->name)+1)) == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); + + if(oldpkg) { + /* this is kinda odd. If the old package exists, at this point we make a + * NEW transaction, unrelated to handle->trans, and instantiate a "remove" + * with the type PM_TRANS_TYPE_UPGRADE */ + pmtrans_t *tr = _alpm_trans_new(); + _alpm_log(PM_LOG_DEBUG, _("removing old package first (%s-%s)"), oldpkg->name, oldpkg->version); + + if(!tr) { + RET_ERR(PM_ERR_TRANS_ABORT, -1); } - STRNCPY(what, info->name, strlen(info->name)+1); - /* pre_install scriptlet */ - if(info->scriptlet && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, info->data, "pre_install", info->version, NULL, trans); + if(_alpm_trans_init(tr, PM_TRANS_TYPE_UPGRADE, trans->flags, NULL, NULL, NULL) == -1) { + FREETRANS(tr); + RET_ERR(PM_ERR_TRANS_ABORT, -1); + } + + if(_alpm_remove_loadtarget(tr, db, newpkg->name) == -1) { + FREETRANS(tr); + RET_ERR(PM_ERR_TRANS_ABORT, -1); + } + + /* copy the skiplist over */ + tr->skiplist = alpm_list_strdup(trans->skiplist); + alpm_list_t *b; + + /* Add files in the NEW package's backup array to the noupgrade array + * so this removal operation doesn't kill them */ + alpm_list_t *old_noupgrade = alpm_list_strdup(handle->noupgrade); + for(b = newpkg->backup; b; b = b->next) { + _alpm_log(PM_LOG_DEBUG, _("adding %s to the NoUpgrade array temporarilly"), (char *)b->data); + handle->noupgrade = alpm_list_add(handle->noupgrade, strdup(b->data)); + } + + int ret = _alpm_remove_commit(tr, db); + + FREETRANS(tr); + /* restore our "NoUpgrade" list to previous state */ + alpm_list_free_inner(handle->noupgrade, free); + alpm_list_free(handle->noupgrade); + handle->noupgrade = old_noupgrade; + + if(ret == -1) { + RET_ERR(PM_ERR_TRANS_ABORT, -1); } - } else { - _alpm_log(PM_LOG_DEBUG, _("adding new package %s-%s"), info->name, info->version); } if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) { _alpm_log(PM_LOG_DEBUG, _("extracting files")); - /* Extract the package */ if ((archive = archive_read_new()) == NULL) { RET_ERR(PM_ERR_LIBARCHIVE_ERROR, -1); } @@ -471,14 +476,13 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - if(archive_read_open_file(archive, info->data, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { + if(archive_read_open_file(archive, newpkg->data, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { RET_ERR(PM_ERR_PKG_OPEN, -1); } /* 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")); - /* in case of error, cwd content is undefined: so we set it to something */ cwd[0] = 0; } @@ -487,394 +491,352 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) targ_count = alpm_list_count(targ); /* call PROGRESS once with 0 percent, as we sort-of skip that here */ - PROGRESS(trans, cb_state, what, 0, pkg_count, (pkg_count - targ_count +1)); - - for(i = 0; archive_read_next_header (archive, &entry) == ARCHIVE_OK; i++) { - int nb = 0; - int notouch = 0; - char *md5_orig = NULL; - char *sha1_orig = NULL; - char pathname[PATH_MAX]; + PROGRESS(trans, (is_upgrade ? PM_TRANS_PROGRESS_UPGRADE_START : PM_TRANS_PROGRESS_ADD_START), + newpkg->name, 0, pkg_count, (pkg_count - targ_count +1)); + + for(i = 0; archive_read_next_header(archive, &entry) == ARCHIVE_OK; i++) { + const char *entryname; /* the name of the file in the archive */ + char filename[PATH_MAX]; /* the actual file we're extracting */ + int needbackup = 0, notouch = 0; + char *hash_orig = NULL; struct stat buf; - STRNCPY(pathname, archive_entry_pathname(entry), PATH_MAX); + entryname = archive_entry_pathname(entry); - if(info->size != 0) { - /* Using compressed size for calculations here, as info->isize is not + 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) */ unsigned long pos = archive_position_compressed(archive); - percent = (double)pos / (double)info->size; - _alpm_log(PM_LOG_DEBUG, "decompression progress: %f%% (%ld / %ld)", percent*100.0, pos, info->size); + percent = (double)pos / (double)newpkg->size; + _alpm_log(PM_LOG_DEBUG, "decompression progress: %f%% (%ld / %ld)", percent*100.0, pos, newpkg->size); if(percent >= 1.0) { percent = 1.0; } } - PROGRESS(trans, cb_state, what, (int)(percent * 100), pkg_count, (pkg_count - targ_count +1)); + PROGRESS(trans, (is_upgrade ? PM_TRANS_PROGRESS_UPGRADE_START : PM_TRANS_PROGRESS_ADD_START), + newpkg->name, (int)(percent * 100), pkg_count, (pkg_count - targ_count +1)); - if(strcmp(pathname, ".PKGINFO") == 0 || strcmp(pathname, ".FILELIST") == 0) { - archive_read_data_skip (archive); + memset(filename, 0, PATH_MAX); /* just to be sure */ + + if(strcmp(entryname, ".PKGINFO") == 0 || strcmp(entryname, ".FILELIST") == 0) { + archive_read_data_skip(archive); continue; - } else if(strcmp(pathname, ".INSTALL") == 0) { + } else if(strcmp(entryname, ".INSTALL") == 0) { /* the install script goes inside the db */ - snprintf(expath, PATH_MAX, "%s/%s-%s/install", db->path, - info->name, info->version); - } else if(strcmp(pathname, ".CHANGELOG") == 0) { + snprintf(filename, PATH_MAX, "%s/%s-%s/install", db->path, + newpkg->name, newpkg->version); + } else if(strcmp(entryname, ".CHANGELOG") == 0) { /* the changelog goes inside the db */ - snprintf(expath, PATH_MAX, "%s/%s-%s/changelog", db->path, - info->name, info->version); + snprintf(filename, PATH_MAX, "%s/%s-%s/changelog", db->path, + newpkg->name, newpkg->version); } else { - /* build the new pathname relative to handle->root */ - snprintf(expath, PATH_MAX, "%s%s", handle->root, pathname); + /* build the new entryname relative to handle->root */ + snprintf(filename, PATH_MAX, "%s%s", handle->root, entryname); } - /* if a file is in NoExtract then we never extract it. - * - * eg, /home/httpd/html/index.html may be removed so index.php - * could be used. - */ - if(alpm_list_find_str(handle->noextract, pathname)) { - alpm_logaction(_("notice: %s is in NoExtract -- skipping extraction"), pathname); - archive_read_data_skip (archive); + /* if a file is in NoExtract then we never extract it */ + if(alpm_list_find_str(handle->noextract, entryname)) { + alpm_logaction(_("notice: %s is in NoExtract -- skipping extraction"), entryname); + archive_read_data_skip(archive); continue; } - if(!stat(expath, &buf) && !S_ISDIR(buf.st_mode)) { - /* file already exists */ - if(!pmo_upgrade || oldpkg == NULL) { - nb = alpm_list_find_str(info->backup, pathname); - } else { - /* op == PM_TRANS_TYPE_UPGRADE */ - md5_orig = _alpm_needbackup(pathname, oldpkg->backup); - sha1_orig = _alpm_needbackup(pathname, oldpkg->backup); - if(md5_orig || sha1_orig) { - nb = 1; + /* check is file already exists */ + if(stat(filename, &buf) == 0 && !S_ISDIR(buf.st_mode)) { + /* it does, is it a backup=() file? + * always check the newpkg first, so when we do add a backup=() file, + * we don't have to wait a full upgrade cycle */ + needbackup = alpm_list_find_str(newpkg->backup, entryname); + + if(is_upgrade) { + hash_orig = _alpm_needbackup(entryname, oldpkg->backup); + if(hash_orig) { + needbackup = 1; } } - if(alpm_list_find_str(handle->noupgrade, pathname)) { + + /* this is kind of gross. if we force hash_orig to be non-NULL we can + * catch the pro-active backup=() case (when the backup entry is in + * the new package, and not the old */ + if(needbackup && !hash_orig) { + hash_orig = strdup(""); + } + + /* NoUpgrade skips all this backup stuff, because it's just never + * touched */ + if(alpm_list_find_str(handle->noupgrade, entryname)) { notouch = 1; - nb = 0; + needbackup = 0; } } - if(nb) { - char *temp; - char *md5_local, *md5_pkg; - char *sha1_local, *sha1_pkg; + if(needbackup) { + char *tempfile = NULL; + char *hash_local = NULL, *hash_pkg = NULL; int fd; /* extract the package's version to a temporary file and md5 it */ - temp = strdup("/tmp/alpm_XXXXXX"); - fd = mkstemp(temp); + tempfile = strdup("/tmp/alpm_XXXXXX"); + fd = mkstemp(tempfile); - archive_entry_set_pathname (entry, temp); + archive_entry_set_pathname(entry, tempfile); - if(archive_read_extract (archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) { - alpm_logaction(_("could not extract %s (%s)"), pathname, strerror(errno)); + if(archive_read_extract(archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) { + _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)"), entryname, strerror(errno)); + alpm_logaction(_("could not extract %s (%s)"), entryname, strerror(errno)); errors++; - unlink(temp); - FREE(temp); - FREE(md5_orig); - FREE(sha1_orig); + unlink(tempfile); + FREE(hash_orig); close(fd); continue; } - md5_local = _alpm_MDFile(expath); - md5_pkg = _alpm_MDFile(temp); - sha1_local = _alpm_SHAFile(expath); - sha1_pkg = _alpm_SHAFile(temp); - /* append the new md5 or sha1 hash to it's respective entry in info->backup - * (it will be the new orginal) - */ - for(lp = info->backup; lp; lp = lp->next) { - char *fn; - char *file = lp->data; - - if(!file) continue; - if(!strcmp(file, pathname)) { - if(info->sha1sum != NULL && info->sha1sum != '\0') { - /* 32 for the hash, 1 for the terminating NULL, and 1 for the tab delimiter */ - if((fn = (char *)malloc(strlen(file)+34)) == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - sprintf(fn, "%s\t%s", file, md5_pkg); - FREE(file); - lp->data = fn; - } else { - /* 41 for the hash, 1 for the terminating NULL, and 1 for the tab delimiter */ - if((fn = (char *)malloc(strlen(file)+43)) == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - sprintf(fn, "%s\t%s", file, sha1_pkg); - FREE(file); - lp->data = fn; - } - } + + if(use_md5) { + hash_local = _alpm_MDFile(filename); + hash_pkg = _alpm_MDFile(tempfile); + } else { + hash_local = _alpm_SHAFile(filename); + hash_pkg = _alpm_SHAFile(tempfile); } - if (info->sha1sum != NULL && info->sha1sum != '\0') { - _alpm_log(PM_LOG_DEBUG, _("checking md5 hashes for %s"), pathname); - _alpm_log(PM_LOG_DEBUG, _("current: %s"), md5_local); - _alpm_log(PM_LOG_DEBUG, _("new: %s"), md5_pkg); - if(md5_orig) { - _alpm_log(PM_LOG_DEBUG, _("original: %s"), md5_orig); + /* append the new md5 or sha1 hash to it's respective entry in newpkg->backup + * (it will be the new orginal) */ + for(lp = newpkg->backup; lp; lp = lp->next) { + if(!lp->data || strcmp(lp->data, entryname) != 0) { + continue; } - } else { - _alpm_log(PM_LOG_DEBUG, _("checking sha1 hashes for %s"), pathname); - _alpm_log(PM_LOG_DEBUG, _("current: %s"), sha1_local); - _alpm_log(PM_LOG_DEBUG, _("new: %s"), sha1_pkg); - if(sha1_orig) { - _alpm_log(PM_LOG_DEBUG, _("original: %s"), sha1_orig); + char *backup = NULL; + int backup_len = strlen(lp->data) + 2; /* tab char and null byte */ + + if(use_md5) { + backup_len += 32; /* MD5s are 32 chars in length */ + } else { + backup_len += 40; /* SHA1s are 40 chars in length */ + } + + backup = malloc(backup_len); + if(!backup) { + RET_ERR(PM_ERR_MEMORY, -1); } - } - if(!pmo_upgrade) { - /* PM_ADD */ + sprintf(backup, "%s\t%s", (char *)lp->data, hash_pkg); + backup[backup_len-1] = '\0'; + FREE(lp->data); + lp->data = backup; + } - /* if a file already exists with a different md5 or sha1 hash, - * then we rename it to a .pacorig extension and continue */ - if(strcmp(md5_local, md5_pkg) || strcmp(sha1_local, sha1_pkg)) { + if(use_md5) { + _alpm_log(PM_LOG_DEBUG, _("checking md5 hashes for %s"), entryname); + } else { + _alpm_log(PM_LOG_DEBUG, _("checking sha1 hashes for %s"), entryname); + } + _alpm_log(PM_LOG_DEBUG, _("current: %s"), hash_local); + _alpm_log(PM_LOG_DEBUG, _("new: %s"), hash_pkg); + _alpm_log(PM_LOG_DEBUG, _("original: %s"), hash_orig); + + if(!is_upgrade) { + /* looks like we have a local file that has a different hash as the + * file in the package, move it to a .pacorig */ + if(strcmp(hash_local, hash_pkg) != 0) { char newpath[PATH_MAX]; - snprintf(newpath, PATH_MAX, "%s.pacorig", expath); - if(rename(expath, newpath)) { - archive_entry_set_pathname (entry, expath); - _alpm_log(PM_LOG_ERROR, _("could not rename %s (%s)"), pathname, strerror(errno)); - alpm_logaction(_("error: could not rename %s (%s)"), expath, strerror(errno)); - } - if(_alpm_copyfile(temp, expath)) { - archive_entry_set_pathname (entry, expath); - _alpm_log(PM_LOG_ERROR, _("could not copy %s to %s (%s)"), temp, pathname, strerror(errno)); - alpm_logaction(_("error: could not copy %s to %s (%s)"), temp, expath, strerror(errno)); + snprintf(newpath, PATH_MAX, "%s.pacorig", filename); + + /* move the existing file to the "pacorig" */ + if(rename(filename, newpath)) { + archive_entry_set_pathname(entry, filename); + _alpm_log(PM_LOG_ERROR, _("could not rename %s (%s)"), filename, strerror(errno)); + alpm_logaction(_("error: could not rename %s (%s)"), filename, strerror(errno)); errors++; } else { - archive_entry_set_pathname (entry, expath); - _alpm_log(PM_LOG_WARNING, _("%s saved as %s.pacorig"), pathname, pathname); - alpm_logaction(_("warning: %s saved as %s"), expath, newpath); + /* copy the tempfile we extracted to the real path */ + if(_alpm_copyfile(tempfile, filename)) { + archive_entry_set_pathname(entry, filename); + _alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)"), filename, strerror(errno)); + alpm_logaction(_("error: could not copy tempfile to %s (%s)"), filename, strerror(errno)); + errors++; + } else { + archive_entry_set_pathname(entry, filename); + _alpm_log(PM_LOG_WARNING, _("%s saved as %s.pacorig"), filename, newpath); + alpm_logaction(_("warning: %s saved as %s"), filename, newpath); + } } } - } else if(md5_orig || sha1_pkg) { - /* PM_UPGRADE */ - int installnew = 0; - + } else if(hash_orig) { /* the fun part */ - if(!strcmp(md5_orig, md5_local)|| !strcmp(sha1_orig, sha1_local)) { - if(!strcmp(md5_local, md5_pkg) || !strcmp(sha1_local, sha1_pkg)) { - _alpm_log(PM_LOG_DEBUG, _("action: installing new file")); - installnew = 1; + + if(strcmp(hash_orig, hash_local) == 0) { + /* installed file has NOT been changed by user */ + if(strcmp(hash_orig, hash_pkg) != 0) { + _alpm_log(PM_LOG_DEBUG, _("action: installing new file: %s"), entryname); + + if(_alpm_copyfile(tempfile, filename)) { + _alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)"), filename, strerror(errno)); + errors++; + } + archive_entry_set_pathname(entry, filename); } else { - _alpm_log(PM_LOG_DEBUG, _("action: installing new file")); - installnew = 1; + /* there's no sense in installing the same file twice, install + * ONLY is the original and package hashes differ */ + _alpm_log(PM_LOG_DEBUG, _("action: leaving existing file in place")); } - } else if(!strcmp(md5_orig, md5_pkg) || !strcmp(sha1_orig, sha1_pkg)) { + } else if(strcmp(hash_orig, hash_pkg) == 0) { + /* originally installed file and new file are the same - this + * implies the case above failed - i.e. the file was changed by a + * user */ + _alpm_log(PM_LOG_DEBUG, _("action: leaving existing file in place")); + } else if(strcmp(hash_local, hash_pkg) == 0) { + /* this would be magical. The above two cases failed, but the + * user changes just so happened to make the new file exactly the + * same as the one in the package... skip it */ _alpm_log(PM_LOG_DEBUG, _("action: leaving existing file in place")); - } else if(!strcmp(md5_local, md5_pkg) || !strcmp(sha1_local, sha1_pkg)) { - _alpm_log(PM_LOG_DEBUG, _("action: installing new file")); - installnew = 1; } else { char newpath[PATH_MAX]; _alpm_log(PM_LOG_DEBUG, _("action: keeping current file and installing new one with .pacnew ending")); - installnew = 0; - snprintf(newpath, PATH_MAX, "%s.pacnew", expath); - if(_alpm_copyfile(temp, newpath)) { - _alpm_log(PM_LOG_ERROR, _("could not install %s as %s: %s"), expath, newpath, strerror(errno)); - alpm_logaction(_("error: could not install %s as %s: %s"), expath, newpath, strerror(errno)); + snprintf(newpath, PATH_MAX, "%s.pacnew", filename); + if(_alpm_copyfile(tempfile, newpath)) { + _alpm_log(PM_LOG_ERROR, _("could not install %s as %s: %s"), filename, newpath, strerror(errno)); + alpm_logaction(_("error: could not install %s as %s: %s"), filename, newpath, strerror(errno)); } else { - _alpm_log(PM_LOG_WARNING, _("%s installed as %s"), expath, newpath); - alpm_logaction(_("warning: %s installed as %s"), expath, newpath); + _alpm_log(PM_LOG_WARNING, _("%s installed as %s"), filename, newpath); + alpm_logaction(_("warning: %s installed as %s"), filename, newpath); } } - - if(installnew) { - _alpm_log(PM_LOG_DEBUG, _("extracting %s"), pathname); - if(_alpm_copyfile(temp, expath)) { - _alpm_log(PM_LOG_ERROR, _("could not copy %s to %s (%s)"), temp, pathname, strerror(errno)); - errors++; - } - archive_entry_set_pathname (entry, expath); - } } - FREE(md5_local); - FREE(md5_pkg); - FREE(md5_orig); - FREE(sha1_local); - FREE(sha1_pkg); - FREE(sha1_orig); - unlink(temp); - FREE(temp); + FREE(hash_local); + FREE(hash_pkg); + FREE(hash_orig); + unlink(tempfile); + FREE(tempfile); close(fd); - } else { - if(!notouch) { - _alpm_log(PM_LOG_DEBUG, _("extracting %s"), pathname); + } else { /* ! needbackup */ + + if(notouch) { + _alpm_log(PM_LOG_DEBUG, _("%s is in NoUpgrade -- skipping"), filename); + _alpm_log(PM_LOG_WARNING, _("extracting %s as %s.pacnew"), filename, filename); + alpm_logaction(_("warning: extracting %s as %s.pacnew"), filename, filename); + strncat(filename, ".pacnew", PATH_MAX); } else { - _alpm_log(PM_LOG_DEBUG, _("%s is in NoUpgrade -- skipping"), pathname); - strncat(expath, ".pacnew", PATH_MAX); - _alpm_log(PM_LOG_WARNING, _("extracting %s as %s.pacnew"), pathname, pathname); - alpm_logaction(_("warning: extracting %s%s as %s"), handle->root, pathname, expath); - /*tar_skip_regfile(tar);*/ + _alpm_log(PM_LOG_DEBUG, _("extracting %s"), filename); } + if(trans->flags & PM_TRANS_FLAG_FORCE) { /* if FORCE was used, then unlink() each file (whether it's there * or not) before extracting. this prevents the old "Text file busy" * error that crops up if one tries to --force a glibc or pacman * upgrade. */ - unlink(expath); + unlink(filename); } - archive_entry_set_pathname (entry, expath); - if(archive_read_extract (archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)"), expath, strerror(errno)); - alpm_logaction(_("error: could not extract %s (%s)"), expath, strerror(errno)); + + archive_entry_set_pathname(entry, filename); + + if(archive_read_extract(archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) { + _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)"), filename, strerror(errno)); + alpm_logaction(_("error: could not extract %s (%s)"), filename, strerror(errno)); errors++; } - /* calculate an md5 or sha1 hash if this is in info->backup */ - for(lp = info->backup; lp; lp = lp->next) { - char *fn, *md5, *sha1; - char *file = lp->data; - - if(!file) continue; - if(!strcmp(file, pathname)) { - _alpm_log(PM_LOG_DEBUG, _("appending backup entry")); - if (info->sha1sum != NULL && info->sha1sum != '\0') { - md5 = _alpm_MDFile(expath); - /* 32 for the hash, 1 for the terminating NULL, and 1 for the tab delimiter */ - if((fn = (char *)malloc(strlen(file)+34)) == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - sprintf(fn, "%s\t%s", file, md5); - FREE(md5); - } else { - /* 41 for the hash, 1 for the terminating NULL, and 1 for the tab delimiter */ - sha1 = _alpm_SHAFile(expath); - if((fn = (char *)malloc(strlen(file)+43)) == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - sprintf(fn, "%s\t%s", file, sha1); - FREE(sha1); - } - FREE(file); - lp->data = fn; + + /* calculate an hash if this is in newpkg->backup */ + for(lp = newpkg->backup; lp; lp = lp->next) { + char *backup = NULL, *hash = NULL; + int backup_len = strlen(lp->data) + 2; /* tab char and null byte */ + + if(!lp->data || strcmp(lp->data, entryname) != 0) { + continue; } + _alpm_log(PM_LOG_DEBUG, _("appending backup entry for %s"), filename); + + if(use_md5) { + backup_len += 32; /* MD5s are 32 chars in length */ + hash = _alpm_MDFile(filename); + } else { + backup_len += 40; /* SHA1s are 40 chars in length */ + hash = _alpm_SHAFile(filename); + } + + backup = malloc(backup_len); + if(!backup) { + RET_ERR(PM_ERR_MEMORY, -1); + } + + sprintf(backup, "%s\t%s", (char *)lp->data, hash); + backup[backup_len-1] = '\0'; + FREE(hash); + FREE(lp->data); + lp->data = backup; } } } + archive_read_finish(archive); + + /* restore the old cwd is we have it */ if(strlen(cwd)) { chdir(cwd); } - archive_read_finish (archive); if(errors) { ret = 1; _alpm_log(PM_LOG_ERROR, _("errors occurred while %s %s"), - (pmo_upgrade ? _("upgrading") : _("installing")), info->name); + (is_upgrade ? _("upgrading") : _("installing")), newpkg->name); alpm_logaction(_("errors occurred while %s %s"), - (pmo_upgrade ? _("upgrading") : _("installing")), info->name); + (is_upgrade ? _("upgrading") : _("installing")), newpkg->name); } } - /* Add the package to the database */ - t = time(NULL); - /* Update the requiredby field by scanning the whole database * looking for packages depending on the package to add */ - for(lp = _alpm_db_get_pkgcache(db, INFRQ_DEPENDS); lp; lp = lp->next) { - pmpkg_t *tmpp = lp->data; - alpm_list_t *tmppm = NULL; - if(tmpp == NULL) { - continue; - } - for(tmppm = tmpp->depends; tmppm; tmppm = tmppm->next) { - pmdepend_t depend; - if(_alpm_splitdep(tmppm->data, &depend)) { - continue; - } - if(tmppm->data && !strcmp(depend.name, info->name)) { - _alpm_log(PM_LOG_DEBUG, _("adding '%s' in requiredby field for '%s'"), tmpp->name, info->name); - info->requiredby = alpm_list_add(info->requiredby, strdup(tmpp->name)); - } - } - } + _alpm_pkg_update_requiredby(newpkg); + /* make an install date (in UTC) */ - STRNCPY(info->installdate, asctime(gmtime(&t)), sizeof(info->installdate)); + time_t t = time(NULL); + strncpy(newpkg->installdate, asctime(gmtime(&t)), PKG_DATE_LEN); /* remove the extra line feed appended by asctime() */ - info->installdate[strlen(info->installdate)-1] = 0; + newpkg->installdate[strlen(newpkg->installdate)-1] = 0; _alpm_log(PM_LOG_DEBUG, _("updating database")); - _alpm_log(PM_LOG_DEBUG, _("adding database entry '%s'"), info->name); - if(_alpm_db_write(db, info, INFRQ_ALL)) { + _alpm_log(PM_LOG_DEBUG, _("adding database entry '%s'"), newpkg->name); + + if(_alpm_db_write(db, newpkg, INFRQ_ALL)) { _alpm_log(PM_LOG_ERROR, _("could not update database entry %s-%s"), - info->name, info->version); - alpm_logaction(NULL, _("error updating database for %s-%s!"), info->name, info->version); + newpkg->name, newpkg->version); + alpm_logaction(_("could not update database entry %s-%s"), + newpkg->name, newpkg->version); RET_ERR(PM_ERR_DB_WRITE, -1); } - if(_alpm_db_add_pkgincache(db, info) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not add entry '%s' in cache"), info->name); + + if(_alpm_db_add_pkgincache(db, newpkg) == -1) { + _alpm_log(PM_LOG_ERROR, _("could not add entry '%s' in cache"), newpkg->name); } - /* XXX: This is copy-pasta from remove.c - refactor */ /* update dependency packages' REQUIREDBY fields */ - if(info->depends) { - _alpm_log(PM_LOG_DEBUG, _("updating dependency packages 'requiredby' fields")); - } - for(lp = info->depends; lp; lp = lp->next) { - pmpkg_t *depinfo; - pmdepend_t depend; - if(_alpm_splitdep(lp->data, &depend)) { - continue; - } - depinfo = _alpm_db_get_pkgfromcache(db, depend.name); - if(depinfo == NULL) { - /* look for a provides package */ - alpm_list_t *provides = _alpm_db_whatprovides(db, depend.name); - if(provides) { - /* TODO: should check _all_ packages listed in provides, not just - * the first one. - */ - /* use the first one */ - depinfo = _alpm_db_get_pkgfromcache(db, ((pmpkg_t *)provides->data)->name); - FREELISTPTR(provides); - } - if(depinfo == NULL) { - /* We'll let the front end deal with this case... it may be intentional */ - _alpm_log(PM_LOG_DEBUG, _("could not find dependency '%s'"), depend.name); - continue; - } - } - - /* Ensure package has the right info */ - _alpm_db_read(db, INFRQ_DEPENDS, depinfo); - - _alpm_log(PM_LOG_DEBUG, _("adding '%s' in requiredby field for '%s'"), info->name, depinfo->name); - depinfo->requiredby = alpm_list_add(depinfo->requiredby, strdup(info->name)); - if(_alpm_db_write(db, depinfo, INFRQ_DEPENDS)) { - _alpm_log(PM_LOG_ERROR, _("could not update 'requiredby' database entry %s-%s"), - depinfo->name, depinfo->version); - } - } + _alpm_pkg_update_depends(newpkg, 0 /*is an add*/); - PROGRESS(trans, cb_state, what, 100, pkg_count, (pkg_count - targ_count +1)); + PROGRESS(trans, (is_upgrade ? PM_TRANS_PROGRESS_UPGRADE_START : PM_TRANS_PROGRESS_ADD_START), + newpkg->name, 100, pkg_count, (pkg_count - targ_count +1)); EVENT(trans, PM_TRANS_EVT_EXTRACT_DONE, NULL, NULL); - FREE(what); /* run the post-install script if it exists */ - if(info->scriptlet && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - snprintf(pm_install, PATH_MAX, "%s%s/%s/%s-%s/install", handle->root, handle->dbpath, db->treename, info->name, info->version); - if(pmo_upgrade) { - _alpm_runscriptlet(handle->root, pm_install, "post_upgrade", info->version, oldpkg ? oldpkg->version : NULL, trans); + if(newpkg->scriptlet && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + char pm_install[PATH_MAX]; + snprintf(pm_install, PATH_MAX, "%s%s/%s/%s-%s/install", handle->root, handle->dbpath, db->treename, newpkg->name, newpkg->version); + if(is_upgrade) { + _alpm_runscriptlet(handle->root, pm_install, "post_upgrade", newpkg->version, oldpkg ? oldpkg->version : NULL, trans); } else { - _alpm_runscriptlet(handle->root, pm_install, "post_install", info->version, NULL, trans); + _alpm_runscriptlet(handle->root, pm_install, "post_install", newpkg->version, NULL, trans); } } - EVENT(trans, (pmo_upgrade) ? PM_TRANS_EVT_UPGRADE_DONE : PM_TRANS_EVT_ADD_DONE, info, oldpkg); + EVENT(trans, (is_upgrade) ? PM_TRANS_EVT_UPGRADE_DONE : PM_TRANS_EVT_ADD_DONE, newpkg, oldpkg); FREEPKG(oldpkg); } /* run ldconfig if it exists */ - if(handle->trans->state != STATE_INTERRUPTED) { + if((trans->type != PM_TRANS_TYPE_UPGRADE) && (handle->trans->state != STATE_INTERRUPTED)) { _alpm_log(PM_LOG_DEBUG, _("running \"ldconfig -r %s\""), handle->root); _alpm_ldconfig(handle->root); } -- cgit v1.2.3-54-g00ecf