[pacman-dev] [PATCH] Save backup files with extension .pacsave.timestamp
Pang Yan Han
pangyanhan at gmail.com
Fri Jul 29 03:03:03 EDT 2011
Teach pacman to save backup files using extension of .pacsave.timestamp
"timestamp" is the time of removal of the backup file. It is in
<year>-<month>-<day>-<HHMMSS> format, where:
- year is either the year with century or a 2 digit number from 00 to 99 (year
without century) if the timestamp string exceeds 20 characters
- month is a 2 digit number from 01 to 12
- day is a 2 digit number from 01 to 31
- HH is a 2 digit number from 00 to 23 representing the hour
- MM and SS are 2 digit numbers from 00 to 59 representing minutes and seconds
respectively
An example of such a pacsave file is /etc/pacman.conf.pacsave.2011-07-29-145035
This addresses FS#24192 (pacman overwrites .pacsave files)
FILE_PACSAVE rule for the test suite is updated to reflect the change in
.pacsave file extension. FILE_PACSAVE rules can be used as per before this patch.
Signed-off-by: Pang Yan Han <pangyanhan at gmail.com>
---
doc/pacman.8.txt | 13 ++++++++++++-
lib/libalpm/remove.c | 20 ++++++++++++++++++--
test/pacman/pmrule.py | 21 +++++++++++++++++++--
3 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index 64b1ff3..d029294 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -54,8 +54,19 @@ Operations
removed, in which case every package in that group will be removed.
Files belonging to the specified package will be deleted, and the
database will be updated. Most configuration files will be saved
- with a '.pacsave' extension unless the '\--nosave' option is used.
+ with a '.pacsave-<timestamp>' extension unless the '\--nosave' option is used.
See <<RO,Remove Options>> below.
++
+'<timestamp>' is the time of removal of the configuration file. It is in
+<year>-<month>-<day>-<HHMMSS> format, where:
++
+ - year is either the year with century or a 2 digit number from 00 to 99
+ (year without century) if the string exceeds 20 characters
+ - month is a 2 digit number from 01 to 12
+ - day is a 2 digit number from 01 to 31
+ - HH is a 2 digit number from 00 to 23 representing the hour
+ - MM and SS are 2 digit numbers from 00 to 59 representing minutes and seconds
+ respectively
*-S, \--sync*::
Synchronize packages. Packages are installed directly from the ftp
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 83c437f..a39a154 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
+#include <time.h>
#include <limits.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -287,7 +288,8 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
}
}
} else {
- /* if the file needs backup and has been modified, back it up to .pacsave */
+ /* if the file needs backup and has been modified, back it up to
+ * .pacsave.YYYY-MM-DD-HHMMSS */
alpm_backup_t *backup = _alpm_needbackup(fileobj->name, info);
if(backup) {
if(nosave) {
@@ -298,7 +300,21 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
FREE(filehash);
if(cmp != 0) {
char newpath[PATH_MAX];
- snprintf(newpath, PATH_MAX, "%s.pacsave", file);
+ char timestr[21];
+ time_t curtime;
+ struct tm tm;
+ size_t ret;
+
+ curtime = time(NULL);
+ localtime_r(&curtime, &tm);
+ ret = strftime(timestr, 21, "%Y-%m-%d-%H%M%S", &tm);
+ if (ret == 0) {
+ /* Year with century can't fit.
+ * So we print year without century (00 to 99) */
+ strftime(timestr, 21, "%y-%m-%d-%H%M%S", &tm);
+ }
+
+ snprintf(newpath, PATH_MAX, "%s.pacsave.%s", file, timestr);
rename(file, newpath);
_alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), file, newpath);
alpm_logaction(handle, "warning: %s saved as %s\n", file, newpath);
diff --git a/test/pacman/pmrule.py b/test/pacman/pmrule.py
index cb7ae88..44cee8a 100644
--- a/test/pacman/pmrule.py
+++ b/test/pacman/pmrule.py
@@ -17,6 +17,7 @@
import os
import stat
+import re
import util
@@ -141,8 +142,24 @@ def check(self, test):
if not os.path.isfile("%s.pacorig" % filename):
success = 0
elif case == "PACSAVE":
- if not os.path.isfile("%s.pacsave" % filename):
- success = 0
+ # pacsave.YYYY-MM-DD-HHMMSS
+ saved_re = re.compile(filename + ".pacsave." + "\d{2,}-\d{2}-\d{2}-\d{6}")
+
+ # Extract directory component of pacsave file
+ dir_ = ""
+ dir_re = re.compile('(.*)/[^/]*')
+ dir_match = dir_re.match(filename)
+ if dir_match is not None:
+ dir_ = dir_match.group(1)
+ dir_ = os.path.join(test.root, dir_)
+
+ success = 0
+ files = os.listdir(dir_)
+ for f in files:
+ fullname = os.path.join(dir_, f)
+ if saved_re.match(fullname):
+ success = 1
+ break
else:
print "FILE rule '%s' not found" % case
success = -1
--
1.7.6.178.g55272
More information about the pacman-dev
mailing list