I took a stab at addressing Savannah bug #44102 [1], which pointed out Patch will silently change file permissions, even if the original permissions listed in the diff file do not match the actual permissions on the disk.
While looking into this issue I discovered a second, related issue. The "old mode" field of diff files was always being read in as "0". This meant we were always working with bad data on the starting point of file permissions. I've attempted to fix this. Also, I added a warning so when file permissions do not match "old mode" the user is told. Also, if "--force" is not used, the original file permissions are maintained. Both fixes are in the attached patch. - Jesse 1. https://savannah.gnu.org/bugs/index.php?44102
diff --git a/src/patch.c b/src/patch.c index 3794319..da4872a 100644 --- a/src/patch.c +++ b/src/patch.c @@ -580,7 +580,23 @@ main (int argc, char **argv) struct timespec new_time = pch_timestamp (! reverse); mode_t mode = file_type | ((set_mode ? new_mode : instat.st_mode) & S_IRWXUGO); - + /* If mode is changing and old mode is not + the same as expected in the patch, warn. */ + if ( (old_mode) && (old_mode != instat.st_mode) ) + { + if (! force) + { + say("Warning: original file's permission mode does not " + "match expected mode in patch file. Leaving " + "original mode in place. Use --force to overrule.\n"); + mode = instat.st_mode; + } + else + { + say("Warning: original file's permission mode does not " + "match expected mode in patch file.\n"); + } + } if ((set_time | set_utc) && new_time.tv_sec != -1) { struct timespec old_time = pch_timestamp (reverse); diff --git a/src/pch.c b/src/pch.c index cb54e03..5e81049 100644 --- a/src/pch.c +++ b/src/pch.c @@ -343,8 +343,14 @@ fetchmode (char const *str) } if (*s == '\r') s++; + /* + This check causes old mode to be reset every time. if (*s != '\n') + { + printf("DEBUG resetting mode due to newline\n"); mode = 0; + } + */ /* NOTE: The "diff --git" format always sets the file mode permission bits of symlinks to 0. (On Linux, symlinks actually always have