aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-24 18:18:03 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-24 18:18:03 +0000
commit64a76d7b447eeaf2a50606c04f87cec8ef535efb (patch)
treedc3d21b070c99fe9043b4259f27cec4e6ae2f308
parentc4c2cd44d2befc5c1153cd54e1ceb93b88fee243 (diff)
downloadbusybox-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.c136
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 */
47static char *extract_filename_and_free_line(char *line, int patch_level) 47static 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" */
237quit:
240 238
241 /* 0 = SUCCESS 239 /* 0 = SUCCESS
242 * 1 = Some hunks failed 240 * 1 = Some hunks failed