wok-current rev 498
Busybox: add patch -R
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Mon Mar 24 15:49:00 2008 +0000 (2008-03-24) |
parents | 1b37a413afd5 |
children | 20068c6f5109 |
files | busybox/stuff/busybox-1.10.0-patch.u |
line diff
1.1 --- a/busybox/stuff/busybox-1.10.0-patch.u Sun Mar 23 20:55:19 2008 +0100 1.2 +++ b/busybox/stuff/busybox-1.10.0-patch.u Mon Mar 24 15:49:00 2008 +0000 1.3 @@ -1,11 +1,15 @@ 1.4 ---- busybox-1.10.0/editors/patch.c Sat Mar 22 02:31:52 2008 1.5 -+++ busybox-1.10.0/editors/patch.c Sat Mar 22 02:31:52 2008 1.6 -@@ -23,11 +23,9 @@ 1.7 +--- busybox-1.10.0/editors/patch.c 2008-03-24 15:46:20.000000000 +0100 1.8 ++++ busybox-1.10.0/editors/patch.c 2008-03-24 15:46:20.000000000 +0100 1.9 +@@ -19,15 +19,11 @@ 1.10 + * - Reject file isnt saved 1.11 + */ 1.12 1.13 +-#include <getopt.h> 1.14 +- 1.15 #include "libbb.h" 1.16 1.17 -static unsigned int copy_lines(FILE *src_stream, FILE *dest_stream, const unsigned int lines_count) 1.18 -+static unsigned int copy_lines(FILE *src_stream, FILE *dest_stream, unsigned int lines_count) 1.19 ++static unsigned copy_lines(FILE *src_stream, FILE *dest_stream, unsigned lines_count) 1.20 { 1.21 - unsigned int i = 0; 1.22 - 1.23 @@ -14,10 +18,11 @@ 1.24 char *line; 1.25 line = xmalloc_fgets(src_stream); 1.26 if (line == NULL) { 1.27 -@@ -38,9 +36,9 @@ 1.28 +@@ -37,60 +33,70 @@ 1.29 + bb_perror_msg_and_die("error writing to new file"); 1.30 } 1.31 free(line); 1.32 - 1.33 +- 1.34 - i++; 1.35 + lines_count--; 1.36 } 1.37 @@ -26,82 +31,162 @@ 1.38 } 1.39 1.40 /* If patch_level is -1 it will remove all directory names 1.41 -@@ -49,26 +47,24 @@ 1.42 + * char *line must be greater than 4 chars 1.43 + * returns NULL if the file doesnt exist or error 1.44 * returns malloc'ed filename 1.45 ++ * NB: frees 1st argument! 1.46 */ 1.47 1.48 -static char *extract_filename(char *line, int patch_level) 1.49 -+static char *extract_filename(char *line, unsigned int patch_level) 1.50 ++static char *extract_filename(char *line, unsigned patch_level, const char *pat) 1.51 { 1.52 - char *temp, *filename_start_ptr = line + 4; 1.53 +- char *temp, *filename_start_ptr = line + 4; 1.54 - int i; 1.55 ++ char *temp = NULL, *filename_start_ptr = line + 4; 1.56 1.57 - /* Terminate string at end of source filename */ 1.58 +- /* Terminate string at end of source filename */ 1.59 - temp = strchrnul(filename_start_ptr, '\t'); 1.60 - *temp = '\0'; 1.61 -+ line[strcspn(line,"\t\n")] = '\0'; 1.62 - 1.63 - /* Skip over (patch_level) number of leading directories */ 1.64 +- 1.65 +- /* Skip over (patch_level) number of leading directories */ 1.66 - if (patch_level == -1) 1.67 - patch_level = INT_MAX; 1.68 - for (i = 0; i < patch_level; i++) { 1.69 -+ while (patch_level--) { 1.70 - temp = strchr(filename_start_ptr, '/'); 1.71 - if (!temp) 1.72 - break; 1.73 - filename_start_ptr = temp + 1; 1.74 +- temp = strchr(filename_start_ptr, '/'); 1.75 +- if (!temp) 1.76 +- break; 1.77 +- filename_start_ptr = temp + 1; 1.78 ++ if (strncmp(line, pat, 4) == 0) { 1.79 ++ /* Terminate string at end of source filename */ 1.80 ++ line[strcspn(line,"\t\n\r")] = '\0'; 1.81 ++ 1.82 ++ /* Skip over (patch_level) number of leading directories */ 1.83 ++ while (patch_level--) { 1.84 ++ temp = strchr(filename_start_ptr, '/'); 1.85 ++ if (!temp) 1.86 ++ break; 1.87 ++ filename_start_ptr = temp + 1; 1.88 ++ } 1.89 ++ temp = xstrdup(filename_start_ptr); 1.90 } 1.91 - 1.92 +- 1.93 - return xstrdup(filename_start_ptr); 1.94 -+ temp = xstrdup(filename_start_ptr); 1.95 + free(line); 1.96 + return temp; 1.97 } 1.98 1.99 int patch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1.100 -@@ -77,7 +73,7 @@ 1.101 - int patch_level = -1; 1.102 - char *patch_line; 1.103 - int ret; 1.104 + int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) 1.105 + { 1.106 +- int patch_level = -1; 1.107 +- char *patch_line; 1.108 +- int ret; 1.109 - FILE *patch_file = NULL; 1.110 -+ FILE *patch_file = stdin; 1.111 struct stat saved_stat; 1.112 - 1.113 +- 1.114 ++ char *patch_line; 1.115 ++ FILE *patch_file; 1.116 ++ int patch_level; 1.117 ++ int ret = 0; 1.118 ++#define ENABLE_FEATURE_PATCH_REVERSE 1 1.119 ++#if ENABLE_FEATURE_PATCH_REVERSE 1.120 ++ char minus = '-'; 1.121 ++ char plus = '+'; 1.122 ++#else 1.123 ++ const char minus = '-'; 1.124 ++ const char plus = '+'; 1.125 ++#endif 1.126 ++ 1.127 ++ xfunc_error_retval = 2; 1.128 { 1.129 -@@ -87,12 +83,11 @@ 1.130 - patch_level = xatol_range(p, -1, USHRT_MAX); 1.131 - if (ret & 2) { 1.132 - patch_file = xfopen(i, "r"); 1.133 +- char *p, *i; 1.134 +- ret = getopt32(argv, "p:i:", &p, &i); 1.135 +- if (ret & 1) 1.136 +- patch_level = xatol_range(p, -1, USHRT_MAX); 1.137 +- if (ret & 2) { 1.138 +- patch_file = xfopen(i, "r"); 1.139 - } else { 1.140 - patch_file = stdin; 1.141 - } 1.142 - ret = 0; 1.143 +- } 1.144 +- ret = 0; 1.145 ++ const char *p = "-1"; 1.146 ++ const char *i = "-"; /* compat */ 1.147 ++#if ENABLE_FEATURE_PATCH_REVERSE 1.148 ++ if (getopt32(argv, "p:i:R", &p, &i) & 4) { 1.149 ++ minus = '+'; 1.150 ++ plus = '-'; 1.151 ++ } 1.152 ++#else 1.153 ++ getopt32(argv, "p:i:", &p, &i); 1.154 ++#endif 1.155 ++ patch_level = xatoi(p); /* can be negative! */ 1.156 ++ patch_file = xfopen_stdin(i); 1.157 } 1.158 1.159 -+ //xfunc_error_retval = 2; 1.160 patch_line = xmalloc_getline(patch_file); 1.161 - while (patch_line) { 1.162 - FILE *src_stream; 1.163 -@@ -118,17 +113,13 @@ 1.164 +@@ -100,38 +106,38 @@ 1.165 + char *original_filename; 1.166 + char *new_filename; 1.167 + char *backup_filename; 1.168 +- unsigned int src_cur_line = 1; 1.169 +- unsigned int dest_cur_line = 0; 1.170 +- unsigned int dest_beg_line; 1.171 +- unsigned int bad_hunk_count = 0; 1.172 +- unsigned int hunk_count = 0; 1.173 +- char copy_trailing_lines_flag = 0; 1.174 ++ unsigned src_cur_line = 1; 1.175 ++ unsigned dest_cur_line = 0; 1.176 ++ unsigned dest_beg_line; 1.177 ++ unsigned bad_hunk_count = 0; 1.178 ++ unsigned hunk_count = 0; 1.179 ++ smallint copy_trailing_lines_flag = 0; 1.180 1.181 - /* Extract the filename used before the patch was generated */ 1.182 - original_filename = extract_filename(patch_line, patch_level); 1.183 + /* Skip everything upto the "---" marker 1.184 + * No need to parse the lines "Only in <dir>", and "diff <args>" 1.185 + */ 1.186 +- while (patch_line && strncmp(patch_line, "--- ", 4) != 0) { 1.187 +- free(patch_line); 1.188 ++ do { 1.189 ++ /* Extract the filename used before the patch was generated */ 1.190 ++ original_filename = extract_filename(patch_line, patch_level, "--- "); 1.191 + patch_line = xmalloc_getline(patch_file); 1.192 +- } 1.193 +- /* FIXME: patch_line NULL check?? */ 1.194 ++ if (!patch_line) goto quit; 1.195 ++ } while (!original_filename); 1.196 + 1.197 +- /* Extract the filename used before the patch was generated */ 1.198 +- original_filename = extract_filename(patch_line, patch_level); 1.199 - free(patch_line); 1.200 - 1.201 - patch_line = xmalloc_getline(patch_file); 1.202 - /* FIXME: NULL check?? */ 1.203 - if (strncmp(patch_line, "+++ ", 4) != 0) { 1.204 +- 1.205 +- patch_line = xmalloc_getline(patch_file); 1.206 +- /* FIXME: NULL check?? */ 1.207 +- if (strncmp(patch_line, "+++ ", 4) != 0) { 1.208 - ret = 2; 1.209 - bb_error_msg("invalid patch"); 1.210 - continue; 1.211 -+ bb_error_msg_and_die("invalid patch: %s\n",patch_line); 1.212 ++ new_filename = extract_filename(patch_line, patch_level, "+++ "); 1.213 ++ if (!new_filename) { 1.214 ++ bb_error_msg_and_die("invalid patch"); 1.215 ++ } 1.216 ++#if ENABLE_FEATURE_PATCH_REVERSE 1.217 ++ if (plus != '+') { 1.218 ++ /* reverse patch */ 1.219 ++ char *tmp = original_filename; 1.220 ++ original_filename = new_filename; 1.221 ++ new_filename = tmp; 1.222 } 1.223 - new_filename = extract_filename(patch_line, patch_level); 1.224 +- new_filename = extract_filename(patch_line, patch_level); 1.225 - free(patch_line); 1.226 ++#endif 1.227 1.228 /* Get access rights from the file to be patched, -1 file does not exist */ 1.229 - if (stat(new_filename, &saved_stat)) { 1.230 -@@ -140,20 +131,19 @@ 1.231 +- if (stat(new_filename, &saved_stat)) { 1.232 ++ if (stat(new_filename, &saved_stat) != 0) { 1.233 + char *line_ptr; 1.234 + /* Create leading directories */ 1.235 + line_ptr = strrchr(new_filename, '/'); 1.236 +@@ -140,132 +146,137 @@ 1.237 bb_make_directory(new_filename, -1, FILEUTILS_RECUR); 1.238 *line_ptr = '/'; 1.239 } 1.240 @@ -109,54 +194,84 @@ 1.241 backup_filename = NULL; 1.242 + saved_stat.st_mode = 0644; 1.243 } else { 1.244 - backup_filename = xmalloc(strlen(new_filename) + 6); 1.245 - strcpy(backup_filename, new_filename); 1.246 - strcat(backup_filename, ".orig"); 1.247 +- backup_filename = xmalloc(strlen(new_filename) + 6); 1.248 +- strcpy(backup_filename, new_filename); 1.249 +- strcat(backup_filename, ".orig"); 1.250 ++ backup_filename = xasprintf("%s.orig", new_filename); 1.251 xrename(new_filename, backup_filename); 1.252 - dst_stream = xfopen(new_filename, "w"); 1.253 - fchmod(fileno(dst_stream), saved_stat.st_mode); 1.254 } 1.255 - 1.256 +- 1.257 - if ((backup_filename == NULL) || stat(original_filename, &saved_stat)) { 1.258 - src_stream = NULL; 1.259 - } else { 1.260 +- if (strcmp(original_filename, new_filename) == 0) { 1.261 +- src_stream = xfopen(backup_filename, "r"); 1.262 +- } else { 1.263 +- src_stream = xfopen(original_filename, "r"); 1.264 +- } 1.265 + dst_stream = xfopen(new_filename, "w"); 1.266 + fchmod(fileno(dst_stream), saved_stat.st_mode); 1.267 + src_stream = NULL; 1.268 ++ 1.269 + if (backup_filename && !stat(original_filename, &saved_stat)) { 1.270 - if (strcmp(original_filename, new_filename) == 0) { 1.271 - src_stream = xfopen(backup_filename, "r"); 1.272 - } else { 1.273 -@@ -168,54 +158,57 @@ 1.274 ++ src_stream = xfopen((strcmp(original_filename, new_filename)) ? 1.275 ++ original_filename : backup_filename, "r"); 1.276 + } 1.277 + 1.278 + printf("patching file %s\n", new_filename); 1.279 + 1.280 +- /* Handle each hunk */ 1.281 ++ /* Handle all hunks for this file */ 1.282 + patch_line = xmalloc_fgets(patch_file); 1.283 while (patch_line) { 1.284 - unsigned int count; 1.285 - unsigned int src_beg_line; 1.286 -+ unsigned int src_last_line = 1; 1.287 - unsigned int unused; 1.288 - unsigned int hunk_offset_start = 0; 1.289 - int hunk_error = 0; 1.290 - 1.291 - /* This bit should be improved */ 1.292 +- unsigned int count; 1.293 +- unsigned int src_beg_line; 1.294 +- unsigned int unused; 1.295 +- unsigned int hunk_offset_start = 0; 1.296 +- int hunk_error = 0; 1.297 +- 1.298 +- /* This bit should be improved */ 1.299 - if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, &unused, &dest_beg_line, &unused) != 4) && 1.300 - (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, &unused, &dest_beg_line) != 3) && 1.301 - (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, &dest_beg_line, &unused) != 3)) { 1.302 -+ if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, 1.303 -+ &src_last_line, &dest_beg_line, &unused) != 4) && 1.304 -+ (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, 1.305 -+ &src_last_line, &dest_beg_line) != 3) && 1.306 -+ (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, 1.307 -+ &dest_beg_line, &unused) != 3) && 1.308 -+ (sscanf(patch_line, "@@ -%d +%d @@", &src_beg_line, 1.309 -+ &dest_beg_line) != 2)) { 1.310 ++ unsigned count; 1.311 ++ unsigned src_beg_line; 1.312 ++ unsigned hunk_offset_start; 1.313 ++ unsigned src_last_line = 1; 1.314 ++#if ENABLE_FEATURE_PATCH_REVERSE 1.315 ++ unsigned dst_last_line = 1; 1.316 ++ 1.317 ++ if ((sscanf(patch_line, "@@ -%d,%d +%d,%d", &src_beg_line, &src_last_line, &dest_beg_line, &dst_last_line) < 3) && 1.318 ++ (sscanf(patch_line, "@@ -%d +%d,%d", &src_beg_line, &dest_beg_line, &dst_last_line) < 2)) { 1.319 /* No more hunks for this file */ 1.320 break; 1.321 } 1.322 - free(patch_line); 1.323 ++ if (plus != '+') { 1.324 ++ /* reverse patch */ 1.325 ++ unsigned tmp = src_last_line; 1.326 ++ src_last_line = dst_last_line; 1.327 ++ dst_last_line = tmp; 1.328 ++ tmp = src_beg_line; 1.329 ++ src_beg_line = dest_beg_line; 1.330 ++ dest_beg_line = tmp; 1.331 ++ } 1.332 ++#else 1.333 ++ 1.334 ++ if ((sscanf(patch_line, "@@ -%d,%d +%d", &src_beg_line, &src_last_line, &dest_beg_line) != 3) && 1.335 ++ (sscanf(patch_line, "@@ -%d +%d", &src_beg_line, &dest_beg_line) != 2)) { 1.336 ++ /* No more hunks for this file */ 1.337 ++ break; 1.338 ++ } 1.339 ++#endif 1.340 hunk_count++; 1.341 1.342 if (src_beg_line && dest_beg_line) { 1.343 /* Copy unmodified lines upto start of hunk */ 1.344 - /* src_beg_line will be 0 if its a new file */ 1.345 +- /* src_beg_line will be 0 if its a new file */ 1.346 ++ /* src_beg_line will be 0 if it's a new file */ 1.347 count = src_beg_line - src_cur_line; 1.348 - if (copy_lines(src_stream, dst_stream, count) != count) { 1.349 + if (copy_lines(src_stream, dst_stream, count)) { 1.350 @@ -167,11 +282,18 @@ 1.351 copy_trailing_lines_flag = 1; 1.352 } 1.353 - hunk_offset_start = src_cur_line; 1.354 +- 1.355 +- while ((patch_line = xmalloc_fgets(patch_file)) != NULL) { 1.356 +- if ((*patch_line == '-') || (*patch_line == ' ')) { 1.357 + src_last_line += hunk_offset_start = src_cur_line; 1.358 - 1.359 -- while ((patch_line = xmalloc_fgets(patch_file)) != NULL) { 1.360 -+ while (free(patch_line), (patch_line = xmalloc_fgets(patch_file)) != NULL) { 1.361 - if ((*patch_line == '-') || (*patch_line == ' ')) { 1.362 ++#if ENABLE_FEATURE_PATCH_REVERSE 1.363 ++ dst_last_line += dest_cur_line; 1.364 ++#endif 1.365 ++ while (1) { 1.366 ++ free(patch_line); 1.367 ++ patch_line = xmalloc_fgets(patch_file); 1.368 ++ if (patch_line == NULL) break; 1.369 ++ if ((*patch_line == minus) || (*patch_line == ' ')) { 1.370 char *src_line = NULL; 1.371 + if (src_cur_line == src_last_line) break; 1.372 if (src_stream) { 1.373 @@ -184,29 +306,107 @@ 1.374 + int diff = strcmp(src_line, patch_line + 1); 1.375 src_cur_line++; 1.376 + free(src_line); 1.377 -+ if (diff) { 1.378 -+ src_line = NULL; 1.379 -+ } 1.380 ++ if (diff) src_line = NULL; 1.381 } 1.382 - if (strcmp(src_line, patch_line + 1) != 0) { 1.383 -+ if (!src_line) { 1.384 - bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start); 1.385 - hunk_error++; 1.386 +- bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start); 1.387 +- hunk_error++; 1.388 - free(patch_line); 1.389 - /* Probably need to find next hunk, etc... */ 1.390 - /* but for now we just bail out */ 1.391 - patch_line = NULL; 1.392 - break; 1.393 - } 1.394 +- break; 1.395 +- } 1.396 - free(src_line); 1.397 } 1.398 - if (*patch_line == ' ') { 1.399 - fputs(patch_line + 1, dst_stream); 1.400 -@@ -227,7 +220,6 @@ 1.401 - } else { 1.402 +- if (*patch_line == ' ') { 1.403 +- fputs(patch_line + 1, dst_stream); 1.404 +- dest_cur_line++; 1.405 ++ if (!src_line) { 1.406 ++ bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start); 1.407 ++ bad_hunk_count++; 1.408 ++ break; 1.409 + } 1.410 +- } else if (*patch_line == '+') { 1.411 +- fputs(patch_line + 1, dst_stream); 1.412 +- dest_cur_line++; 1.413 +- } else { 1.414 ++ if (*patch_line != ' ') { 1.415 ++ continue; 1.416 ++ } 1.417 ++ } else if (*patch_line != plus) { 1.418 break; 1.419 } 1.420 - free(patch_line); 1.421 +- } 1.422 +- if (hunk_error) { 1.423 +- bad_hunk_count++; 1.424 +- } 1.425 +- } 1.426 ++#if ENABLE_FEATURE_PATCH_REVERSE 1.427 ++ if (dest_cur_line == dst_last_line) break; 1.428 ++#endif 1.429 ++ fputs(patch_line + 1, dst_stream); 1.430 ++ dest_cur_line++; 1.431 ++ } /* end of while loop handling one hunk */ 1.432 ++ } /* end of while loop handling one file */ 1.433 + 1.434 + /* Cleanup last patched file */ 1.435 + if (copy_trailing_lines_flag) { 1.436 +- copy_lines(src_stream, dst_stream, -1); 1.437 ++ copy_lines(src_stream, dst_stream, (unsigned)(-1)); 1.438 + } 1.439 + if (src_stream) { 1.440 + fclose(src_stream); 1.441 + } 1.442 +- if (dst_stream) { 1.443 +- fclose(dst_stream); 1.444 +- } 1.445 ++ fclose(dst_stream); 1.446 + if (bad_hunk_count) { 1.447 +- if (!ret) { 1.448 +- ret = 1; 1.449 +- } 1.450 +- bb_error_msg("%d out of %d hunk FAILED", bad_hunk_count, hunk_count); 1.451 ++ ret = 1; 1.452 ++ bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); 1.453 + } else { 1.454 + /* It worked, we can remove the backup */ 1.455 + if (backup_filename) { 1.456 + unlink(backup_filename); 1.457 ++ free(backup_filename); 1.458 } 1.459 - if (hunk_error) { 1.460 - bad_hunk_count++; 1.461 + if ((dest_cur_line == 0) || (dest_beg_line == 0)) { 1.462 + /* The new patched file is empty, remove it */ 1.463 + xunlink(new_filename); 1.464 +- if (strcmp(new_filename, original_filename) != 0) 1.465 +- xunlink(original_filename); 1.466 ++ /* original_filename and new_filename may be the same file */ 1.467 ++ unlink(original_filename); 1.468 + } 1.469 + } 1.470 +- } 1.471 ++ } /* end of "while there are patch lines" */ 1.472 ++quit: 1.473 + 1.474 + /* 0 = SUCCESS 1.475 + * 1 = Some hunks failed 1.476 +- * 2 = More serious problems 1.477 ++ * 2 = More serious problems (exited earlier) 1.478 + */ 1.479 + return ret; 1.480 + } 1.481 + 1.482 +--- busybox-1.10.0/include/usage.h 2008-03-24 16:20:43.000000000 +0100 1.483 ++++ busybox-1.10.0/include/usage.h 2008-03-24 16:22:06.000000000 +0100 1.484 +@@ -2833,8 +2833,9 @@ 1.485 + ) 1.486 + 1.487 + #define patch_trivial_usage \ 1.488 +- "[-p NUM] [-i DIFF]" 1.489 ++ "[-R] [-p NUM] [-i DIFF]" 1.490 + #define patch_full_usage \ 1.491 ++ " -R Reverse patch\n" \ 1.492 + " -p NUM Strip NUM leading components from file names" \ 1.493 + "\n -i DIFF Read DIFF instead of stdin" \ 1.494 +