Summary: Patch wrongly assumes that rename(from, to) leaves no from file Author: Andreas Gruenbacher %description Patch assumes that after calling the rename(from, to) system call, the from file is removed. If from and to refer to the same file, rename is specified to do nothing and return succeessfully. If a patch.orig file happens to refer to the same inode as the patch file, patch accidentally also modifies to .orig file. The bug can be reproduced like this: | $ cat f | f-old | $ cat f.patch | --- f.old 2003-01-15 01:28:58.000000000 +0100 | +++ f 2003-01-15 01:29:08.000000000 +0100 | @@ -2 +2 @@ | -f-old | +f-new | $ ln f f.orig | $ patch -p0 < f.patch | patching file f | Hunk #1 succeeded at 1 (offset -1 lines). | $ ls -i f f.orig | 712235 f 712235 f.orig The patch checks if the from file still exists after rename(), and sets the needs_removal flag accordingly. %patch --- patch-2.5.4/util.c 1999-08-30 08:20:08.000000000 +0200 +++ patch-2.5.4~rename-same-file-agruen/util.c 2003-01-15 12:56:05.000000000 +0100 @@ -153,7 +153,17 @@ quotearg_n (0, from), quotearg_n (1, to)); if (rename (from, to) == 0) - *from_needs_removal = 0; + { + struct stat from_stat; + + /* rename("x", "y") does nothing and succeeds if + x and y refer to the same file. */ + + if (stat (from, &from_stat) == 0) + *from_needs_removal = 1; + else + *from_needs_removal = 0; + } else { int to_dir_known_to_exist = 0;