diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/Config.src | 6 | ||||
-rw-r--r-- | editors/Kbuild.src | 1 | ||||
-rw-r--r-- | editors/awk.c | 14 | ||||
-rw-r--r-- | editors/cmp.c | 9 | ||||
-rw-r--r-- | editors/diff.c | 2 | ||||
-rw-r--r-- | editors/patch.c | 336 | ||||
-rw-r--r-- | editors/sed.c | 6 |
7 files changed, 144 insertions, 230 deletions
diff --git a/editors/Config.src b/editors/Config.src index fc824ccd5..201ee6eb9 100644 --- a/editors/Config.src +++ b/editors/Config.src | |||
@@ -60,12 +60,6 @@ config ED | |||
60 | Small, simple, evil. Part of SUSv3. If you're not already using | 60 | Small, simple, evil. Part of SUSv3. If you're not already using |
61 | this, you don't need it. | 61 | this, you don't need it. |
62 | 62 | ||
63 | config PATCH | ||
64 | bool "patch" | ||
65 | default y | ||
66 | help | ||
67 | Apply a unified diff formatted patch. | ||
68 | |||
69 | config SED | 63 | config SED |
70 | bool "sed" | 64 | bool "sed" |
71 | default y | 65 | default y |
diff --git a/editors/Kbuild.src b/editors/Kbuild.src index 98128064d..2f23ae12f 100644 --- a/editors/Kbuild.src +++ b/editors/Kbuild.src | |||
@@ -11,6 +11,5 @@ lib-$(CONFIG_AWK) += awk.o | |||
11 | lib-$(CONFIG_CMP) += cmp.o | 11 | lib-$(CONFIG_CMP) += cmp.o |
12 | lib-$(CONFIG_DIFF) += diff.o | 12 | lib-$(CONFIG_DIFF) += diff.o |
13 | lib-$(CONFIG_ED) += ed.o | 13 | lib-$(CONFIG_ED) += ed.o |
14 | lib-$(CONFIG_PATCH) += patch.o | ||
15 | lib-$(CONFIG_SED) += sed.o | 14 | lib-$(CONFIG_SED) += sed.o |
16 | lib-$(CONFIG_VI) += vi.o | 15 | lib-$(CONFIG_VI) += vi.o |
diff --git a/editors/awk.c b/editors/awk.c index 8bc56756c..2eeb9d77a 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -277,10 +277,10 @@ enum { | |||
277 | 277 | ||
278 | /* tokens and their corresponding info values */ | 278 | /* tokens and their corresponding info values */ |
279 | 279 | ||
280 | #define NTC "\377" /* switch to next token class (tc<<1) */ | 280 | #define NTC "\377" /* switch to next token class (tc<<1) */ |
281 | #define NTCC '\377' | 281 | #define NTCC '\377' |
282 | 282 | ||
283 | #define OC_B OC_BUILTIN | 283 | #define OC_B OC_BUILTIN |
284 | 284 | ||
285 | static const char tokenlist[] ALIGN1 = | 285 | static const char tokenlist[] ALIGN1 = |
286 | "\1(" NTC | 286 | "\1(" NTC |
@@ -368,7 +368,7 @@ static const uint32_t tokeninfo[] = { | |||
368 | OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b), | 368 | OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b), |
369 | OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49), | 369 | OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49), |
370 | OC_GETLINE|SV|P(0), | 370 | OC_GETLINE|SV|P(0), |
371 | 0, 0, | 371 | 0, 0, |
372 | 0, | 372 | 0, |
373 | 0 /* END */ | 373 | 0 /* END */ |
374 | }; | 374 | }; |
@@ -380,7 +380,7 @@ enum { | |||
380 | ORS, RS, RT, FILENAME, | 380 | ORS, RS, RT, FILENAME, |
381 | SUBSEP, F0, ARGIND, ARGC, | 381 | SUBSEP, F0, ARGIND, ARGC, |
382 | ARGV, ERRNO, FNR, NR, | 382 | ARGV, ERRNO, FNR, NR, |
383 | NF, IGNORECASE, ENVIRON, NUM_INTERNAL_VARS | 383 | NF, IGNORECASE, ENVIRON, NUM_INTERNAL_VARS |
384 | }; | 384 | }; |
385 | 385 | ||
386 | static const char vNames[] ALIGN1 = | 386 | static const char vNames[] ALIGN1 = |
@@ -2335,7 +2335,7 @@ static var *evaluate(node *op, var *res) | |||
2335 | #define fnargs (G.evaluate__fnargs) | 2335 | #define fnargs (G.evaluate__fnargs) |
2336 | /* seed is initialized to 1 */ | 2336 | /* seed is initialized to 1 */ |
2337 | #define seed (G.evaluate__seed) | 2337 | #define seed (G.evaluate__seed) |
2338 | #define sreg (G.evaluate__sreg) | 2338 | #define sreg (G.evaluate__sreg) |
2339 | 2339 | ||
2340 | var *v1; | 2340 | var *v1; |
2341 | 2341 | ||
@@ -2611,7 +2611,7 @@ static var *evaluate(node *op, var *res) | |||
2611 | rsm->F = popen(L.s, "r"); | 2611 | rsm->F = popen(L.s, "r"); |
2612 | rsm->is_pipe = TRUE; | 2612 | rsm->is_pipe = TRUE; |
2613 | } else { | 2613 | } else { |
2614 | rsm->F = fopen_for_read(L.s); /* not xfopen! */ | 2614 | rsm->F = fopen_for_read(L.s); /* not xfopen! */ |
2615 | } | 2615 | } |
2616 | } | 2616 | } |
2617 | } else { | 2617 | } else { |
diff --git a/editors/cmp.c b/editors/cmp.c index f495da7d2..f84a56e3e 100644 --- a/editors/cmp.c +++ b/editors/cmp.c | |||
@@ -33,8 +33,6 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
33 | unsigned opt; | 33 | unsigned opt; |
34 | int retval = 0; | 34 | int retval = 0; |
35 | 35 | ||
36 | xfunc_error_retval = 2; /* 1 is returned if files are different. */ | ||
37 | |||
38 | opt_complementary = "-1" | 36 | opt_complementary = "-1" |
39 | IF_DESKTOP(":?4") | 37 | IF_DESKTOP(":?4") |
40 | IF_NOT_DESKTOP(":?2") | 38 | IF_NOT_DESKTOP(":?2") |
@@ -43,8 +41,6 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
43 | argv += optind; | 41 | argv += optind; |
44 | 42 | ||
45 | filename1 = *argv; | 43 | filename1 = *argv; |
46 | fp1 = xfopen_stdin(filename1); | ||
47 | |||
48 | if (*++argv) { | 44 | if (*++argv) { |
49 | filename2 = *argv; | 45 | filename2 = *argv; |
50 | if (ENABLE_DESKTOP && *++argv) { | 46 | if (ENABLE_DESKTOP && *++argv) { |
@@ -55,6 +51,10 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
55 | } | 51 | } |
56 | } | 52 | } |
57 | 53 | ||
54 | xfunc_error_retval = 2; /* missing file results in exitcode 2 */ | ||
55 | if (opt & CMP_OPT_s) | ||
56 | logmode = 0; /* -s suppresses open error messages */ | ||
57 | fp1 = xfopen_stdin(filename1); | ||
58 | fp2 = xfopen_stdin(filename2); | 58 | fp2 = xfopen_stdin(filename2); |
59 | if (fp1 == fp2) { /* Paranoia check... stdin == stdin? */ | 59 | if (fp1 == fp2) { /* Paranoia check... stdin == stdin? */ |
60 | /* Note that we don't bother reading stdin. Neither does gnu wc. | 60 | /* Note that we don't bother reading stdin. Neither does gnu wc. |
@@ -63,6 +63,7 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
63 | */ | 63 | */ |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | logmode = LOGMODE_STDIO; | ||
66 | 67 | ||
67 | if (opt & CMP_OPT_l) | 68 | if (opt & CMP_OPT_l) |
68 | fmt = fmt_l_opt; | 69 | fmt = fmt_l_opt; |
diff --git a/editors/diff.c b/editors/diff.c index d9d709db6..cc7ba472e 100644 --- a/editors/diff.c +++ b/editors/diff.c | |||
@@ -230,7 +230,7 @@ static int search(const int *c, int k, int y, const struct cand *list) | |||
230 | { | 230 | { |
231 | int i, j; | 231 | int i, j; |
232 | 232 | ||
233 | if (list[c[k]].y < y) /* quick look for typical case */ | 233 | if (list[c[k]].y < y) /* quick look for typical case */ |
234 | return k + 1; | 234 | return k + 1; |
235 | 235 | ||
236 | for (i = 0, j = k + 1;;) { | 236 | for (i = 0, j = k + 1;;) { |
diff --git a/editors/patch.c b/editors/patch.c index 33ff8b569..9c6d967b9 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -1,8 +1,7 @@ | |||
1 | /* Adapted from toybox's patch. */ | ||
2 | |||
3 | /* vi: set sw=4 ts=4: | 1 | /* vi: set sw=4 ts=4: |
4 | * | 2 | * |
5 | * patch.c - Apply a "universal" diff. | 3 | * Apply a "universal" diff. |
4 | * Adapted from toybox's patch implementation. | ||
6 | * | 5 | * |
7 | * Copyright 2007 Rob Landley <rob@landley.net> | 6 | * Copyright 2007 Rob Landley <rob@landley.net> |
8 | * | 7 | * |
@@ -20,30 +19,45 @@ | |||
20 | * -f force (no questions asked) | 19 | * -f force (no questions asked) |
21 | * -F fuzz (number, default 2) | 20 | * -F fuzz (number, default 2) |
22 | * [file] which file to patch | 21 | * [file] which file to patch |
22 | */ | ||
23 | |||
24 | //applet:IF_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
25 | |||
26 | //kbuild:lib-$(CONFIG_PATCH) += patch.o | ||
27 | |||
28 | //config:config PATCH | ||
29 | //config: bool "patch" | ||
30 | //config: default y | ||
31 | //config: help | ||
32 | //config: Apply a unified diff formatted patch. | ||
33 | |||
34 | //usage:#define patch_trivial_usage | ||
35 | //usage: "[OPTIONS] [ORIGFILE [PATCHFILE]]" | ||
36 | //usage:#define patch_full_usage "\n\n" | ||
37 | //usage: IF_LONG_OPTS( | ||
38 | //usage: " -p,--strip N Strip N leading components from file names" | ||
39 | //usage: "\n -i,--input DIFF Read DIFF instead of stdin" | ||
40 | //usage: "\n -R,--reverse Reverse patch" | ||
41 | //usage: "\n -N,--forward Ignore already applied patches" | ||
42 | //usage: "\n --dry-run Don't actually change files" | ||
43 | //usage: "\n -E,--remove-empty-files Remove output files if they become empty" | ||
44 | //usage: ) | ||
45 | //usage: IF_NOT_LONG_OPTS( | ||
46 | //usage: " -p N Strip N leading components from file names" | ||
47 | //usage: "\n -i DIFF Read DIFF instead of stdin" | ||
48 | //usage: "\n -R Reverse patch" | ||
49 | //usage: "\n -N Ignore already applied patches" | ||
50 | //usage: "\n -E Remove output files if they become empty" | ||
51 | //usage: ) | ||
52 | //usage: | ||
53 | //usage:#define patch_example_usage | ||
54 | //usage: "$ patch -p1 < example.diff\n" | ||
55 | //usage: "$ patch -p0 -i example.diff" | ||
23 | 56 | ||
24 | USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN)) | 57 | #include "libbb.h" |
25 | |||
26 | config PATCH | ||
27 | bool "patch" | ||
28 | default y | ||
29 | help | ||
30 | usage: patch [-i file] [-p depth] [-Ru] | ||
31 | |||
32 | Apply a unified diff to one or more files. | ||
33 | 58 | ||
34 | -i Input file (defaults=stdin) | ||
35 | -p number of '/' to strip from start of file paths (default=all) | ||
36 | -R Reverse patch. | ||
37 | -u Ignored (only handles "unified" diffs) | ||
38 | 59 | ||
39 | This version of patch only handles unified diffs, and only modifies | 60 | // libbb candidate? |
40 | a file when all all hunks to that file apply. Patch prints failed | ||
41 | hunks to stderr, and exits with nonzero status if any hunks fail. | ||
42 | |||
43 | A file compared against /dev/null (or with a date <= the epoch) is | ||
44 | created or deleted if -E or --remove-empty-files set. | ||
45 | */ | ||
46 | #include "libbb.h" | ||
47 | 61 | ||
48 | struct double_list { | 62 | struct double_list { |
49 | struct double_list *next; | 63 | struct double_list *next; |
@@ -51,188 +65,55 @@ struct double_list { | |||
51 | char *data; | 65 | char *data; |
52 | }; | 66 | }; |
53 | 67 | ||
54 | // Return the first item from the list, advancing the list (which must be called | ||
55 | // as &list) | ||
56 | static | ||
57 | void *TOY_llist_pop(void *list) | ||
58 | { | ||
59 | // I'd use a void ** for the argument, and even accept the typecast in all | ||
60 | // callers as documentation you need the &, except the stupid compiler | ||
61 | // would then scream about type-punned pointers. Screw it. | ||
62 | void **llist = (void **)list; | ||
63 | void **next = (void **)*llist; | ||
64 | *llist = *next; | ||
65 | |||
66 | return (void *)next; | ||
67 | } | ||
68 | |||
69 | // Free all the elements of a linked list | 68 | // Free all the elements of a linked list |
70 | // if freeit!=NULL call freeit() on each element before freeing it. | 69 | // Call freeit() on each element before freeing it. |
71 | static | 70 | static |
72 | void TOY_llist_free(void *list, void (*freeit)(void *data)) | 71 | void dlist_free(struct double_list *list, void (*freeit)(void *data)) |
73 | { | 72 | { |
74 | while (list) { | 73 | while (list) { |
75 | void *pop = TOY_llist_pop(&list); | 74 | void *pop = list; |
76 | if (freeit) freeit(pop); | 75 | list = list->next; |
77 | else free(pop); | 76 | freeit(pop); |
78 | 77 | // Bail out also if list is circular. | |
79 | // End doubly linked list too. | 78 | if (list == pop) break; |
80 | if (list==pop) break; | ||
81 | } | 79 | } |
82 | } | 80 | } |
83 | //Override bbox's names | ||
84 | #define llist_pop TOY_llist_pop | ||
85 | #define llist_free TOY_llist_free | ||
86 | 81 | ||
87 | // Add an entry to the end off a doubly linked list | 82 | // Add an entry before "list" element in (circular) doubly linked list |
88 | static | 83 | static |
89 | struct double_list *dlist_add(struct double_list **list, char *data) | 84 | struct double_list *dlist_add(struct double_list **list, char *data) |
90 | { | 85 | { |
91 | struct double_list *line = xmalloc(sizeof(struct double_list)); | 86 | struct double_list *llist; |
87 | struct double_list *line = xmalloc(sizeof(*line)); | ||
92 | 88 | ||
93 | line->data = data; | 89 | line->data = data; |
94 | if (*list) { | 90 | llist = *list; |
95 | line->next = *list; | 91 | if (llist) { |
96 | line->prev = (*list)->prev; | 92 | struct double_list *p; |
97 | (*list)->prev->next = line; | 93 | line->next = llist; |
98 | (*list)->prev = line; | 94 | p = line->prev = llist->prev; |
99 | } else *list = line->next = line->prev = line; | 95 | // (list is circular, we assume p is never NULL) |
96 | p->next = line; | ||
97 | llist->prev = line; | ||
98 | } else | ||
99 | *list = line->next = line->prev = line; | ||
100 | 100 | ||
101 | return line; | 101 | return line; |
102 | } | 102 | } |
103 | 103 | ||
104 | // Ensure entire path exists. | ||
105 | // If mode != -1 set permissions on newly created dirs. | ||
106 | // Requires that path string be writable (for temporary null terminators). | ||
107 | static | ||
108 | void xmkpath(char *path, int mode) | ||
109 | { | ||
110 | char *p, old; | ||
111 | mode_t mask; | ||
112 | int rc; | ||
113 | struct stat st; | ||
114 | |||
115 | for (p = path; ; p++) { | ||
116 | if (!*p || *p == '/') { | ||
117 | old = *p; | ||
118 | *p = rc = 0; | ||
119 | if (stat(path, &st) || !S_ISDIR(st.st_mode)) { | ||
120 | if (mode != -1) { | ||
121 | mask = umask(0); | ||
122 | rc = mkdir(path, mode); | ||
123 | umask(mask); | ||
124 | } else rc = mkdir(path, 0777); | ||
125 | } | ||
126 | *p = old; | ||
127 | if(rc) bb_perror_msg_and_die("mkpath '%s'", path); | ||
128 | } | ||
129 | if (!*p) break; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | // Slow, but small. | ||
134 | static | ||
135 | char *get_rawline(int fd, long *plen, char end) | ||
136 | { | ||
137 | char c, *buf = NULL; | ||
138 | long len = 0; | ||
139 | |||
140 | for (;;) { | ||
141 | if (1>read(fd, &c, 1)) break; | ||
142 | if (!(len & 63)) buf=xrealloc(buf, len+65); | ||
143 | if ((buf[len++]=c) == end) break; | ||
144 | } | ||
145 | if (buf) buf[len]=0; | ||
146 | if (plen) *plen = len; | ||
147 | |||
148 | return buf; | ||
149 | } | ||
150 | |||
151 | static | ||
152 | char *get_line(int fd) | ||
153 | { | ||
154 | long len; | ||
155 | char *buf = get_rawline(fd, &len, '\n'); | ||
156 | |||
157 | if (buf && buf[--len]=='\n') buf[len]=0; | ||
158 | |||
159 | return buf; | ||
160 | } | ||
161 | |||
162 | // Copy the rest of in to out and close both files. | ||
163 | static | ||
164 | void xsendfile(int in, int out) | ||
165 | { | ||
166 | long len; | ||
167 | char buf[4096]; | ||
168 | |||
169 | if (in<0) return; | ||
170 | for (;;) { | ||
171 | len = safe_read(in, buf, 4096); | ||
172 | if (len<1) break; | ||
173 | xwrite(out, buf, len); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | // Copy the rest of the data and replace the original with the copy. | ||
178 | static | ||
179 | void replace_tempfile(int fdin, int fdout, char **tempname) | ||
180 | { | ||
181 | char *temp = xstrdup(*tempname); | ||
182 | |||
183 | temp[strlen(temp)-6]=0; | ||
184 | if (fdin != -1) { | ||
185 | xsendfile(fdin, fdout); | ||
186 | xclose(fdin); | ||
187 | } | ||
188 | xclose(fdout); | ||
189 | rename(*tempname, temp); | ||
190 | free(*tempname); | ||
191 | free(temp); | ||
192 | *tempname = NULL; | ||
193 | } | ||
194 | |||
195 | // Open a temporary file to copy an existing file into. | ||
196 | static | ||
197 | int copy_tempfile(int fdin, char *name, char **tempname) | ||
198 | { | ||
199 | struct stat statbuf; | ||
200 | int fd; | ||
201 | |||
202 | *tempname = xasprintf("%sXXXXXX", name); | ||
203 | fd = xmkstemp(*tempname); | ||
204 | |||
205 | // Set permissions of output file | ||
206 | fstat(fdin, &statbuf); | ||
207 | fchmod(fd, statbuf.st_mode); | ||
208 | |||
209 | return fd; | ||
210 | } | ||
211 | |||
212 | // Abort the copy and delete the temporary file. | ||
213 | static | ||
214 | void delete_tempfile(int fdin, int fdout, char **tempname) | ||
215 | { | ||
216 | close(fdin); | ||
217 | close(fdout); | ||
218 | unlink(*tempname); | ||
219 | free(*tempname); | ||
220 | *tempname = NULL; | ||
221 | } | ||
222 | |||
223 | |||
224 | 104 | ||
225 | struct globals { | 105 | struct globals { |
226 | char *infile; | 106 | char *infile; |
227 | long prefix; | 107 | long prefix; |
228 | 108 | ||
229 | struct double_list *current_hunk; | 109 | struct double_list *current_hunk; |
110 | |||
230 | long oldline, oldlen, newline, newlen; | 111 | long oldline, oldlen, newline, newlen; |
231 | long linenum; | 112 | long linenum; |
232 | int context, state, filein, fileout, filepatch, hunknum; | 113 | int context, state, hunknum; |
114 | int filein, fileout; | ||
233 | char *tempname; | 115 | char *tempname; |
234 | 116 | ||
235 | // was toys.foo: | ||
236 | int exitval; | 117 | int exitval; |
237 | }; | 118 | }; |
238 | #define TT (*ptr_to_globals) | 119 | #define TT (*ptr_to_globals) |
@@ -263,7 +144,7 @@ struct globals { | |||
263 | 144 | ||
264 | static void do_line(void *data) | 145 | static void do_line(void *data) |
265 | { | 146 | { |
266 | struct double_list *dlist = (struct double_list *)data; | 147 | struct double_list *dlist = data; |
267 | 148 | ||
268 | if (TT.state>1 && *dlist->data != TT.state) | 149 | if (TT.state>1 && *dlist->data != TT.state) |
269 | fdprintf(TT.state == 2 ? 2 : TT.fileout, | 150 | fdprintf(TT.state == 2 ? 2 : TT.fileout, |
@@ -272,19 +153,35 @@ static void do_line(void *data) | |||
272 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); | 153 | if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); |
273 | 154 | ||
274 | free(dlist->data); | 155 | free(dlist->data); |
275 | free(data); | 156 | free(dlist); |
276 | } | 157 | } |
277 | 158 | ||
278 | static void finish_oldfile(void) | 159 | static void finish_oldfile(void) |
279 | { | 160 | { |
280 | if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); | 161 | if (TT.tempname) { |
162 | // Copy the rest of the data and replace the original with the copy. | ||
163 | char *temp; | ||
164 | |||
165 | if (TT.filein != -1) { | ||
166 | bb_copyfd_eof(TT.filein, TT.fileout); | ||
167 | xclose(TT.filein); | ||
168 | } | ||
169 | xclose(TT.fileout); | ||
170 | |||
171 | temp = xstrdup(TT.tempname); | ||
172 | temp[strlen(temp) - 6] = '\0'; | ||
173 | rename(TT.tempname, temp); | ||
174 | free(temp); | ||
175 | |||
176 | free(TT.tempname); | ||
177 | TT.tempname = NULL; | ||
178 | } | ||
281 | TT.fileout = TT.filein = -1; | 179 | TT.fileout = TT.filein = -1; |
282 | } | 180 | } |
283 | 181 | ||
284 | static void fail_hunk(void) | 182 | static void fail_hunk(void) |
285 | { | 183 | { |
286 | if (!TT.current_hunk) return; | 184 | if (!TT.current_hunk) return; |
287 | TT.current_hunk->prev->next = 0; | ||
288 | 185 | ||
289 | fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline); | 186 | fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline); |
290 | TT.exitval = 1; | 187 | TT.exitval = 1; |
@@ -293,9 +190,17 @@ static void fail_hunk(void) | |||
293 | // this file and advance to next file. | 190 | // this file and advance to next file. |
294 | 191 | ||
295 | TT.state = 2; | 192 | TT.state = 2; |
296 | llist_free(TT.current_hunk, do_line); | 193 | TT.current_hunk->prev->next = NULL; |
194 | dlist_free(TT.current_hunk, do_line); | ||
297 | TT.current_hunk = NULL; | 195 | TT.current_hunk = NULL; |
298 | delete_tempfile(TT.filein, TT.fileout, &TT.tempname); | 196 | |
197 | // Abort the copy and delete the temporary file. | ||
198 | close(TT.filein); | ||
199 | close(TT.fileout); | ||
200 | unlink(TT.tempname); | ||
201 | free(TT.tempname); | ||
202 | TT.tempname = NULL; | ||
203 | |||
299 | TT.state = 0; | 204 | TT.state = 0; |
300 | } | 205 | } |
301 | 206 | ||
@@ -333,8 +238,8 @@ static int apply_one_hunk(void) | |||
333 | // complete hunk. | 238 | // complete hunk. |
334 | plist = TT.current_hunk; | 239 | plist = TT.current_hunk; |
335 | buf = NULL; | 240 | buf = NULL; |
336 | if (TT.context) for (;;) { | 241 | if (reverse ? TT.oldlen : TT.newlen) for (;;) { |
337 | char *data = get_line(TT.filein); | 242 | char *data = xmalloc_reads(TT.filein, NULL, NULL); |
338 | 243 | ||
339 | TT.linenum++; | 244 | TT.linenum++; |
340 | 245 | ||
@@ -368,7 +273,9 @@ static int apply_one_hunk(void) | |||
368 | // File ended before we found a place for this hunk. | 273 | // File ended before we found a place for this hunk. |
369 | fail_hunk(); | 274 | fail_hunk(); |
370 | goto done; | 275 | goto done; |
371 | } else if (PATCH_DEBUG) fdprintf(2, "IN: %s\n", data); | 276 | } |
277 | |||
278 | if (PATCH_DEBUG) fdprintf(2, "IN: %s\n", data); | ||
372 | check = dlist_add(&buf, data); | 279 | check = dlist_add(&buf, data); |
373 | 280 | ||
374 | // Compare this line with next expected line of hunk. | 281 | // Compare this line with next expected line of hunk. |
@@ -390,7 +297,8 @@ static int apply_one_hunk(void) | |||
390 | fdprintf(2, "NOT: %s\n", plist->data); | 297 | fdprintf(2, "NOT: %s\n", plist->data); |
391 | 298 | ||
392 | TT.state = 3; | 299 | TT.state = 3; |
393 | check = llist_pop(&buf); | 300 | check = buf; |
301 | buf = buf->next; | ||
394 | check->prev->next = buf; | 302 | check->prev->next = buf; |
395 | buf->prev = check->prev; | 303 | buf->prev = check->prev; |
396 | do_line(check); | 304 | do_line(check); |
@@ -398,8 +306,8 @@ static int apply_one_hunk(void) | |||
398 | 306 | ||
399 | // If we've reached the end of the buffer without confirming a | 307 | // If we've reached the end of the buffer without confirming a |
400 | // match, read more lines. | 308 | // match, read more lines. |
401 | if (check==buf) { | 309 | if (check == buf) { |
402 | buf = 0; | 310 | buf = NULL; |
403 | break; | 311 | break; |
404 | } | 312 | } |
405 | check = buf; | 313 | check = buf; |
@@ -417,13 +325,13 @@ static int apply_one_hunk(void) | |||
417 | out: | 325 | out: |
418 | // We have a match. Emit changed data. | 326 | // We have a match. Emit changed data. |
419 | TT.state = "-+"[reverse ^ dummy_revert]; | 327 | TT.state = "-+"[reverse ^ dummy_revert]; |
420 | llist_free(TT.current_hunk, do_line); | 328 | dlist_free(TT.current_hunk, do_line); |
421 | TT.current_hunk = NULL; | 329 | TT.current_hunk = NULL; |
422 | TT.state = 1; | 330 | TT.state = 1; |
423 | done: | 331 | done: |
424 | if (buf) { | 332 | if (buf) { |
425 | buf->prev->next = NULL; | 333 | buf->prev->next = NULL; |
426 | llist_free(buf, do_line); | 334 | dlist_free(buf, do_line); |
427 | } | 335 | } |
428 | 336 | ||
429 | return TT.state; | 337 | return TT.state; |
@@ -444,6 +352,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
444 | int reverse, state = 0; | 352 | int reverse, state = 0; |
445 | char *oldname = NULL, *newname = NULL; | 353 | char *oldname = NULL, *newname = NULL; |
446 | char *opt_p, *opt_i; | 354 | char *opt_p, *opt_i; |
355 | long oldlen = oldlen; /* for compiler */ | ||
356 | long newlen = newlen; /* for compiler */ | ||
447 | 357 | ||
448 | INIT_TT(); | 358 | INIT_TT(); |
449 | 359 | ||
@@ -453,10 +363,10 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
453 | TT.prefix = (opts & FLAG_PATHLEN) ? xatoi(opt_p) : 0; // can be negative! | 363 | TT.prefix = (opts & FLAG_PATHLEN) ? xatoi(opt_p) : 0; // can be negative! |
454 | TT.filein = TT.fileout = -1; | 364 | TT.filein = TT.fileout = -1; |
455 | if (opts & FLAG_INPUT) { | 365 | if (opts & FLAG_INPUT) { |
456 | TT.filepatch = xopen_stdin(opt_i); | 366 | xmove_fd(xopen_stdin(opt_i), STDIN_FILENO); |
457 | } else { | 367 | } else { |
458 | if (argv[0] && argv[1]) { | 368 | if (argv[0] && argv[1]) { |
459 | TT.filepatch = xopen_stdin(argv[1]); | 369 | xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO); |
460 | } | 370 | } |
461 | } | 371 | } |
462 | if (argv[0]) { | 372 | if (argv[0]) { |
@@ -468,7 +378,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
468 | for(;;) { | 378 | for(;;) { |
469 | char *patchline; | 379 | char *patchline; |
470 | 380 | ||
471 | patchline = get_line(TT.filepatch); | 381 | patchline = xmalloc_fgetline(stdin); |
472 | if (!patchline) break; | 382 | if (!patchline) break; |
473 | 383 | ||
474 | // Other versions of patch accept damaged patches, | 384 | // Other versions of patch accept damaged patches, |
@@ -483,8 +393,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
483 | if (*patchline==' ' || *patchline=='+' || *patchline=='-') { | 393 | if (*patchline==' ' || *patchline=='+' || *patchline=='-') { |
484 | dlist_add(&TT.current_hunk, patchline); | 394 | dlist_add(&TT.current_hunk, patchline); |
485 | 395 | ||
486 | if (*patchline != '+') TT.oldlen--; | 396 | if (*patchline != '+') oldlen--; |
487 | if (*patchline != '-') TT.newlen--; | 397 | if (*patchline != '-') newlen--; |
488 | 398 | ||
489 | // Context line? | 399 | // Context line? |
490 | if (*patchline==' ' && state==2) TT.context++; | 400 | if (*patchline==' ' && state==2) TT.context++; |
@@ -492,7 +402,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
492 | 402 | ||
493 | // If we've consumed all expected hunk lines, apply the hunk. | 403 | // If we've consumed all expected hunk lines, apply the hunk. |
494 | 404 | ||
495 | if (!TT.oldlen && !TT.newlen) state = apply_one_hunk(); | 405 | if (!oldlen && !newlen) state = apply_one_hunk(); |
496 | continue; | 406 | continue; |
497 | } | 407 | } |
498 | fail_hunk(); | 408 | fail_hunk(); |
@@ -539,11 +449,14 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
539 | 449 | ||
540 | // Read oldline[,oldlen] +newline[,newlen] | 450 | // Read oldline[,oldlen] +newline[,newlen] |
541 | 451 | ||
542 | TT.oldlen = TT.newlen = 1; | 452 | TT.oldlen = oldlen = TT.newlen = newlen = 1; |
543 | TT.oldline = strtol(s, &s, 10); | 453 | TT.oldline = strtol(s, &s, 10); |
544 | if (*s == ',') TT.oldlen=strtol(s+1, &s, 10); | 454 | if (*s == ',') TT.oldlen = oldlen = strtol(s+1, &s, 10); |
545 | TT.newline = strtol(s+2, &s, 10); | 455 | TT.newline = strtol(s+2, &s, 10); |
546 | if (*s == ',') TT.newlen = strtol(s+1, &s, 10); | 456 | if (*s == ',') TT.newlen = newlen = strtol(s+1, &s, 10); |
457 | |||
458 | if (oldlen < 1 && newlen < 1) | ||
459 | bb_error_msg_and_die("Really? %s", patchline); | ||
547 | 460 | ||
548 | TT.context = 0; | 461 | TT.context = 0; |
549 | state = 2; | 462 | state = 2; |
@@ -553,8 +466,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
553 | int oldsum, newsum, empty = 0; | 466 | int oldsum, newsum, empty = 0; |
554 | char *name; | 467 | char *name; |
555 | 468 | ||
556 | oldsum = TT.oldline + TT.oldlen; | 469 | oldsum = TT.oldline + oldlen; |
557 | newsum = TT.newline + TT.newlen; | 470 | newsum = TT.newline + newlen; |
558 | 471 | ||
559 | name = reverse ? oldname : newname; | 472 | name = reverse ? oldname : newname; |
560 | 473 | ||
@@ -588,13 +501,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
588 | } | 501 | } |
589 | // If we've got a file to open, do so. | 502 | // If we've got a file to open, do so. |
590 | } else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) { | 503 | } else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) { |
504 | struct stat statbuf; | ||
505 | |||
591 | // If the old file was null, we're creating a new one. | 506 | // If the old file was null, we're creating a new one. |
592 | if (!strcmp(oldname, "/dev/null") || !oldsum) { | 507 | if (!strcmp(oldname, "/dev/null") || !oldsum) { |
593 | printf("creating %s\n", name); | 508 | printf("creating %s\n", name); |
594 | s = strrchr(name, '/'); | 509 | s = strrchr(name, '/'); |
595 | if (s) { | 510 | if (s) { |
596 | *s = 0; | 511 | *s = 0; |
597 | xmkpath(name, -1); | 512 | bb_make_directory(name, -1, FILEUTILS_RECUR); |
598 | *s = '/'; | 513 | *s = '/'; |
599 | } | 514 | } |
600 | TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); | 515 | TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); |
@@ -602,7 +517,13 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
602 | printf("patching file %s\n", name); | 517 | printf("patching file %s\n", name); |
603 | TT.filein = xopen(name, O_RDONLY); | 518 | TT.filein = xopen(name, O_RDONLY); |
604 | } | 519 | } |
605 | TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); | 520 | |
521 | TT.tempname = xasprintf("%sXXXXXX", name); | ||
522 | TT.fileout = xmkstemp(TT.tempname); | ||
523 | // Set permissions of output file | ||
524 | fstat(TT.filein, &statbuf); | ||
525 | fchmod(TT.fileout, statbuf.st_mode); | ||
526 | |||
606 | TT.linenum = 0; | 527 | TT.linenum = 0; |
607 | TT.hunknum = 0; | 528 | TT.hunknum = 0; |
608 | } | 529 | } |
@@ -620,7 +541,6 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
620 | finish_oldfile(); | 541 | finish_oldfile(); |
621 | 542 | ||
622 | if (ENABLE_FEATURE_CLEAN_UP) { | 543 | if (ENABLE_FEATURE_CLEAN_UP) { |
623 | close(TT.filepatch); | ||
624 | free(oldname); | 544 | free(oldname); |
625 | free(newname); | 545 | free(newname); |
626 | } | 546 | } |
diff --git a/editors/sed.c b/editors/sed.c index 964d0405e..b91acfb7f 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -117,9 +117,9 @@ struct globals { | |||
117 | char *add_cmd_line; | 117 | char *add_cmd_line; |
118 | 118 | ||
119 | struct pipeline { | 119 | struct pipeline { |
120 | char *buf; /* Space to hold string */ | 120 | char *buf; /* Space to hold string */ |
121 | int idx; /* Space used */ | 121 | int idx; /* Space used */ |
122 | int len; /* Space allocated */ | 122 | int len; /* Space allocated */ |
123 | } pipeline; | 123 | } pipeline; |
124 | } FIX_ALIASING; | 124 | } FIX_ALIASING; |
125 | #define G (*(struct globals*)&bb_common_bufsiz1) | 125 | #define G (*(struct globals*)&bb_common_bufsiz1) |