diff options
-rw-r--r-- | src/patch.c | 12 | ||||
-rw-r--r-- | src/util.c | 11 | ||||
-rw-r--r-- | src/util.h | 3 | ||||
-rw-r--r-- | tests/preserve-mode-and-timestamp | 17 |
4 files changed, 34 insertions, 9 deletions
diff --git a/src/patch.c b/src/patch.c index d73aaaf..4764e0d 100644 --- a/src/patch.c +++ b/src/patch.c @@ -471,7 +471,7 @@ main (int argc, char **argv) if (failed < hunk || diff_type == ED_DIFF || set_mode || pch_copy () || pch_rename ()) { - enum file_attributes attr = FA_IDS | FA_MODE; + enum file_attributes attr = 0; struct timespec new_time = pch_timestamp (! reverse); mode_t mode = file_type | ((new_mode ? new_mode : instat.st_mode) & S_IRWXUGO); @@ -496,9 +496,15 @@ main (int argc, char **argv) attr |= FA_TIMES; } - if (! inerrno) - set_file_attributes (TMPOUTNAME, attr, inname, &instat, + if (inerrno) + set_file_attributes (TMPOUTNAME, attr, NULL, NULL, mode, &new_time); + else + { + attr |= FA_IDS | FA_MODE | FA_XATTRS; + set_file_attributes (TMPOUTNAME, attr, inname, &instat, + mode, &new_time); + } assert (outst.st_size != -1); move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal, &outst, @@ -203,7 +203,7 @@ set_file_attributes (char const *to, enum file_attributes attr, } if (lutimens (to, times) != 0) pfatal ("Failed to set the timestamps of %s %s", - S_ISLNK (st->st_mode) ? "symbolic link" : "file", + S_ISLNK (mode) ? "symbolic link" : "file", quotearg (to)); } if (attr & FA_IDS) @@ -231,11 +231,12 @@ set_file_attributes (char const *to, enum file_attributes attr, && errno != EPERM))) pfatal ("Failed to set the %s of %s %s", (uid == -1) ? "owner" : "owning group", - S_ISLNK (st->st_mode) ? "symbolic link" : "file", + S_ISLNK (mode) ? "symbolic link" : "file", quotearg (to)); } - if (copy_attr (from, to)) - fatal_exit (0); + if (attr & FA_XATTRS) + if (copy_attr (from, to)) + fatal_exit (0); /* FIXME: There may be other attributes to preserve. */ if (attr & FA_MODE) { @@ -248,7 +249,7 @@ set_file_attributes (char const *to, enum file_attributes attr, if (! S_ISLNK (mode) && chmod (to, mode) != 0) #endif pfatal ("Failed to set the permissions of %s %s", - S_ISLNK (st->st_mode) ? "symbolic link" : "file", + S_ISLNK (mode) ? "symbolic link" : "file", quotearg (to)); } } @@ -67,7 +67,8 @@ bool file_already_seen (struct stat const *); enum file_attributes { FA_TIMES = 1, FA_IDS = 2, - FA_MODE = 4 + FA_MODE = 4, + FA_XATTRS = 8 }; void set_file_attributes (char const *, enum file_attributes, char const *, diff --git a/tests/preserve-mode-and-timestamp b/tests/preserve-mode-and-timestamp index 9e27955..855d95c 100644 --- a/tests/preserve-mode-and-timestamp +++ b/tests/preserve-mode-and-timestamp @@ -102,3 +102,20 @@ EOF check 'ls -l f.rej | sed "s,\(..........\).*,\1,"' <<EOF -rw-r----- EOF + +# ============================================================== + +cat > f.diff <<EOF +--- /dev/null ++++ b/f $timestamp2 +@@ -0,0 +1 @@ ++one +EOF + +rm -f f + +check 'patch -p1 --backup --set-utc < f.diff' <<EOF +patching file f +EOF + +ncheck 'test ! \( f -ot f.compare -o f -nt f.compare \) || echo "timstamp differs"' |