patch: fix vda's thinko: we need to open new_filename.orig, always!
plug memory leak; add testsuite

patch_main                                          1009     988     -21

diff --git a/editors/patch.c b/editors/patch.c
index 7b39160..2a2b130 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -87,7 +87,7 @@
 	while (patch_line) {
 		FILE *src_stream;
 		FILE *dst_stream;
-		char *original_filename;
+		//char *old_filename;
 		char *new_filename;
 		char *backup_filename;
 		unsigned src_cur_line = 1;
@@ -102,10 +102,12 @@
 		 */
 		do {
 			/* Extract the filename used before the patch was generated */
-			original_filename = extract_filename(patch_line, patch_level, "--- ");
+			new_filename = extract_filename(patch_line, patch_level, "--- ");
+			// was old_filename above
 			patch_line = xmalloc_getline(patch_file);
 			if (!patch_line) goto quit;
-		} while (!original_filename);
+		} while (!new_filename);
+		free(new_filename); // "source" filename is irrelevant
 
 		new_filename = extract_filename(patch_line, patch_level, "+++ ");
 		if (!new_filename) {
@@ -122,25 +124,15 @@
 				*slash = '/';
 			}
 			backup_filename = NULL;
+			src_stream = NULL;
 			saved_stat.st_mode = 0644;
 		} else {
 			backup_filename = xasprintf("%s.orig", new_filename);
 			xrename(new_filename, backup_filename);
+			src_stream = xfopen(backup_filename, "r");
 		}
 		dst_stream = xfopen(new_filename, "w");
 		fchmod(fileno(dst_stream), saved_stat.st_mode);
-		src_stream = NULL;
-		if (backup_filename && stat(original_filename, &saved_stat) == 0) {
-			// strcmp() is never 0! Otherwise:
-			// original_filename == new_filename,
-			// stat(original_filename) == stat(new_filename),
-			// stat(new_filename) == 0,
-			// but we renamed new_filename if it existed!
-			// stat() must fail!
-			//src_stream = xfopen((strcmp(original_filename, new_filename)) ?
-			//			original_filename : backup_filename, "r");
-			src_stream = xfopen(original_filename, "r");
-		}
 
 		printf("patching file %s\n", new_filename);
 
@@ -224,15 +216,17 @@
 			/* It worked, we can remove the backup */
 			if (backup_filename) {
 				unlink(backup_filename);
-				free(backup_filename);
 			}
 			if ((dest_cur_line == 0) || (dest_beg_line == 0)) {
 				/* The new patched file is empty, remove it */
 				xunlink(new_filename);
-				/* original_filename and new_filename may be the same file */
-				unlink(original_filename);
+				// /* old_filename and new_filename may be the same file */
+				// unlink(old_filename);
 			}
 		}
+		free(backup_filename);
+		//free(old_filename);
+		free(new_filename);
 	} /* end of "while there are patch lines" */
 quit:
 
diff --git a/testsuite/patch.tests b/testsuite/patch.tests
new file mode 100755
index 0000000..8a957d3
--- /dev/null
+++ b/testsuite/patch.tests
@@ -0,0 +1,47 @@
+#!/bin/sh
+# Copyright 2008 by Denys Vlasenko
+# Licensed under GPL v2, see file LICENSE for details.
+
+. testing.sh
+
+# testing "test name" "options" "expected result" "file input" "stdin"
+
+testing "patch with old_file == new_file" \
+	"patch; echo $?; cat input" \
+"\
+patching file input
+0
+qwe
+asd
+zxc
+" \
+	"qwe\nzxc\n" \
+"\
+--- input	Jan 01 01:01:01 2000
++++ input	Jan 01 01:01:01 2000
+@@ -1,2 +1,3 @@
+ qwe
++asd
+ zxc
+" \
+
+testing "patch with nonexistent old_file" \
+	"strace -o zzz patch; echo $?; cat input" \
+"\
+patching file input
+0
+qwe
+asd
+zxc
+" \
+	"qwe\nzxc\n" \
+"\
+--- input.doesnt_exist	Jan 01 01:01:01 2000
++++ input	Jan 01 01:01:01 2000
+@@ -1,2 +1,3 @@
+ qwe
++asd
+ zxc
+" \
+
+exit $FAILCOUNT