summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/add.c
diff options
context:
space:
mode:
authorAndrew Gregory <andrew.gregory.8@gmail.com>2014-10-01 08:26:14 +0200
committerAllan McRae <allan@archlinux.org>2015-01-21 05:27:47 +0100
commit5167160c0cd6007c0ed77534f02f78e5ad04e719 (patch)
tree427df1651e9ae4eb14318261f7dd6bbc00b419bc /lib/libalpm/add.c
parentba0d225d93d4254e08e48b97ca6b55861cc8e54f (diff)
downloadpacman-5167160c0cd6007c0ed77534f02f78e5ad04e719.tar.gz
pacman-5167160c0cd6007c0ed77534f02f78e5ad04e719.tar.xz
extract_single_file: consolidate extraction logic
Also adds checks that the filename does not exceed PATH_MAX. Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
Diffstat (limited to 'lib/libalpm/add.c')
-rw-r--r--lib/libalpm/add.c140
1 files changed, 61 insertions, 79 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 0a63566b..b1245693 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -178,6 +178,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
const char *hash_orig = NULL;
int errors = 0;
struct stat lsbuf;
+ size_t filename_len;
if(*entryname == '.') {
return extract_db_file(handle, archive, entry, newpkg, entryname);
@@ -191,7 +192,12 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
}
/* build the new entryname relative to handle->root */
- snprintf(filename, PATH_MAX, "%s%s", handle->root, entryname);
+ filename_len = snprintf(filename, PATH_MAX, "%s%s", handle->root, entryname);
+ if(filename_len >= PATH_MAX) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("unable to extract %s%s: path too long"), handle->root, entryname);
+ return 1;
+ }
/* if a file is in NoExtract then we never extract it */
if(_alpm_fnmatch_patterns(handle->noextract, entryname) == 0) {
@@ -278,32 +284,56 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
}
}
- if(needbackup) {
- char *checkfile;
- char *hash_local = NULL, *hash_pkg = NULL;
- size_t len;
+ if(notouch || needbackup) {
+ if(filename_len + strlen(".pacnew") >= PATH_MAX) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("unable to extract %s.pacnew: path too long"), filename);
+ return 1;
+ }
+ strcpy(filename + filename_len, ".pacnew");
+ }
- len = strlen(filename) + 10;
- MALLOC(checkfile, len,
- errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
- snprintf(checkfile, len, "%s.pacnew", filename);
+ if(handle->trans->flags & ALPM_TRANS_FLAG_FORCE) {
+ /* if FORCE was used, unlink() each file (whether it's there
+ * or not) before extracting. This prevents the old "Text file busy"
+ * error that crops up if forcing a glibc or pacman upgrade. */
+ unlink(filename);
+ }
- if(perform_extraction(handle, archive, entry, checkfile)) {
- errors++;
- goto needbackup_cleanup;
- }
+ _alpm_log(handle, ALPM_LOG_DEBUG, "extracting %s\n", filename);
+ if(perform_extraction(handle, archive, entry, filename)) {
+ errors++;
+ return errors;
+ }
- hash_local = alpm_compute_md5sum(filename);
- hash_pkg = alpm_compute_md5sum(checkfile);
+ if(backup) {
+ FREE(backup->hash);
+ backup->hash = alpm_compute_md5sum(filename);
+ }
- /* update the md5 hash in newpkg's backup (it will be the new original) */
- if(backup) {
- FREE(backup->hash);
- STRDUP(backup->hash, hash_pkg,
- errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
- }
+ if(notouch) {
+ alpm_event_pacnew_created_t event = {
+ .type = ALPM_EVENT_PACNEW_CREATED,
+ .from_noupgrade = 1,
+ .oldpkg = oldpkg,
+ .newpkg = newpkg,
+ .file = filename
+ };
+ /* "remove" the .pacnew suffix */
+ filename[filename_len] = '\0';
+ EVENT(handle, &event);
+ alpm_logaction(handle, ALPM_CALLER_PREFIX,
+ "warning: %s installed as %s.pacnew\n", filename, filename);
+ } else if(needbackup) {
+ char *hash_local = NULL, *hash_pkg = NULL;
+ char origfile[PATH_MAX] = "";
+
+ strncat(origfile, filename, filename_len);
- _alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", filename);
+ hash_local = alpm_compute_md5sum(origfile);
+ hash_pkg = backup ? backup->hash : alpm_compute_md5sum(filename);
+
+ _alpm_log(handle, ALPM_LOG_DEBUG, "checking hashes for %s\n", origfile);
_alpm_log(handle, ALPM_LOG_DEBUG, "current: %s\n", hash_local);
_alpm_log(handle, ALPM_LOG_DEBUG, "new: %s\n", hash_pkg);
_alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig);
@@ -312,8 +342,8 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
/* local and new files are the same, updating anyway to get
* correct timestamps */
_alpm_log(handle, ALPM_LOG_DEBUG, "action: installing new file: %s\n",
- filename);
- if(try_rename(handle, checkfile, filename)) {
+ origfile);
+ if(try_rename(handle, filename, origfile)) {
errors++;
}
} else if(hash_orig && hash_pkg && strcmp(hash_orig, hash_pkg) == 0) {
@@ -321,13 +351,13 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
* including any user changes */
_alpm_log(handle, ALPM_LOG_DEBUG,
"action: leaving existing file in place\n");
- unlink(checkfile);
+ unlink(filename);
} else if(hash_orig && hash_local && strcmp(hash_orig, hash_local) == 0) {
/* installed file has NOT been changed by user,
* update to the new version */
_alpm_log(handle, ALPM_LOG_DEBUG, "action: installing new file: %s\n",
- filename);
- if(try_rename(handle, checkfile, filename)) {
+ origfile);
+ if(try_rename(handle, filename, origfile)) {
errors++;
}
} else {
@@ -338,67 +368,19 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
.from_noupgrade = 0,
.oldpkg = oldpkg,
.newpkg = newpkg,
- .file = filename
+ .file = origfile
};
_alpm_log(handle, ALPM_LOG_DEBUG,
"action: keeping current file and installing"
" new one with .pacnew ending\n");
EVENT(handle, &event);
alpm_logaction(handle, ALPM_CALLER_PREFIX,
- "warning: %s installed as %s\n", filename, checkfile);
+ "warning: %s installed as %s\n", origfile, filename);
}
-needbackup_cleanup:
- free(checkfile);
free(hash_local);
- free(hash_pkg);
- } else {
- size_t len;
- /* we didn't need a backup */
- if(notouch) {
- /* change the path to a .pacnew extension */
- _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoUpgrade -- skipping\n", filename);
- /* remember len so we can get the old filename back for the event */
- len = strlen(filename);
- strncat(filename, ".pacnew", PATH_MAX - len);
- } else {
- _alpm_log(handle, ALPM_LOG_DEBUG, "extracting %s\n", filename);
- }
-
- if(handle->trans->flags & ALPM_TRANS_FLAG_FORCE) {
- /* if FORCE was used, unlink() each file (whether it's there
- * or not) before extracting. This prevents the old "Text file busy"
- * error that crops up if forcing a glibc or pacman upgrade. */
- unlink(filename);
- }
-
- if(perform_extraction(handle, archive, entry, filename)) {
- /* error */
- errors++;
- return errors;
- }
-
- if(notouch) {
- alpm_event_pacnew_created_t event = {
- .type = ALPM_EVENT_PACNEW_CREATED,
- .from_noupgrade = 1,
- .oldpkg = oldpkg,
- .newpkg = newpkg,
- .file = filename
- };
- /* "remove" the .pacnew suffix */
- filename[len] = '\0';
- EVENT(handle, &event);
- alpm_logaction(handle, ALPM_CALLER_PREFIX,
- "warning: %s installed as %s.pacnew\n", filename, filename);
- /* restore */
- filename[len] = '.';
- }
-
- /* calculate an hash if this is in newpkg's backup */
- if(backup) {
- FREE(backup->hash);
- backup->hash = alpm_compute_md5sum(filename);
+ if(!backup) {
+ free(hash_pkg);
}
}
return errors;