svn commit: trunk/busybox/editors

vda at busybox.net vda at busybox.net
Mon Mar 24 18:18:04 UTC 2008


Author: vda
Date: 2008-03-24 11:18:03 -0700 (Mon, 24 Mar 2008)
New Revision: 21472

Log:
patch: support for patches without dates and generated with -U1; shrink

function                                             old     new   delta
extract_filename                                       -      92     +92
extract_filename_and_free_line                        70       -     -70
patch_main                                          1096    1009     -87
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 0/1 up/down: 92/-157)           Total: -65 bytes



Modified:
   trunk/busybox/editors/patch.c


Changeset:
Modified: trunk/busybox/editors/patch.c
===================================================================
--- trunk/busybox/editors/patch.c	2008-03-24 16:55:13 UTC (rev 21471)
+++ trunk/busybox/editors/patch.c	2008-03-24 18:18:03 UTC (rev 21472)
@@ -44,23 +44,23 @@
  * returns malloc'ed filename
  * NB: frees 1st argument!
  */
-static char *extract_filename_and_free_line(char *line, int patch_level)
+static char *extract_filename(char *line, int patch_level, const char *pat)
 {
-	char *temp, *filename_start_ptr = line + 4;
+	char *temp = NULL, *filename_start_ptr = line + 4;
 
-	/* Terminate string at end of source filename */
-	temp = strchrnul(filename_start_ptr, '\t');
-	*temp = '\0';
+	if (strncmp(line, pat, 4) == 0) {
+		/* Terminate string at end of source filename */
+		line[strcspn(line,"\t\n\r")] = '\0';
 
-	/* Skip over (patch_level) number of leading directories */
-	while (patch_level--) {
-		temp = strchr(filename_start_ptr, '/');
-		if (!temp)
-			break;
-		filename_start_ptr = temp + 1;
+		/* Skip over (patch_level) number of leading directories */
+		while (patch_level--) {
+			temp = strchr(filename_start_ptr, '/');
+			if (!temp)
+				break;
+			filename_start_ptr = temp + 1;
+		}
+		temp = xstrdup(filename_start_ptr);
 	}
-
-	temp = xstrdup(filename_start_ptr);
 	free(line);
 	return temp;
 }
@@ -100,30 +100,26 @@
 		/* Skip everything upto the "---" marker
 		 * No need to parse the lines "Only in <dir>", and "diff <args>"
 		 */
-		while (strncmp(patch_line, "--- ", 4) != 0) {
-			free(patch_line);
+		do {
+			/* Extract the filename used before the patch was generated */
+			original_filename = extract_filename(patch_line, patch_level, "--- ");
 			patch_line = xmalloc_getline(patch_file);
-			if (!patch_line)
-				bb_error_msg_and_die("invalid patch");
-		}
+			if (!patch_line) goto quit;
+		} while (!original_filename);
 
-		/* Extract the filename used before the patch was generated */
-		original_filename = extract_filename_and_free_line(patch_line, patch_level);
-
-		patch_line = xmalloc_getline(patch_file);
-		if (!patch_line || strncmp(patch_line, "+++ ", 4) != 0)
+		new_filename = extract_filename(patch_line, patch_level, "+++ ");
+		if (!new_filename) {
 			bb_error_msg_and_die("invalid patch");
-		new_filename = extract_filename_and_free_line(patch_line, patch_level);
+		}
 
-		/* Get access rights from the file to be patched, -1 file does not exist */
+		/* Get access rights from the file to be patched */
 		if (stat(new_filename, &saved_stat) != 0) {
-			char *line_ptr;
-			/* Create leading directories */
-			line_ptr = strrchr(new_filename, '/');
-			if (line_ptr) {
-				*line_ptr = '\0';
+			char *slash = strrchr(new_filename, '/');
+			if (slash) {
+				/* Create leading directories */
+				*slash = '\0';
 				bb_make_directory(new_filename, -1, FILEUTILS_RECUR);
-				*line_ptr = '/';
+				*slash = '/';
 			}
 			backup_filename = NULL;
 			saved_stat.st_mode = 0644;
@@ -134,10 +130,16 @@
 		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)) {
-			src_stream = xfopen((strcmp(original_filename, new_filename)) ?
-							    original_filename : backup_filename, "r");
+		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);
@@ -147,16 +149,12 @@
 		while (patch_line) {
 			unsigned count;
 			unsigned src_beg_line;
-			unsigned unused;
-			unsigned hunk_offset_start = 0;
-			smallint hunk_error = 0;
+			unsigned hunk_offset_start;
+			unsigned src_last_line = 1;
 
-			/* This bit should be improved */
-			if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, &unused, &dest_beg_line, &unused) != 4)
-			 && (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, &unused, &dest_beg_line) != 3)
-			 && (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, &dest_beg_line, &unused) != 3)
-			) {
-				/* No more hunks for this file */
+			if ((sscanf(patch_line, "@@ -%d,%d +%d", &src_beg_line, &src_last_line, &dest_beg_line) != 3)
+			 && (sscanf(patch_line, "@@ -%d +%d", &src_beg_line, &dest_beg_line) != 2)
+			) { /* No more hunks for this file */
 				break;
 			}
 			hunk_count++;
@@ -172,14 +170,22 @@
 				dest_cur_line += count;
 				copy_trailing_lines_flag = 1;
 			}
