aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-23 22:55:25 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-23 22:55:25 +0000
commitc93b162248892265eae5f54e9ee409074dfa08c5 (patch)
tree497549c9ca48814af3de07d185bf7beaa0d360b2 /editors
parent324d26f9aa7453871e8bc5c2cc7c45ae2627bc35 (diff)
downloadbusybox-w32-c93b162248892265eae5f54e9ee409074dfa08c5.tar.gz
busybox-w32-c93b162248892265eae5f54e9ee409074dfa08c5.tar.bz2
busybox-w32-c93b162248892265eae5f54e9ee409074dfa08c5.zip
patch: shrink by Pascal Bellard <pascal.bellard AT ads-lu.com> (-80 bytes)
*: removal of #include <getopt.h>
Diffstat (limited to 'editors')
-rw-r--r--editors/patch.c171
1 files changed, 73 insertions, 98 deletions
diff --git a/editors/patch.c b/editors/patch.c
index 9a678e162..a37f4e62f 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -19,15 +19,11 @@
19 * - Reject file isnt saved 19 * - Reject file isnt saved
20 */ 20 */
21 21
22#include <getopt.h>
23
24#include "libbb.h" 22#include "libbb.h"
25 23
26static unsigned int copy_lines(FILE *src_stream, FILE *dest_stream, const unsigned int lines_count) 24static unsigned copy_lines(FILE *src_stream, FILE *dest_stream, unsigned lines_count)
27{ 25{
28 unsigned int i = 0; 26 while (src_stream && lines_count) {
29
30 while (src_stream && (i < lines_count)) {
31 char *line; 27 char *line;
32 line = xmalloc_fgets(src_stream); 28 line = xmalloc_fgets(src_stream);
33 if (line == NULL) { 29 if (line == NULL) {
@@ -37,60 +33,54 @@ static unsigned int copy_lines(FILE *src_stream, FILE *dest_stream, const unsign
37 bb_perror_msg_and_die("error writing to new file"); 33 bb_perror_msg_and_die("error writing to new file");
38 } 34 }
39 free(line); 35 free(line);
40 36 lines_count--;
41 i++;
42 } 37 }
43 return i; 38 return lines_count;
44} 39}
45 40
46/* If patch_level is -1 it will remove all directory names 41/* If patch_level is -1 it will remove all directory names
47 * char *line must be greater than 4 chars 42 * char *line must be greater than 4 chars
48 * returns NULL if the file doesnt exist or error 43 * returns NULL if the file doesnt exist or error
49 * returns malloc'ed filename 44 * returns malloc'ed filename
45 * NB: frees 1st argument!
50 */ 46 */
51 47static char *extract_filename_and_free_line(char *line, int patch_level)
52static char *extract_filename(char *line, int patch_level)
53{ 48{
54 char *temp, *filename_start_ptr = line + 4; 49 char *temp, *filename_start_ptr = line + 4;
55 int i;
56 50
57 /* Terminate string at end of source filename */ 51 /* Terminate string at end of source filename */
58 temp = strchrnul(filename_start_ptr, '\t'); 52 temp = strchrnul(filename_start_ptr, '\t');
59 *temp = '\0'; 53 *temp = '\0';
60 54
61 /* Skip over (patch_level) number of leading directories */ 55 /* Skip over (patch_level) number of leading directories */
62 if (patch_level == -1) 56 while (patch_level--) {
63 patch_level = INT_MAX;
64 for (i = 0; i < patch_level; i++) {
65 temp = strchr(filename_start_ptr, '/'); 57 temp = strchr(filename_start_ptr, '/');
66 if (!temp) 58 if (!temp)
67 break; 59 break;
68 filename_start_ptr = temp + 1; 60 filename_start_ptr = temp + 1;
69 } 61 }
70 62
71 return xstrdup(filename_start_ptr); 63 temp = xstrdup(filename_start_ptr);
64 free(line);
65 return temp;
72} 66}
73 67
74int patch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 68int patch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
75int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) 69int patch_main(int argc ATTRIBUTE_UNUSED, char **argv)
76{ 70{
77 int patch_level = -1;
78 char *patch_line;
79 int ret;
80 FILE *patch_file = NULL;
81 struct stat saved_stat; 71 struct stat saved_stat;
82 72 char *patch_line;
73 FILE *patch_file;
74 int patch_level;
75 int ret = 0;
76
77 xfunc_error_retval = 2;
83 { 78 {
84 char *p, *i; 79 const char *p = "-1";
85 ret = getopt32(argv, "p:i:", &p, &i); 80 const char *i = "-"; /* compat */
86 if (ret & 1) 81 getopt32(argv, "p:i:", &p, &i);
87 patch_level = xatol_range(p, -1, USHRT_MAX); 82 patch_level = xatoi(p); /* can be negative! */
88 if (ret & 2) { 83 patch_file = xfopen_stdin(i);
89 patch_file = xfopen(i, "r");
90 } else {
91 patch_file = stdin;
92 }
93 ret = 0;
94 } 84 }
95 85
96 patch_line = xmalloc_getline(patch_file); 86 patch_line = xmalloc_getline(patch_file);
@@ -100,38 +90,33 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv)
100 char *original_filename; 90 char *original_filename;
101 char *new_filename; 91 char *new_filename;
102 char *backup_filename; 92 char *backup_filename;
103 unsigned int src_cur_line = 1; 93 unsigned src_cur_line = 1;
104 unsigned int dest_cur_line = 0; 94 unsigned dest_cur_line = 0;
105 unsigned int dest_beg_line; 95 unsigned dest_beg_line;
106 unsigned int bad_hunk_count = 0; 96 unsigned bad_hunk_count = 0;
107 unsigned int hunk_count = 0; 97 unsigned hunk_count = 0;
108 char copy_trailing_lines_flag = 0; 98 smallint copy_trailing_lines_flag = 0;
109 99
110 /* Skip everything upto the "---" marker 100 /* Skip everything upto the "---" marker
111 * 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>"
112 */ 102 */
113 while (patch_line && strncmp(patch_line, "--- ", 4) != 0) { 103 while (strncmp(patch_line, "--- ", 4) != 0) {
114 free(patch_line); 104 free(patch_line);
115 patch_line = xmalloc_getline(patch_file); 105 patch_line = xmalloc_getline(patch_file);
106 if (!patch_line)
107 bb_error_msg_and_die("invalid patch");
116 } 108 }
117 /* FIXME: patch_line NULL check?? */
118 109
119 /* Extract the filename used before the patch was generated */ 110 /* Extract the filename used before the patch was generated */
120 original_filename = extract_filename(patch_line, patch_level); 111 original_filename = extract_filename_and_free_line(patch_line, patch_level);
121 free(patch_line);
122 112
123 patch_line = xmalloc_getline(patch_file); 113 patch_line = xmalloc_getline(patch_file);
124 /* FIXME: NULL check?? */ 114 if (!patch_line || strncmp(patch_line, "+++ ", 4) != 0)
125 if (strncmp(patch_line, "+++ ", 4) != 0) { 115 bb_error_msg_and_die("invalid patch");
126 ret = 2; 116 new_filename = extract_filename_and_free_line(patch_line, patch_level);
127 bb_error_msg("invalid patch");
128 continue;
129 }
130 new_filename = extract_filename(patch_line, patch_level);
131 free(patch_line);
132 117
133 /* Get access rights from the file to be patched, -1 file does not exist */ 118 /* Get access rights from the file to be patched, -1 file does not exist */
134 if (stat(new_filename, &saved_stat)) { 119 if (stat(new_filename, &saved_stat) != 0) {
135 char *line_ptr; 120 char *line_ptr;
136 /* Create leading directories */ 121 /* Create leading directories */
137 line_ptr = strrchr(new_filename, '/'); 122 line_ptr = strrchr(new_filename, '/');
@@ -140,53 +125,47 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv)
140 bb_make_directory(new_filename, -1, FILEUTILS_RECUR); 125 bb_make_directory(new_filename, -1, FILEUTILS_RECUR);
141 *line_ptr = '/'; 126 *line_ptr = '/';
142 } 127 }
143 dst_stream = xfopen(new_filename, "w+");
144 backup_filename = NULL; 128 backup_filename = NULL;
129 saved_stat.st_mode = 0644;
145 } else { 130 } else {
146 backup_filename = xmalloc(strlen(new_filename) + 6); 131 backup_filename = xasprintf("%s.orig", new_filename);
147 strcpy(backup_filename, new_filename);
148 strcat(backup_filename, ".orig");
149 xrename(new_filename, backup_filename); 132 xrename(new_filename, backup_filename);
150 dst_stream = xfopen(new_filename, "w");
151 fchmod(fileno(dst_stream), saved_stat.st_mode);
152 } 133 }
134 dst_stream = xfopen(new_filename, "w");
135 fchmod(fileno(dst_stream), saved_stat.st_mode);
136 src_stream = NULL;
153 137
154 if ((backup_filename == NULL) || stat(original_filename, &saved_stat)) { 138 if (backup_filename && !stat(original_filename, &saved_stat)) {
155 src_stream = NULL; 139 src_stream = xfopen((strcmp(original_filename, new_filename)) ?
156 } else { 140 original_filename : backup_filename, "r");
157 if (strcmp(original_filename, new_filename) == 0) {
158 src_stream = xfopen(backup_filename, "r");
159 } else {
160 src_stream = xfopen(original_filename, "r");
161 }
162 } 141 }
163 142
164 printf("patching file %s\n", new_filename); 143 printf("patching file %s\n", new_filename);
165 144
166 /* Handle each hunk */ 145 /* Handle all hunks for this file */
167 patch_line = xmalloc_fgets(patch_file); 146 patch_line = xmalloc_fgets(patch_file);
168 while (patch_line) { 147 while (patch_line) {
169 unsigned int count; 148 unsigned count;
170 unsigned int src_beg_line; 149 unsigned src_beg_line;
171 unsigned int unused; 150 unsigned unused;
172 unsigned int hunk_offset_start = 0; 151 unsigned hunk_offset_start = 0;
173 int hunk_error = 0; 152 smallint hunk_error = 0;
174 153
175 /* This bit should be improved */ 154 /* This bit should be improved */
176 if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, &unused, &dest_beg_line, &unused) != 4) && 155 if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, &unused, &dest_beg_line, &unused) != 4)
177 (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, &unused, &dest_beg_line) != 3) && 156 && (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, &unused, &dest_beg_line) != 3)
178 (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, &dest_beg_line, &unused) != 3)) { 157 && (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, &dest_beg_line, &unused) != 3)
158 ) {
179 /* No more hunks for this file */ 159 /* No more hunks for this file */
180 break; 160 break;
181 } 161 }
182 free(patch_line);
183 hunk_count++; 162 hunk_count++;
184 163
185 if (src_beg_line && dest_beg_line) { 164 if (src_beg_line && dest_beg_line) {
186 /* Copy unmodified lines upto start of hunk */ 165 /* Copy unmodified lines upto start of hunk */
187 /* src_beg_line will be 0 if its a new file */ 166 /* src_beg_line will be 0 if it's a new file */
188 count = src_beg_line - src_cur_line; 167 count = src_beg_line - src_cur_line;
189 if (copy_lines(src_stream, dst_stream, count) != count) { 168 if (copy_lines(src_stream, dst_stream, count)) {
190 bb_error_msg_and_die("bad src file"); 169 bb_error_msg_and_die("bad src file");
191 } 170 }
192 src_cur_line += count; 171 src_cur_line += count;
@@ -195,27 +174,25 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv)
195 } 174 }
196 hunk_offset_start = src_cur_line; 175 hunk_offset_start = src_cur_line;
197 176
198 while ((patch_line = xmalloc_fgets(patch_file)) != NULL) { 177 while (1) {
178 free(patch_line);
179 patch_line = xmalloc_fgets(patch_file);
180 if (patch_line == NULL) break;
199 if ((*patch_line == '-') || (*patch_line == ' ')) { 181 if ((*patch_line == '-') || (*patch_line == ' ')) {
200 char *src_line = NULL; 182 char *src_line = NULL;
201 if (src_stream) { 183 if (src_stream) {
202 src_line = xmalloc_fgets(src_stream); 184 src_line = xmalloc_fgets(src_stream);
203 if (!src_line) { 185 if (src_line) {
204 hunk_error++; 186 int diff = strcmp(src_line, patch_line + 1);
205 break;
206 } else {
207 src_cur_line++; 187 src_cur_line++;
188 free(src_line);
189 if (diff) src_line = NULL;
208 } 190 }
209 if (strcmp(src_line, patch_line + 1) != 0) { 191 if (!src_line) {
210 bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start); 192 bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start);
211 hunk_error++; 193 hunk_error = 1;
212 free(patch_line);
213 /* Probably need to find next hunk, etc... */
214 /* but for now we just bail out */
215 patch_line = NULL;
216 break; 194 break;
217 } 195 }
218 free(src_line);
219 } 196 }
220 if (*patch_line == ' ') { 197 if (*patch_line == ' ') {
221 fputs(patch_line + 1, dst_stream); 198 fputs(patch_line + 1, dst_stream);
@@ -227,16 +204,15 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv)
227 } else { 204 } else {
228 break; 205 break;
229 } 206 }
230 free(patch_line); 207 } /* end of while loop handling one hunk */
231 }
232 if (hunk_error) { 208 if (hunk_error) {
233 bad_hunk_count++; 209 bad_hunk_count++;
234 } 210 }
235 } 211 } /* end of while loop handling one file */
236 212
237 /* Cleanup last patched file */ 213 /* Cleanup last patched file */
238 if (copy_trailing_lines_flag) { 214 if (copy_trailing_lines_flag) {
239 copy_lines(src_stream, dst_stream, -1); 215 copy_lines(src_stream, dst_stream, (unsigned)(-1));
240 } 216 }
241 if (src_stream) { 217 if (src_stream) {
242 fclose(src_stream); 218 fclose(src_stream);
@@ -245,14 +221,13 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv)
245 fclose(dst_stream); 221 fclose(dst_stream);
246 } 222 }
247 if (bad_hunk_count) { 223 if (bad_hunk_count) {
248 if (!ret) { 224 ret = 1;
249 ret = 1; 225 bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count);
250 }
251 bb_error_msg("%d out of %d hunk FAILED", bad_hunk_count, hunk_count);
252 } else { 226 } else {
253 /* It worked, we can remove the backup */ 227 /* It worked, we can remove the backup */
254 if (backup_filename) { 228 if (backup_filename) {
255 unlink(backup_filename); 229 unlink(backup_filename);
230 free(backup_filename);
256 } 231 }
257 if ((dest_cur_line == 0) || (dest_beg_line == 0)) { 232 if ((dest_cur_line == 0) || (dest_beg_line == 0)) {
258 /* The new patched file is empty, remove it */ 233 /* The new patched file is empty, remove it */
@@ -261,11 +236,11 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv)
261 xunlink(original_filename); 236 xunlink(original_filename);
262 } 237 }
263 } 238 }
264 } 239 } /* end of "while there are patch lines" */
265 240
266 /* 0 = SUCCESS 241 /* 0 = SUCCESS
267 * 1 = Some hunks failed 242 * 1 = Some hunks failed
268 * 2 = More serious problems 243 * 2 = More serious problems (exited earlier)
269 */ 244 */
270 return ret; 245 return ret;
271} 246}