summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2022-04-06 10:48:35 +0200
committerAndreas Gruenbacher <agruen@gnu.org>2022-05-10 10:53:04 +0200
commitc835ecc67b7e37c0d0b7dd7e032209fdaa285808 (patch)
tree6bb0019a5756498b12c1bdb00657242ba59501af
parent24f81beb27b3ea92bc6bccfca960f93de7f9055d (diff)
downloadpatch-c835ecc67b7e37c0d0b7dd7e032209fdaa285808.tar.gz
Pass the correct stat to backup filesHEADmaster
The last case to call output_file() in the main loop is output_file (outname, NULL, &tmpoutst, NULL, NULL, file_type | 0, backup); and this essentially means to create a backup file (where to=NULL) only if backup=true, and does nothing else. And, in the current code, the passed file stat (&tmpoutst) is a file stat of the temporary file that has been processed, not the original file (outname) to be backed up. When the backup is performed immediately, this is no big problem. However, output_file() may schedule the deferred handling, and the given file may be backed up at a later point. The problem is that create_backup() tries to avoid the backup of the same file twice, and it checks the given stat i-node number in the hash list. Since it's a stat of a temporary file, the same i-node number may be reused once a temp file is deleted and another is created. This results in a false-positive detection of the already existing file, eventually missing a backup file. This patch attempts to address the issue: - Modify the condition for better understanding, clearly indicating that the code there is for creating a backup file - Pass the stat of the original file instead of a temporary file BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1198106 Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jean Delvare <jdelvare@suse.de>
-rw-r--r--src/patch.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/patch.c b/src/patch.c
index 73d140f..d5f456c 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -622,9 +622,16 @@ main (int argc, char **argv)
output_file (NULL, NULL, NULL, inname, &instat,
mode, backup);
}
- else
- output_file (outname, NULL, &tmpoutst, NULL, NULL,
- file_type | 0, backup);
+ else if (backup)
+ {
+ struct stat outstat;
+
+ if (stat_file (outname, &outstat) != 0)
+ say ("Cannot stat file %s, skipping backup\n", outname);
+ else
+ output_file (outname, NULL, &outstat, NULL, NULL,
+ file_type | 0, true);
+ }
}
}
}