# HG changeset patch # User Pascal Bellard # Date 1206373740 0 # Node ID bb8a2bcece7d5b077fd909bfe4380afda4c729bb # Parent 1b37a413afd5ca769ed3947a3bea06371ad76289 Busybox: add patch -R diff -r 1b37a413afd5 -r bb8a2bcece7d busybox/stuff/busybox-1.10.0-patch.u --- a/busybox/stuff/busybox-1.10.0-patch.u Sun Mar 23 20:55:19 2008 +0100 +++ b/busybox/stuff/busybox-1.10.0-patch.u Mon Mar 24 15:49:00 2008 +0000 @@ -1,11 +1,15 @@ ---- busybox-1.10.0/editors/patch.c Sat Mar 22 02:31:52 2008 -+++ busybox-1.10.0/editors/patch.c Sat Mar 22 02:31:52 2008 -@@ -23,11 +23,9 @@ +--- busybox-1.10.0/editors/patch.c 2008-03-24 15:46:20.000000000 +0100 ++++ busybox-1.10.0/editors/patch.c 2008-03-24 15:46:20.000000000 +0100 +@@ -19,15 +19,11 @@ + * - Reject file isnt saved + */ +-#include +- #include "libbb.h" -static unsigned int copy_lines(FILE *src_stream, FILE *dest_stream, const unsigned int lines_count) -+static unsigned int copy_lines(FILE *src_stream, FILE *dest_stream, unsigned int lines_count) ++static unsigned copy_lines(FILE *src_stream, FILE *dest_stream, unsigned lines_count) { - unsigned int i = 0; - @@ -14,10 +18,11 @@ char *line; line = xmalloc_fgets(src_stream); if (line == NULL) { -@@ -38,9 +36,9 @@ +@@ -37,60 +33,70 @@ + bb_perror_msg_and_die("error writing to new file"); } free(line); - +- - i++; + lines_count--; } @@ -26,82 +31,162 @@ } /* If patch_level is -1 it will remove all directory names -@@ -49,26 +47,24 @@ + * char *line must be greater than 4 chars + * returns NULL if the file doesnt exist or error * returns malloc'ed filename ++ * NB: frees 1st argument! */ -static char *extract_filename(char *line, int patch_level) -+static char *extract_filename(char *line, unsigned int patch_level) ++static char *extract_filename(char *line, unsigned patch_level, const char *pat) { - char *temp, *filename_start_ptr = line + 4; +- char *temp, *filename_start_ptr = line + 4; - int i; ++ char *temp = NULL, *filename_start_ptr = line + 4; - /* Terminate string at end of source filename */ +- /* Terminate string at end of source filename */ - temp = strchrnul(filename_start_ptr, '\t'); - *temp = '\0'; -+ line[strcspn(line,"\t\n")] = '\0'; - - /* Skip over (patch_level) number of leading directories */ +- +- /* Skip over (patch_level) number of leading directories */ - if (patch_level == -1) - patch_level = INT_MAX; - for (i = 0; i < patch_level; i++) { -+ while (patch_level--) { - temp = strchr(filename_start_ptr, '/'); - if (!temp) - break; - filename_start_ptr = temp + 1; +- temp = strchr(filename_start_ptr, '/'); +- if (!temp) +- break; +- filename_start_ptr = temp + 1; ++ 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; ++ } ++ temp = xstrdup(filename_start_ptr); } - +- - return xstrdup(filename_start_ptr); -+ temp = xstrdup(filename_start_ptr); + free(line); + return temp; } int patch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -@@ -77,7 +73,7 @@ - int patch_level = -1; - char *patch_line; - int ret; + int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) + { +- int patch_level = -1; +- char *patch_line; +- int ret; - FILE *patch_file = NULL; -+ FILE *patch_file = stdin; struct stat saved_stat; - +- ++ char *patch_line; ++ FILE *patch_file; ++ int patch_level; ++ int ret = 0; ++#define ENABLE_FEATURE_PATCH_REVERSE 1 ++#if ENABLE_FEATURE_PATCH_REVERSE ++ char minus = '-'; ++ char plus = '+'; ++#else ++ const char minus = '-'; ++ const char plus = '+'; ++#endif ++ ++ xfunc_error_retval = 2; { -@@ -87,12 +83,11 @@ - patch_level = xatol_range(p, -1, USHRT_MAX); - if (ret & 2) { - patch_file = xfopen(i, "r"); +- char *p, *i; +- ret = getopt32(argv, "p:i:", &p, &i); +- if (ret & 1) +- patch_level = xatol_range(p, -1, USHRT_MAX); +- if (ret & 2) { +- patch_file = xfopen(i, "r"); - } else { - patch_file = stdin; - } - ret = 0; +- } +- ret = 0; ++ const char *p = "-1"; ++ const char *i = "-"; /* compat */ ++#if ENABLE_FEATURE_PATCH_REVERSE ++ if (getopt32(argv, "p:i:R", &p, &i) & 4) { ++ minus = '+'; ++ plus = '-'; ++ } ++#else ++ getopt32(argv, "p:i:", &p, &i); ++#endif ++ patch_level = xatoi(p); /* can be negative! */ ++ patch_file = xfopen_stdin(i); } -+ //xfunc_error_retval = 2; patch_line = xmalloc_getline(patch_file); - while (patch_line) { - FILE *src_stream; -@@ -118,17 +113,13 @@ +@@ -100,38 +106,38 @@ + char *original_filename; + char *new_filename; + char *backup_filename; +- unsigned int src_cur_line = 1; +- unsigned int dest_cur_line = 0; +- unsigned int dest_beg_line; +- unsigned int bad_hunk_count = 0; +- unsigned int hunk_count = 0; +- char copy_trailing_lines_flag = 0; ++ unsigned src_cur_line = 1; ++ unsigned dest_cur_line = 0; ++ unsigned dest_beg_line; ++ unsigned bad_hunk_count = 0; ++ unsigned hunk_count = 0; ++ smallint copy_trailing_lines_flag = 0; - /* Extract the filename used before the patch was generated */ - original_filename = extract_filename(patch_line, patch_level); + /* Skip everything upto the "---" marker + * No need to parse the lines "Only in ", and "diff " + */ +- while (patch_line && 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); +- } +- /* FIXME: patch_line NULL check?? */ ++ if (!patch_line) goto quit; ++ } while (!original_filename); + +- /* Extract the filename used before the patch was generated */ +- original_filename = extract_filename(patch_line, patch_level); - free(patch_line); - - patch_line = xmalloc_getline(patch_file); - /* FIXME: NULL check?? */ - if (strncmp(patch_line, "+++ ", 4) != 0) { +- +- patch_line = xmalloc_getline(patch_file); +- /* FIXME: NULL check?? */ +- if (strncmp(patch_line, "+++ ", 4) != 0) { - ret = 2; - bb_error_msg("invalid patch"); - continue; -+ bb_error_msg_and_die("invalid patch: %s\n",patch_line); ++ new_filename = extract_filename(patch_line, patch_level, "+++ "); ++ if (!new_filename) { ++ bb_error_msg_and_die("invalid patch"); ++ } ++#if ENABLE_FEATURE_PATCH_REVERSE ++ if (plus != '+') { ++ /* reverse patch */ ++ char *tmp = original_filename; ++ original_filename = new_filename; ++ new_filename = tmp; } - new_filename = extract_filename(patch_line, patch_level); +- new_filename = extract_filename(patch_line, patch_level); - free(patch_line); ++#endif /* Get access rights from the file to be patched, -1 file does not exist */ - if (stat(new_filename, &saved_stat)) { -@@ -140,20 +131,19 @@ +- if (stat(new_filename, &saved_stat)) { ++ if (stat(new_filename, &saved_stat) != 0) { + char *line_ptr; + /* Create leading directories */ + line_ptr = strrchr(new_filename, '/'); +@@ -140,132 +146,137 @@ bb_make_directory(new_filename, -1, FILEUTILS_RECUR); *line_ptr = '/'; } @@ -109,54 +194,84 @@ backup_filename = NULL; + saved_stat.st_mode = 0644; } else { - backup_filename = xmalloc(strlen(new_filename) + 6); - strcpy(backup_filename, new_filename); - strcat(backup_filename, ".orig"); +- backup_filename = xmalloc(strlen(new_filename) + 6); +- strcpy(backup_filename, new_filename); +- strcat(backup_filename, ".orig"); ++ backup_filename = xasprintf("%s.orig", new_filename); xrename(new_filename, backup_filename); - dst_stream = xfopen(new_filename, "w"); - fchmod(fileno(dst_stream), saved_stat.st_mode); } - +- - if ((backup_filename == NULL) || stat(original_filename, &saved_stat)) { - src_stream = NULL; - } else { +- if (strcmp(original_filename, new_filename) == 0) { +- src_stream = xfopen(backup_filename, "r"); +- } else { +- src_stream = xfopen(original_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)) { - if (strcmp(original_filename, new_filename) == 0) { - src_stream = xfopen(backup_filename, "r"); - } else { -@@ -168,54 +158,57 @@ ++ src_stream = xfopen((strcmp(original_filename, new_filename)) ? ++ original_filename : backup_filename, "r"); + } + + printf("patching file %s\n", new_filename); + +- /* Handle each hunk */ ++ /* Handle all hunks for this file */ + patch_line = xmalloc_fgets(patch_file); while (patch_line) { - unsigned int count; - unsigned int src_beg_line; -+ unsigned int src_last_line = 1; - unsigned int unused; - unsigned int hunk_offset_start = 0; - int hunk_error = 0; - - /* This bit should be improved */ +- unsigned int count; +- unsigned int src_beg_line; +- unsigned int unused; +- unsigned int hunk_offset_start = 0; +- int hunk_error = 0; +- +- /* 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)) { -+ if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, -+ &src_last_line, &dest_beg_line, &unused) != 4) && -+ (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, -+ &src_last_line, &dest_beg_line) != 3) && -+ (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, -+ &dest_beg_line, &unused) != 3) && -+ (sscanf(patch_line, "@@ -%d +%d @@", &src_beg_line, -+ &dest_beg_line) != 2)) { ++ unsigned count; ++ unsigned src_beg_line; ++ unsigned hunk_offset_start; ++ unsigned src_last_line = 1; ++#if ENABLE_FEATURE_PATCH_REVERSE ++ unsigned dst_last_line = 1; ++ ++ if ((sscanf(patch_line, "@@ -%d,%d +%d,%d", &src_beg_line, &src_last_line, &dest_beg_line, &dst_last_line) < 3) && ++ (sscanf(patch_line, "@@ -%d +%d,%d", &src_beg_line, &dest_beg_line, &dst_last_line) < 2)) { /* No more hunks for this file */ break; } - free(patch_line); ++ if (plus != '+') { ++ /* reverse patch */ ++ unsigned tmp = src_last_line; ++ src_last_line = dst_last_line; ++ dst_last_line = tmp; ++ tmp = src_beg_line; ++ src_beg_line = dest_beg_line; ++ dest_beg_line = tmp; ++ } ++#else ++ ++ 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; ++ } ++#endif hunk_count++; if (src_beg_line && dest_beg_line) { /* Copy unmodified lines upto start of hunk */ - /* src_beg_line will be 0 if its a new file */ +- /* src_beg_line will be 0 if its a new file */ ++ /* src_beg_line will be 0 if it's a new file */ count = src_beg_line - src_cur_line; - if (copy_lines(src_stream, dst_stream, count) != count) { + if (copy_lines(src_stream, dst_stream, count)) { @@ -167,11 +282,18 @@ copy_trailing_lines_flag = 1; } - hunk_offset_start = src_cur_line; +- +- while ((patch_line = xmalloc_fgets(patch_file)) != NULL) { +- if ((*patch_line == '-') || (*patch_line == ' ')) { + src_last_line += hunk_offset_start = src_cur_line; - -- while ((patch_line = xmalloc_fgets(patch_file)) != NULL) { -+ while (free(patch_line), (patch_line = xmalloc_fgets(patch_file)) != NULL) { - if ((*patch_line == '-') || (*patch_line == ' ')) { ++#if ENABLE_FEATURE_PATCH_REVERSE ++ dst_last_line += dest_cur_line; ++#endif ++ while (1) { ++ free(patch_line); ++ patch_line = xmalloc_fgets(patch_file); ++ if (patch_line == NULL) break; ++ if ((*patch_line == minus) || (*patch_line == ' ')) { char *src_line = NULL; + if (src_cur_line == src_last_line) break; if (src_stream) { @@ -184,29 +306,107 @@ + int diff = strcmp(src_line, patch_line + 1); src_cur_line++; + free(src_line); -+ if (diff) { -+ src_line = NULL; -+ } ++ if (diff) src_line = NULL; } - if (strcmp(src_line, patch_line + 1) != 0) { -+ if (!src_line) { - bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start); - hunk_error++; +- bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start); +- hunk_error++; - free(patch_line); - /* Probably need to find next hunk, etc... */ - /* but for now we just bail out */ - patch_line = NULL; - break; - } +- break; +- } - free(src_line); } - if (*patch_line == ' ') { - fputs(patch_line + 1, dst_stream); -@@ -227,7 +220,6 @@ - } else { +- 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 { ++ if (*patch_line != ' ') { ++ continue; ++ } ++ } else if (*patch_line != plus) { break; } - free(patch_line); +- } +- if (hunk_error) { +- bad_hunk_count++; +- } +- } ++#if ENABLE_FEATURE_PATCH_REVERSE ++ if (dest_cur_line == dst_last_line) break; ++#endif ++ fputs(patch_line + 1, dst_stream); ++ dest_cur_line++; ++ } /* end of while loop handling one hunk */ ++ } /* end of while loop handling one file */ + + /* Cleanup last patched file */ + if (copy_trailing_lines_flag) { +- copy_lines(src_stream, dst_stream, -1); ++ copy_lines(src_stream, dst_stream, (unsigned)(-1)); + } + if (src_stream) { + fclose(src_stream); + } +- if (dst_stream) { +- fclose(dst_stream); +- } ++ fclose(dst_stream); + if (bad_hunk_count) { +- if (!ret) { +- ret = 1; +- } +- bb_error_msg("%d out of %d hunk FAILED", bad_hunk_count, hunk_count); ++ ret = 1; ++ bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); + } else { + /* It worked, we can remove the backup */ + if (backup_filename) { + unlink(backup_filename); ++ free(backup_filename); } - if (hunk_error) { - bad_hunk_count++; + 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 +- * 2 = More serious problems ++ * 2 = More serious problems (exited earlier) + */ + return ret; + } + +--- busybox-1.10.0/include/usage.h 2008-03-24 16:20:43.000000000 +0100 ++++ busybox-1.10.0/include/usage.h 2008-03-24 16:22:06.000000000 +0100 +@@ -2833,8 +2833,9 @@ + ) + + #define patch_trivial_usage \ +- "[-p NUM] [-i DIFF]" ++ "[-R] [-p NUM] [-i DIFF]" + #define patch_full_usage \ ++ " -R Reverse patch\n" \ + " -p NUM Strip NUM leading components from file names" \ + "\n -i DIFF Read DIFF instead of stdin" \ +