>From 8c0ff5764a029e0ebdacec574c553a0683f89d2b Mon Sep 17 00:00:00 2001
From: Allan McRae <mcrae_allan@hotmail.com>
Date: Sun, 13 Jan 2008 22:09:46 +1000
Subject: [PATCH] Restore .pacsave file if present

Restores old <file>.pacsave file if present and <file> is not.  Writes
package file to <file>.pacnew.  Fixes FS#8645.

Signed-off-by: Allan McRae <mcrae_allan@hotmail.com>
---
 lib/libalpm/add.c |   79 +++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 59 insertions(+), 20 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 72b8934..5088178 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -344,6 +344,31 @@ static int extract_single_file(struct archive *archive,
 		return(0);
 	}
 
+	/* if file does not exist, check for a .pacsave file to restore */
+	struct stat lsbuf;
+	int fileabsent, pacsaverestore = 0;
+
+	char pacsavefile[PATH_MAX];
+	snprintf(pacsavefile, PATH_MAX, "%s.pacsave", filename);
+
+	fileabsent = _alpm_lstat(filename, &lsbuf);
+	if(fileabsent != 0) {
+		struct stat pslsbuf;
+		if(_alpm_lstat(pacsavefile, &pslsbuf) == 0) {
+		
+		/* TODO: query or notify about pacsave restore */
+				
+			if(rename(pacsavefile, filename)) {
+				_alpm_log(PM_LOG_ERROR, _("could not rename %s (%s)\n"), pacsavefile, strerror(errno));
+				alpm_logaction("error: could not rename %s (%s)\n", pacsavefile, strerror(errno));
+				errors++;
+			} else {
+				pacsaverestore = 1;
+				fileabsent = _alpm_lstat(filename, &lsbuf);
+			}		
+		}
+	}
+		
 	/* Check for file existence. This is one of the more crucial parts
 	 * to get 'right'. Here are the possibilities, with the filesystem
 	 * on the left and the package on the top:
@@ -363,8 +388,8 @@ static int extract_single_file(struct archive *archive,
 	 *      links, etc.
 	 *  12- skip extraction, dir already exists.
 	 */
-	struct stat lsbuf;
-	if(_alpm_lstat(filename, &lsbuf) != 0) {
+
+	if(fileabsent != 0) {
 		/* cases 1,2,3: couldn't stat an existing file, skip all backup checks */
 	} else {
 		/* do a stat as well, so we can see what symlinks point to */
@@ -508,29 +533,43 @@ static int extract_single_file(struct archive *archive,
 
 		if(!oldpkg) {
 			/* looks like we have a local file that has a different hash as the
-			 * file in the package, move it to a .pacorig */
+			 * file in the package, move it to a .pacorig if it has not been restored
+			 * from a pacsave file, else write the package file to .pacnew*/
 			if(strcmp(hash_local, hash_pkg) != 0) {
-				char newpath[PATH_MAX];
-				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)\n"), filename, strerror(errno));
-					alpm_logaction("error: could not rename %s (%s)\n", filename, strerror(errno));
-					errors++;
-				} else {
-					/* copy the tempfile we extracted to the real path */
-					if(_alpm_copyfile(tempfile, filename)) {
+				if(pacsaverestore == 0) {
+					char newpath[PATH_MAX];
+					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 copy tempfile to %s (%s)\n"), filename, strerror(errno));
-						alpm_logaction("error: could not copy tempfile to %s (%s)\n", filename, strerror(errno));
+						_alpm_log(PM_LOG_ERROR, _("could not rename %s (%s)\n"), filename, strerror(errno));
+						alpm_logaction("error: could not rename %s (%s)\n", filename, strerror(errno));
 						errors++;
 					} else {
-						archive_entry_set_pathname(entry, filename);
-						_alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);
-						alpm_logaction("warning: %s saved as %s\n", filename, 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)\n"), filename, strerror(errno));
+							alpm_logaction("error: could not copy tempfile to %s (%s)\n", filename, strerror(errno));
+							errors++;
+						} else {
+							archive_entry_set_pathname(entry, filename);
+							_alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);
+							alpm_logaction("warning: %s saved as %s\n", filename, newpath);
+						}
 					}
+				} else { /* pacsave file was restored */
+					char newpath[PATH_MAX];
+					_alpm_log(PM_LOG_DEBUG, "action: keeping current file and installing new one with .pacnew ending\n");
+					snprintf(newpath, PATH_MAX, "%s.pacnew", filename);
+					if(_alpm_copyfile(tempfile, newpath)) {
+						_alpm_log(PM_LOG_ERROR, _("could not install %s as %s: %s\n"), filename, newpath, strerror(errno));
+						alpm_logaction("error: could not install %s as %s: %s\n", filename, newpath, strerror(errno));
+					} else {
+						_alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"), filename, newpath);
+						alpm_logaction("warning: %s installed as %s\n", filename, newpath);
+					}				
 				}
 			}
 		} else if(hash_orig) {
-- 
1.5.3.7

