[pacman-dev] [PATCH] Restore .pacsave file if present
Allan McRae
mcrae_allan at hotmail.com
Sat May 10 11:15:24 EDT 2008
This patch adds the ability to restore file "foo.pacsave" when installing
file "foo". File "foo" is then installed as "foo.pacnew"
I really need help with this one. I am a bit wary of this code given
it is in one of the most essential parts of pacman. Despite the new
pactest failure, I actually had the balls to test this out on my
production system... Using the abs package and the /etc/abs.conf.pacsave
file is restored and /etc/abs.conf.pacnew is created as expected.
TODO: Query users about restore
Remove .paccheck from file name in warning about .pacnew creation
Figure out why pactest upgrade025 now fails
Signed-off-by: Allan McRae <mcrae_allan at hotmail.com>
---
lib/libalpm/add.c | 87 ++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 66 insertions(+), 21 deletions(-)
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 3389893..453d5a7 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -333,6 +333,33 @@ 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, sbuf;
+ int filename_lstat, filename_stat, pacsaverestore = 0;
+
+ char pacsavefile[PATH_MAX];
+ snprintf(pacsavefile, PATH_MAX, "%s.pacsave", filename);
+
+ filename_lstat = _alpm_lstat(filename, &lsbuf);
+ filename_stat = stat(filename, &sbuf);
+ if(filename_lstat != 0 || filename_stat != 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;
+ filename_lstat = _alpm_lstat(filename, &lsbuf);
+ filename_stat = stat(filename, &sbuf);
+ }
+ }
+ }
+
/* 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:
@@ -354,8 +381,7 @@ static int extract_single_file(struct archive *archive,
*/
/* 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) {
+ if(filename_lstat != 0 || filename_stat != 0) {
/* cases 1,2,3: couldn't stat an existing file, skip all backup checks */
} else {
if(S_ISDIR(lsbuf.st_mode) && S_ISDIR(entrymode)) {
@@ -492,31 +518,50 @@ 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);
+ 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)) {
- _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
- filename, newpath, strerror(errno));
- alpm_logaction("error: could not rename %s to %s (%s)\n",
- filename, newpath, strerror(errno));
- errors++;
- } else {
- /* rename the file we extracted to the real name */
- if(rename(checkfile, filename)) {
+ /* move the existing file to the "pacorig" */
+ if(rename(filename, newpath)) {
_alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
- checkfile, filename, strerror(errno));
+ filename, newpath, strerror(errno));
alpm_logaction("error: could not rename %s to %s (%s)\n",
- checkfile, filename, strerror(errno));
+ filename, newpath, strerror(errno));
errors++;
} else {
- _alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);
- alpm_logaction("warning: %s saved as %s\n", filename, newpath);
+ /* rename the file we extracted to the real name */
+ if(rename(checkfile, filename)) {
+ _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
+ checkfile, filename, strerror(errno));
+ alpm_logaction("error: could not rename %s to %s (%s)\n",
+ checkfile, filename, strerror(errno));
+ errors++;
+ } else {
+ _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(rename(checkfile, newpath)) {
+ _alpm_log(PM_LOG_ERROR, _("could not install %s as %s: %s\n"),
+ checkfile, newpath, strerror(errno));
+ alpm_logaction("error: could not install %s as %s: %s\n",
+ checkfile, newpath, strerror(errno));
+ } else {
+ _alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"),
+ checkfile, newpath);
+ alpm_logaction("warning: %s installed as %s\n",
+ checkfile, newpath);
+ }
+ }
}
} else if(hash_orig) {
/* the fun part */
--
1.5.5.1
More information about the pacman-dev
mailing list