-			hunk_offset_start = src_cur_line;
+			src_last_line += hunk_offset_start = src_cur_line;
 
 			while (1) {
 				free(patch_line);
 			        patch_line = xmalloc_fgets(patch_file);
-				if (patch_line == NULL) break;
-				if ((*patch_line == '-') || (*patch_line == ' ')) {
+				if (patch_line == NULL)
+					break; /* EOF */
+				if ((*patch_line != '-') && (*patch_line != '+')
+				 && (*patch_line != ' ')
+				) {
+					break; /* End of hunk */
+				}
+				if (*patch_line != '+') { /* '-', ' ' or '\n' */
 					char *src_line = NULL;
+					if (src_cur_line == src_last_line)
+						break;
 					if (src_stream) {
 						src_line = xmalloc_fgets(src_stream);
 						if (src_line) {
@@ -188,26 +194,19 @@
 							free(src_line);
 							if (diff) src_line = NULL;
 						}
-						if (!src_line) {
-							bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start);
-							hunk_error = 1;
-							break;
-						}
 					}
-					if (*patch_line == ' ') {
-						fputs(patch_line + 1, dst_stream);
-						dest_cur_line++;
+					if (!src_line) {
+						bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start);
+						bad_hunk_count++;
+						break;
 					}
-				} else if (*patch_line == '+') {
-					fputs(patch_line + 1, dst_stream);
-					dest_cur_line++;
-				} else {
-					break;
+					if (*patch_line == '-') {
+						continue;
+					}
 				}
+				fputs(patch_line + 1, dst_stream);
+				dest_cur_line++;
 			} /* end of while loop handling one hunk */
-			if (hunk_error) {
-				bad_hunk_count++;
-			}
 		} /* end of while loop handling one file */
 
 		/* Cleanup last patched file */
@@ -217,9 +216,7 @@
 		if (src_stream) {
 			fclose(src_stream);
 		}
-		if (dst_stream) {
-			fclose(dst_stream);
-		}
+		fclose(dst_stream);
 		if (bad_hunk_count) {
 			ret = 1;
 			bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count);
@@ -232,11 +229,12 @@
 			if ((dest_cur_line == 0) || (dest_beg_line == 0)) {
 				/* The new patched file is empty, remove it */
 				xunlink(new_filename);
-				if (strcmp(new_filename, original_filename) != 0)
-					xunlink(original_filename);
+				/* original_filename and new_filename may be the same file */
+				unlink(original_filename);
 			}
 		}
 	} /* end of "while there are patch lines" */
+quit:
 
 	/* 0 = SUCCESS
 	 * 1 = Some hunks failed




More information about the busybox-cvs mailing list