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@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