summaryrefslogtreecommitdiff
path: root/lib/libalpm/add.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/add.c')
-rw-r--r--lib/libalpm/add.c173
1 files changed, 74 insertions, 99 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 3ef81e37..c20e7c61 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -197,30 +197,25 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
* to get 'right'. Here are the possibilities, with the filesystem
* on the left and the package on the top:
* (F=file, N=node, S=symlink, D=dir)
- * | F/N | S | D
- * non-existent | 1 | 2 | 3
- * F/N | 4 | 5 | 6
- * S | 7 | 8 | 9
- * D | 10 | 11 | 12
+ * | F/N | D
+ * non-existent | 1 | 2
+ * F/N | 3 | 4
+ * D | 5 | 6
*
- * 1,2,3- extract, no magic necessary. lstat (_alpm_lstat) will fail here.
- * 4,5,6,7,8- conflict checks should have caught this. either overwrite
+ * 1,2- extract, no magic necessary. lstat (_alpm_lstat) will fail here.
+ * 3,4- conflict checks should have caught this. either overwrite
* or backup the file.
- * 9- follow the symlink, hopefully it is a directory, check it.
- * 10- file replacing directory- don't allow it.
- * 11- don't extract symlink- a dir exists here. we don't want links to
- * links, etc.
- * 12- skip extraction, dir already exists.
+ * 5- file replacing directory- don't allow it.
+ * 6- skip extraction, dir already exists.
*/
- /* do both a lstat and a stat, so we can see what symlinks point to */
- struct stat lsbuf, sbuf;
- if(_alpm_lstat(filename, &lsbuf) != 0 || stat(filename, &sbuf) != 0) {
- /* cases 1,2,3: couldn't stat an existing file, skip all backup checks */
+ struct stat lsbuf;
+ if(_alpm_lstat(filename, &lsbuf) != 0) {
+ /* cases 1,2: file doesn't exist, skip all backup checks */
} else {
if(S_ISDIR(lsbuf.st_mode)) {
if(S_ISDIR(entrymode)) {
- /* case 12: existing dir, ignore it */
+ /* case 6: existing dir, ignore it */
if(lsbuf.st_mode != entrymode) {
/* if filesystem perms are different than pkg perms, warn user */
mode_t mask = 07777;
@@ -237,33 +232,18 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
archive_read_data_skip(archive);
return 0;
} else {
- /* case 10/11: trying to overwrite dir with file/symlink, don't allow it */
+ /* case 5: trying to overwrite dir with file, don't allow it */
_alpm_log(handle, ALPM_LOG_ERROR, _("extract: not overwriting dir with file %s\n"),
filename);
archive_read_data_skip(archive);
return 1;
}
- } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(entrymode)) {
- /* case 9: existing symlink, dir in package */
- if(S_ISDIR(sbuf.st_mode)) {
- /* the symlink on FS is to a directory, so we'll use it */
- _alpm_log(handle, ALPM_LOG_DEBUG, "extract: skipping symlink overwrite of %s\n",
- filename);
- archive_read_data_skip(archive);
- return 0;
- } else {
- /* this is BAD. symlink was not to a directory */
- _alpm_log(handle, ALPM_LOG_ERROR, _("extract: symlink %s does not point to dir\n"),
- filename);
- archive_read_data_skip(archive);
- return 1;
- }
- } else if(S_ISREG(lsbuf.st_mode) && S_ISDIR(entrymode)) {
- /* case 6: trying to overwrite file with dir */
+ } else if(S_ISDIR(entrymode)) {
+ /* case 4: trying to overwrite file with dir */
_alpm_log(handle, ALPM_LOG_DEBUG, "extract: overwriting file with dir %s\n",
filename);
- } else if(S_ISREG(entrymode)) {
- /* case 4,7: */
+ } else {
+ /* case 3: */
/* if file is in NoUpgrade, don't touch it */
if(alpm_list_find(handle->noupgrade, entryname, _alpm_fnmatch)) {
notouch = 1;
@@ -273,8 +253,6 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
/* check newpkg first, so that adding backup files is retroactive */
backup = _alpm_needbackup(entryname, newpkg);
if(backup) {
- /* if we force hash_orig to be non-NULL retroactive backup works */
- hash_orig = "";
needbackup = 1;
}
@@ -288,8 +266,6 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
}
}
}
- /* else if(S_ISLNK(entrymode)) */
- /* case 5,8: don't need to do anything special */
}
/* we need access to the original entryname later after calls to
@@ -332,81 +308,80 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
_alpm_log(handle, ALPM_LOG_DEBUG, "new: %s\n", hash_pkg);
_alpm_log(handle, ALPM_LOG_DEBUG, "original: %s\n", hash_orig);
- if(!oldpkg) {
- if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) != 0) {
- /* looks like we have a local file that has a different hash as the
- * file in the package, move it to a .pacorig */
+ if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) == 0) {
+ /* local and new files are the same, no sense in installing the file
+ * over itself, regardless of what the original file was */
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "action: leaving existing file in place\n");
+ unlink(checkfile);
+ } else if(hash_orig && hash_pkg && strcmp(hash_orig, hash_pkg) == 0) {
+ /* original and new files are the same, leave the local version alone,
+ * including any user changes */
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "action: leaving existing file in place\n");
+ unlink(checkfile);
+ } 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",
+ entryname_orig);
+ if(try_rename(handle, checkfile, filename)) {
+ errors++;
+ }
+ } else {
+ /* none of the three files matched another, unpack the new file alongside
+ * the local file */
+
+ if(oldpkg) {
+ char *newpath;
+ size_t newlen = strlen(filename) + strlen(".pacnew") + 1;
+
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "action: keeping current file and installing"
+ " new one with .pacnew ending\n");
+
+ MALLOC(newpath, newlen,
+ errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
+ snprintf(newpath, newlen, "%s.pacnew", filename);
+
+ if(try_rename(handle, checkfile, newpath)) {
+ errors++;
+ } else {
+ _alpm_log(handle, ALPM_LOG_WARNING, _("%s installed as %s\n"),
+ filename, newpath);
+ alpm_logaction(handle, ALPM_CALLER_PREFIX,
+ "warning: %s installed as %s\n", filename, newpath);
+ }
+
+ free(newpath);
+ } else {
char *newpath;
- size_t newlen = strlen(filename) + 9;
+ size_t newlen = strlen(filename) + strlen(".pacorig") + 1;
+
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "action: saving existing file with a .pacorig ending"
+ " and installing a new one\n");
+
MALLOC(newpath, newlen,
errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
snprintf(newpath, newlen, "%s.pacorig", filename);
/* move the existing file to the "pacorig" */
if(try_rename(handle, filename, newpath)) {
- errors++;
- errors++;
+ errors++; /* failed rename filename -> filename.pacorig */
+ errors++; /* failed rename checkfile -> filename */
} else {
/* rename the file we extracted to the real name */
if(try_rename(handle, checkfile, filename)) {
errors++;
} else {
- _alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);
+ _alpm_log(handle, ALPM_LOG_WARNING,
+ _("%s saved as %s\n"), filename, newpath);
alpm_logaction(handle, ALPM_CALLER_PREFIX,
"warning: %s saved as %s\n", filename, newpath);
}
}
- free(newpath);
- } else {
- /* local file is identical to pkg one, so just remove pkg one */
- unlink(checkfile);
- }
- } else if(hash_orig) {
- /* the fun part */
-
- if(hash_local && strcmp(hash_orig, hash_local) == 0) {
- /* installed file has NOT been changed by user */
- if(hash_pkg && strcmp(hash_orig, hash_pkg) != 0) {
- _alpm_log(handle, ALPM_LOG_DEBUG, "action: installing new file: %s\n",
- entryname_orig);
- if(try_rename(handle, checkfile, filename)) {
- errors++;
- }
- } else {
- /* no sense in installing the same file twice, install
- * ONLY if the original and package hashes differ */
- _alpm_log(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n");
- unlink(checkfile);
- }
- } else if(hash_pkg && 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(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n");
- unlink(checkfile);
- } else if(hash_local && hash_pkg && 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(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n");
- unlink(checkfile);
- } else {
- char *newpath;
- size_t newlen = strlen(filename) + 8;
- _alpm_log(handle, ALPM_LOG_DEBUG, "action: keeping current file and installing"
- " new one with .pacnew ending\n");
- MALLOC(newpath, newlen,
- errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
- snprintf(newpath, newlen, "%s.pacnew", filename);
- if(try_rename(handle, checkfile, newpath)) {
- errors++;
- } else {
- _alpm_log(handle, ALPM_LOG_WARNING, _("%s installed as %s\n"),
- filename, newpath);
- alpm_logaction(handle, ALPM_CALLER_PREFIX,
- "warning: %s installed as %s\n", filename, newpath);
- }
free(newpath);
}
}