diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-24 18:18:03 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-24 18:18:03 +0000 |
| commit | 64a76d7b447eeaf2a50606c04f87cec8ef535efb (patch) | |
| tree | dc3d21b070c99fe9043b4259f27cec4e6ae2f308 | |
| parent | c4c2cd44d2befc5c1153cd54e1ceb93b88fee243 (diff) | |
| download | busybox-w32-64a76d7b447eeaf2a50606c04f87cec8ef535efb.tar.gz busybox-w32-64a76d7b447eeaf2a50606c04f87cec8ef535efb.tar.bz2 busybox-w32-64a76d7b447eeaf2a50606c04f87cec8ef535efb.zip | |
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
| -rw-r--r-- | editors/patch.c | 136 |
1 files changed, 67 insertions, 69 deletions
diff --git a/editors/patch.c b/editors/patch.c index e0fb58f87..7b391603d 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
| @@ -44,23 +44,23 @@ static unsigned copy_lines(FILE *src_stream, FILE *dest_stream, unsigned lines_c | |||
| 44 | * returns malloc'ed filename | 44 | * returns malloc'ed filename |
| 45 | * NB: frees 1st argument! | 45 | * NB: frees 1st argument! |
| 46 | */ | 46 | */ |
| 47 | static char *extract_filename_and_free_line(char *line, int patch_level) | 47 | static char *extract_filename(char *line, int patch_level, const char *pat) |
| 48 | { | 48 | { |
| 49 | char *temp, *filename_start_ptr = line + 4; | 49 | char *temp = NULL, *filename_start_ptr = line + 4; |
| 50 | 50 | ||
| 51 | /* Terminate string at end of source filename */ | 51 | if (strncmp(line, pat, 4) == 0) { |
| 52 | temp = strchrnul(filename_start_ptr, '\t'); | 52 | /* Terminate string at end of source filename */ |
| 53 | *temp = '\0'; | 53 | line[strcspn(line,"\t\n\r")] = '\0'; |
| 54 | 54 | ||
| 55 | /* Skip over (patch_level) number of leading directories */ | 55 | /* Skip over (patch_level) number of leading directories */ |
| 56 | while (patch_level--) { | 56 | while (patch_level--) { |
| 57 | temp = strchr(filename_start_ptr, '/'); | 57 | temp = strchr(filename_start_ptr, '/'); |
| 58 | if (!temp) | 58 | if (!temp) |
| 59 | break; | 59 | break; |
| 60 | filename_start_ptr = temp + 1; | 60 | filename_start_ptr = temp + 1; |
| 61 | } | ||
| 62 | temp = xstrdup(filename_start_ptr); | ||
| 61 | } | 63 | } |
| 62 | |||
| 63 | temp = xstrdup(filename_start_ptr); | ||
| 64 | free(line); | 64 | free(line); |
| 65 | return temp; | 65 | return temp; |
| 66 | } | 66 | } |
| @@ -100,30 +100,26 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 100 | /* Skip everything upto the "---" marker | 100 | /* Skip everything upto the "---" marker |
| 101 | * No need to parse the lines "Only in <dir>", and "diff <args>" | 101 | * No need to parse the lines "Only in <dir>", and "diff <args>" |
| 102 | */ | 102 | */ |
| 103 | while (strncmp(patch_line, "--- ", 4) != 0) { | 103 | do { |
| 104 | free(patch_line); | 104 | /* Extract the filename used before the patch was generated */ |
| 105 | original_filename = extract_filename(patch_line, patch_level, "--- "); | ||
| 105 | patch_line = xmalloc_getline(patch_file); | 106 | patch_line = xmalloc_getline(patch_file); |
| 106 | if (!patch_line) | 107 | if (!patch_line) goto quit; |
| 107 | bb_error_msg_and_die("invalid patch"); | 108 | } while (!original_filename); |
| 108 | } | ||
| 109 | |||
| 110 | /* Extract the filename used before the patch was generated */ | ||
| 111 | original_filename = extract_filename_and_free_line(patch_line, patch_level); | ||
| 112 | 109 | ||
| 113 | patch_line = xmalloc_getline(patch_file); | 110 | new_filename = extract_filename(patch_line, patch_level, "+++ "); |
| 114 | if (!patch_line || strncmp(patch_line, "+++ ", 4) != 0) | 111 | if (!new_filename) { |
| 115 | bb_error_msg_and_die("invalid patch"); | 112 | bb_error_msg_and_die("invalid patch"); |
| 116 | new_filename = extract_filename_and_free_line(patch_line, patch_level); | 113 | } |
| 117 | 114 | ||
| 118 | /* Get access rights from the file to be patched, -1 file does not exist */ | 115 | /* Get access rights from the file to be patched */ |
| 119 | if (stat(new_filename, &saved_stat) != 0) { | 116 | if (stat(new_filename, &saved_stat) != 0) { |
| 120 | char *line_ptr; | 117 | char *slash = strrchr(new_filename, '/'); |
| 121 | /* Create leading directories */ | 118 | if (slash) { |
| 122 | line_ptr = strrchr(new_filename, '/'); | 119 | /* Create leading directories */ |
| 123 | if (line_ptr) { | 120 | *slash = '\0'; |
| 124 | *line_ptr = '\0'; | ||
| 125 | bb_make_directory(new_filename, -1, FILEUTILS_RECUR); | 121 | bb_make_directory(new_filename, -1, FILEUTILS_RECUR); |
| 126 | *line_ptr = '/'; | 122 | *slash = '/'; |
| 127 | } | 123 | } |
| 128 | backup_filename = NULL; | 124 | backup_filename = NULL; |
| 129 | saved_stat.st_mode = 0644; | 125 | saved_stat.st_mode = 0644; |
| @@ -134,10 +130,16 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 134 | dst_stream = xfopen(new_filename, "w"); | 130 | dst_stream = xfopen(new_filename, "w"); |
| 135 | fchmod(fileno(dst_stream), saved_stat.st_mode); | 131 | fchmod(fileno(dst_stream), saved_stat.st_mode); |
| 136 | src_stream = NULL; | 132 | src_stream = NULL; |
| 137 | 133 | if (backup_filename && stat(original_filename, &saved_stat) == 0) { | |
| 138 | if (backup_filename && !stat(original_filename, &saved_stat)) { | 134 | // strcmp() is never 0! Otherwise: |
| 139 | src_stream = xfopen((strcmp(original_filename, new_filename)) ? | 135 | // original_filename == new_filename, |
| 140 | original_filename : backup_filename, "r"); | 136 | // stat(original_filename) == stat(new_filename), |
| 137 | // stat(new_filename) == 0, | ||
| 138 | // but we renamed new_filename if it existed! | ||
| 139 | // stat() must fail! | ||
| 140 | //src_stream = xfopen((strcmp(original_filename, new_filename)) ? | ||
| 141 | // original_filename : backup_filename, "r"); | ||
| 142 | src_stream = xfopen(original_filename, "r"); | ||
| 141 | } | 143 | } |
| 142 | 144 | ||
| 143 | printf("patching file %s\n", new_filename); | 145 | printf("patching file %s\n", new_filename); |
| @@ -147,16 +149,12 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 147 | while (patch_line) { | 149 | while (patch_line) { |
| 148 | unsigned count; | 150 | unsigned count; |
| 149 | unsigned src_beg_line; | 151 | unsigned src_beg_line; |
| 150 | unsigned unused; | 152 | unsigned hunk_offset_start; |
| 151 | unsigned hunk_offset_start = 0; | 153 | unsigned src_last_line = 1; |
| 152 | smallint hunk_error = 0; | 154 | |
| 153 | 155 | if ((sscanf(patch_line, "@@ -%d,%d +%d", &src_beg_line, &src_last_line, &dest_beg_line) != 3) | |
| 154 | /* This bit should be improved */ | 156 | && (sscanf(patch_line, "@@ -%d +%d", &src_beg_line, &dest_beg_line) != 2) |
| 155 | if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, &unused, &dest_beg_line, &unused) != 4) | 157 | ) { /* No more hunks for this file */ |
| 156 | && (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, &unused, &dest_beg_line) != 3) | ||
| 157 | && (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, &dest_beg_line, &unused) != 3) | ||
| 158 | ) { | ||
| 159 | /* No more hunks for this file */ | ||
| 160 | break; | 158 | break; |
| 161 | } | 159 | } |
| 162 | hunk_count++; | 160 | hunk_count++; |
| @@ -172,14 +170,22 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 172 | dest_cur_line += count; | 170 | dest_cur_line += count; |
| 173 | copy_trailing_lines_flag = 1; | 171 | copy_trailing_lines_flag = 1; |
| 174 | } | 172 | } |
| 175 | hunk_offset_start = src_cur_line; | 173 | src_last_line += hunk_offset_start = src_cur_line; |
| 176 | 174 | ||
| 177 | while (1) { | 175 | while (1) { |
| 178 | free(patch_line); | 176 | free(patch_line); |
| 179 | patch_line = xmalloc_fgets(patch_file); | 177 | patch_line = xmalloc_fgets(patch_file); |
| 180 | if (patch_line == NULL) break; | 178 | if (patch_line == NULL) |
| 181 | if ((*patch_line == '-') || (*patch_line == ' ')) { | 179 | break; /* EOF */ |
| 180 | if ((*patch_line != '-') && (*patch_line != '+') | ||
| 181 | && (*patch_line != ' ') | ||
| 182 | ) { | ||
| 183 | break; /* End of hunk */ | ||
| 184 | } | ||
| 185 | if (*patch_line != '+') { /* '-', ' ' or '\n' */ | ||
| 182 | char *src_line = NULL; | 186 | char *src_line = NULL; |
| 187 | if (src_cur_line == src_last_line) | ||
| 188 | break; | ||
| 183 | if (src_stream) { | 189 | if (src_stream) { |
| 184 | src_line = xmalloc_fgets(src_stream); | 190 | src_line = xmalloc_fgets(src_stream); |
| 185 | if (src_line) { | 191 | if (src_line) { |
| @@ -188,26 +194,19 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 188 | free(src_line); | 194 | free(src_line); |
| 189 | if (diff) src_line = NULL; | 195 | if (diff) src_line = NULL; |
| 190 | } | 196 | } |
| 191 | if (!src_line) { | ||
| 192 | bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start); | ||
| 193 | hunk_error = 1; | ||
| 194 | break; | ||
| 195 | } | ||
| 196 | } | 197 | } |
| 197 | if (*patch_line == ' ') { | 198 | if (!src_line) { |
| 198 | fputs(patch_line + 1, dst_stream); | 199 | bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start); |
| 199 | dest_cur_line++; | 200 | bad_hunk_count++; |
| 201 | break; | ||
| 202 | } | ||
| 203 | if (*patch_line == '-') { | ||
| 204 | continue; | ||
| 200 | } | 205 | } |
| 201 | } else if (*patch_line == '+') { | ||
| 202 | fputs(patch_line + 1, dst_stream); | ||
| 203 | dest_cur_line++; | ||
| 204 | } else { | ||
| 205 | break; | ||
| 206 | } | 206 | } |
| 207 | fputs(patch_line + 1, dst_stream); | ||
| 208 | dest_cur_line++; | ||
| 207 | } /* end of while loop handling one hunk */ | 209 | } /* end of while loop handling one hunk */ |
| 208 | if (hunk_error) { | ||
| 209 | bad_hunk_count++; | ||
| 210 | } | ||
| 211 | } /* end of while loop handling one file */ | 210 | } /* end of while loop handling one file */ |
| 212 | 211 | ||
| 213 | /* Cleanup last patched file */ | 212 | /* Cleanup last patched file */ |
| @@ -217,9 +216,7 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 217 | if (src_stream) { | 216 | if (src_stream) { |
| 218 | fclose(src_stream); | 217 | fclose(src_stream); |
| 219 | } | 218 | } |
| 220 | if (dst_stream) { | 219 | fclose(dst_stream); |
| 221 | fclose(dst_stream); | ||
| 222 | } | ||
| 223 | if (bad_hunk_count) { | 220 | if (bad_hunk_count) { |
| 224 | ret = 1; | 221 | ret = 1; |
| 225 | bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); | 222 | bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); |
| @@ -232,11 +229,12 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 232 | if ((dest_cur_line == 0) || (dest_beg_line == 0)) { | 229 | if ((dest_cur_line == 0) || (dest_beg_line == 0)) { |
| 233 | /* The new patched file is empty, remove it */ | 230 | /* The new patched file is empty, remove it */ |
| 234 | xunlink(new_filename); | 231 | xunlink(new_filename); |
| 235 | if (strcmp(new_filename, original_filename) != 0) | 232 | /* original_filename and new_filename may be the same file */ |
| 236 | xunlink(original_filename); | 233 | unlink(original_filename); |
| 237 | } | 234 | } |
| 238 | } | 235 | } |
| 239 | } /* end of "while there are patch lines" */ | 236 | } /* end of "while there are patch lines" */ |
| 237 | quit: | ||
| 240 | 238 | ||
| 241 | /* 0 = SUCCESS | 239 | /* 0 = SUCCESS |
| 242 | * 1 = Some hunks failed | 240 | * 1 = Some hunks failed |
