1 /* reading patches */
2
3 /* Copyright (C) 1986, 1987, 1988 Larry Wall
4
5 Copyright (C) 1990-1993, 1997-2003, 2006, 2009-2012 Free Software
6 Foundation, Inc.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #define XTERN extern
22 #include <common.h>
23 #include <dirname.h>
24 #include <inp.h>
25 #include <quotearg.h>
26 #include <util.h>
27 #include <xalloc.h>
28 #include <xmemdup0.h>
29 #undef XTERN
30 #define XTERN
31 #include <pch.h>
32 #if HAVE_SETMODE_DOS
33 # include <io.h>
34 #endif
35 #include <safe.h>
36 #include <sys/wait.h>
37
38 #define INITHUNKMAX 125 /* initial dynamic allocation size */
39
40 /* Patch (diff listing) abstract type. */
41
42 static FILE *pfp; /* patch file pointer */
43 static int p_says_nonexistent[2]; /* [0] for old file, [1] for new:
44 0 for existent and nonempty,
45 1 for existent and probably (but not necessarily) empty,
46 2 for nonexistent */
47 static int p_rfc934_nesting; /* RFC 934 nesting level */
48 static char *p_name[3]; /* filenames in patch headers */
49 static char const *invalid_names[2];
50 bool p_copy[2]; /* Does this patch create a copy? */
51 bool p_rename[2]; /* Does this patch rename a file? */
52 static char *p_timestr[2]; /* timestamps as strings */
53 static char *p_sha1[2]; /* SHA1 checksums */
54 static mode_t p_mode[2]; /* file modes */
55 static off_t p_filesize; /* size of the patch file */
56 static lin p_first; /* 1st line number */
57 static lin p_newfirst; /* 1st line number of replacement */
58 static lin p_ptrn_lines; /* # lines in pattern */
59 static lin p_repl_lines; /* # lines in replacement text */
60 static lin p_end = -1; /* last line in hunk */
61 static lin p_max; /* max allowed value of p_end */
62 static lin p_prefix_context; /* # of prefix context lines */
63 static lin p_suffix_context; /* # of suffix context lines */
64 static lin p_input_line; /* current line # from patch file */
65 static char **p_line; /* the text of the hunk */
66 static size_t *p_len; /* line length including \n if any */
67 static char *p_Char; /* +, -, and ! */
68 static lin hunkmax = INITHUNKMAX; /* size of above arrays */
69 static size_t p_indent; /* indent to patch */
70 static bool p_strip_trailing_cr; /* true if stripping trailing \r */
71 static bool p_pass_comments_through; /* true if not ignoring # lines */
72 static file_offset p_base; /* where to intuit this time */
73 static lin p_bline; /* line # of p_base */
74 static file_offset p_start; /* where intuit found a patch */
75 static lin p_sline; /* and the line number for it */
76 static lin p_hunk_beg; /* line number of current hunk */
77 static lin p_efake = -1; /* end of faked up lines--don't free */
78 static lin p_bfake = -1; /* beg of faked up lines */
79 static char *p_c_function; /* the C function a hunk is in */
80 static bool p_git_diff; /* true if this is a git style diff */
81
82 static char *scan_linenum (char *, lin *);
83 static enum diff intuit_diff_type (bool, mode_t *);
84 static enum nametype best_name (char * const *, int const *);
85 static int prefix_components (char *, bool);
86 static size_t pget_line (size_t, int, bool, bool);
87 static size_t get_line (void);
88 static bool incomplete_line (void);
89 static bool grow_hunkmax (void);
90 static void malformed (void) __attribute__ ((noreturn));
91 static void next_intuit_at (file_offset, lin);
92 static void skip_to (file_offset, lin);
93 static char get_ed_command_letter (char const *);
94
95 /* Prepare to look for the next patch in the patch file. */
96
97 void
re_patch(void)98 re_patch (void)
99 {
100 p_first = 0;
101 p_newfirst = 0;
102 p_ptrn_lines = 0;
103 p_repl_lines = 0;
104 p_end = -1;
105 p_max = 0;
106 p_indent = 0;
107 p_strip_trailing_cr = false;
108 }
109
110 /* Open the patch file at the beginning of time. */
111
112 void
open_patch_file(char const * filename)113 open_patch_file (char const *filename)
114 {
115 file_offset file_pos = 0;
116 file_offset pos;
117 struct stat st;
118
119 if (!filename || !*filename || strEQ (filename, "-"))
120 pfp = stdin;
121 else
122 {
123 pfp = fopen (filename, binary_transput ? "rb" : "r");
124 if (!pfp)
125 pfatal ("Can't open patch file %s", quotearg (filename));
126 }
127 #if HAVE_SETMODE_DOS
128 if (binary_transput)
129 {
130 if (isatty (fileno (pfp)))
131 fatal ("cannot read binary data from tty on this platform");
132 setmode (fileno (pfp), O_BINARY);
133 }
134 #endif
135 if (fstat (fileno (pfp), &st) != 0)
136 pfatal ("fstat");
137 if (S_ISREG (st.st_mode) && (pos = file_tell (pfp)) != -1)
138 file_pos = pos;
139 else
140 {
141 size_t charsread;
142 int fd;
143 FILE *read_pfp = pfp;
144 fd = make_tempfile (&TMPPATNAME, 'p', NULL, O_RDWR | O_BINARY, 0);
145 if (fd == -1)
146 pfatal ("Can't create temporary file %s", TMPPATNAME);
147 TMPPATNAME_needs_removal = true;
148 pfp = fdopen (fd, "w+b");
149 if (! pfp)
150 pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME));
151 for (st.st_size = 0;
152 (charsread = fread (buf, 1, bufsize, read_pfp)) != 0;
153 st.st_size += charsread)
154 if (fwrite (buf, 1, charsread, pfp) != charsread)
155 write_fatal ();
156 if (ferror (read_pfp) || fclose (read_pfp) != 0)
157 read_fatal ();
158 if (fflush (pfp) != 0
159 || file_seek (pfp, (file_offset) 0, SEEK_SET) != 0)
160 write_fatal ();
161 }
162 p_filesize = st.st_size;
163 if (p_filesize != (file_offset) p_filesize)
164 fatal ("patch file is too long");
165 next_intuit_at (file_pos, 1);
166 }
167
168 /* Make sure our dynamically realloced tables are malloced to begin with. */
169
170 static void
set_hunkmax(void)171 set_hunkmax (void)
172 {
173 if (!p_line)
174 p_line = xmalloc (hunkmax * sizeof *p_line);
175 if (!p_len)
176 p_len = xmalloc (hunkmax * sizeof *p_len);
177 if (!p_Char)
178 p_Char = xmalloc (hunkmax * sizeof *p_Char);
179 }
180
181 /* Enlarge the arrays containing the current hunk of patch. */
182
183 static bool
grow_hunkmax(void)184 grow_hunkmax (void)
185 {
186 hunkmax *= 2;
187 assert (p_line && p_len && p_Char);
188 if ((p_line = realloc (p_line, hunkmax * sizeof (*p_line)))
189 && (p_len = realloc (p_len, hunkmax * sizeof (*p_len)))
190 && (p_Char = realloc (p_Char, hunkmax * sizeof (*p_Char))))
191 return true;
192 if (!using_plan_a)
193 xalloc_die ();
194 /* Don't free previous values of p_line etc.,
195 since some broken implementations free them for us.
196 Whatever is null will be allocated again from within plan_a (),
197 of all places. */
198 return false;
199 }
200
201 static bool
maybe_reverse(char const * name,bool nonexistent,bool is_empty)202 maybe_reverse (char const *name, bool nonexistent, bool is_empty)
203 {
204 bool looks_reversed = (! is_empty) < p_says_nonexistent[reverse ^ is_empty];
205
206 /* Allow to create and delete empty files when we know that they are empty:
207 in the "diff --git" format, we know that from the index header. */
208 if (is_empty
209 && p_says_nonexistent[reverse ^ nonexistent] == 1
210 && p_says_nonexistent[! reverse ^ nonexistent] == 2)
211 return false;
212
213 if (looks_reversed)
214 reverse ^=
215 ok_to_reverse ("The next patch%s would %s the file %s,\nwhich %s!",
216 reverse ? ", when reversed," : "",
217 (nonexistent ? "delete"
218 : is_empty ? "empty out"
219 : "create"),
220 quotearg (name),
221 (nonexistent ? "does not exist"
222 : is_empty ? "is already empty"
223 : "already exists"));
224 return looks_reversed;
225 }
226
227 /* True if the remainder of the patch file contains a diff of some sort. */
228
229 bool
there_is_another_patch(bool need_header,mode_t * file_type)230 there_is_another_patch (bool need_header, mode_t *file_type)
231 {
232 if (p_base != 0 && p_base >= p_filesize) {
233 if (verbosity == VERBOSE)
234 say ("done\n");
235 return false;
236 }
237 if (verbosity == VERBOSE)
238 say ("Hmm...");
239 diff_type = intuit_diff_type (need_header, file_type);
240 if (diff_type == NO_DIFF) {
241 if (verbosity == VERBOSE)
242 say (p_base
243 ? " Ignoring the trailing garbage.\ndone\n"
244 : " I can't seem to find a patch in there anywhere.\n");
245 if (! p_base && p_filesize)
246 fatal ("Only garbage was found in the patch input.");
247 return false;
248 }
249 if (skip_rest_of_patch)
250 {
251 Fseek (pfp, p_start, SEEK_SET);
252 p_input_line = p_sline - 1;
253 return true;
254 }
255 if (verbosity == VERBOSE)
256 say (" %sooks like %s to me...\n",
257 (p_base == 0 ? "L" : "The next patch l"),
258 diff_type == UNI_DIFF ? "a unified diff" :
259 diff_type == CONTEXT_DIFF ? "a context diff" :
260 diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
261 diff_type == NORMAL_DIFF ? "a normal diff" :
262 diff_type == GIT_BINARY_DIFF ? "a git binary diff" :
263 "an ed script" );
264
265 if (no_strip_trailing_cr)
266 p_strip_trailing_cr = false;
267
268 if (verbosity != SILENT)
269 {
270 if (p_indent)
271 say ("(Patch is indented %lu space%s.)\n",
272 (unsigned long int) p_indent, p_indent==1?"":"s");
273 if (p_strip_trailing_cr)
274 say ("(Stripping trailing CRs from patch; use --binary to disable.)\n");
275 if (! inname)
276 {
277 char numbuf[LINENUM_LENGTH_BOUND + 1];
278 say ("can't find file to patch at input line %s\n",
279 format_linenum (numbuf, p_sline));
280 if (diff_type != ED_DIFF && diff_type != NORMAL_DIFF)
281 say (strippath == -1
282 ? "Perhaps you should have used the -p or --strip option?\n"
283 : "Perhaps you used the wrong -p or --strip option?\n");
284 }
285 }
286
287 skip_to(p_start,p_sline);
288 while (!inname) {
289 char *t;
290 if (force | batch) {
291 say ("No file to patch. Skipping patch.\n");
292 skip_rest_of_patch = true;
293 return true;
294 }
295 ask ("File to patch: ");
296 t = buf + strlen (buf);
297 if (t > buf + 1 && *(t - 1) == '\n')
298 {
299 inname = xmemdup0 (buf, t - buf - 1);
300 inerrno = stat_file (inname, &instat);
301 if (inerrno)
302 {
303 perror (inname);
304 fflush (stderr);
305 free (inname);
306 inname = 0;
307 }
308 else
309 invc = -1;
310 }
311 if (!inname) {
312 ask ("Skip this patch? [y] ");
313 if (*buf != 'n') {
314 if (verbosity != SILENT)
315 say ("Skipping patch.\n");
316 skip_rest_of_patch = true;
317 return true;
318 }
319 }
320 }
321 return true;
322 }
323
324 static mode_t _GL_ATTRIBUTE_PURE
fetchmode(char const * str)325 fetchmode (char const *str)
326 {
327 const char *s;
328 mode_t mode;
329
330 while (ISSPACE ((unsigned char) *str))
331 str++;
332
333 for (s = str, mode = 0; s < str + 6; s++)
334 {
335 if (*s >= '0' && *s <= '7')
336 mode = (mode << 3) + (*s - '0');
337 else
338 {
339 mode = 0;
340 break;
341 }
342 }
343 if (*s == '\r')
344 s++;
345 if (*s != '\n')
346 mode = 0;
347
348 /* NOTE: The "diff --git" format always sets the file mode permission
349 bits of symlinks to 0. (On Linux, symlinks actually always have
350 0777 permissions, so this is not even consistent.) */
351
352 return mode;
353 }
354
355 static void
get_sha1(char ** sha1,char const * start,char const * end)356 get_sha1(char **sha1, char const *start, char const *end)
357 {
358 unsigned int len = end - start;
359 *sha1 = xmalloc (len + 1);
360 memcpy (*sha1, start, len);
361 (*sha1)[len] = 0;
362 }
363
364 static int _GL_ATTRIBUTE_PURE
sha1_says_nonexistent(char const * sha1)365 sha1_says_nonexistent(char const *sha1)
366 {
367 char const *empty_sha1 = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391";
368 char const *s;
369
370 /* Nonexisting files have an all-zero checksum. */
371 for (s = sha1; *s; s++)
372 if (*s != '0')
373 break;
374 if (! *s)
375 return 2;
376
377 /* Empty files have empty_sha1 as their checksum. */
378 for (s = sha1; *s; s++, empty_sha1++)
379 if (*s != *empty_sha1)
380 break;
381 return ! *s;
382 }
383
384 static char const * _GL_ATTRIBUTE_PURE
skip_hex_digits(char const * str)385 skip_hex_digits (char const *str)
386 {
387 char const *s;
388
389 for (s = str; (*s >= '0' && *s <= '9') || (*s >= 'a' && *s <= 'f'); s++)
390 /* do nothing */ ;
391 return s == str ? NULL : s;
392 }
393
394 static bool
name_is_valid(char const * name)395 name_is_valid (char const *name)
396 {
397 int i;
398 bool is_valid = true;
399
400 for (i = 0; i < ARRAY_SIZE (invalid_names); i++)
401 {
402 if (! invalid_names[i])
403 break;
404 if (! strcmp (invalid_names[i], name))
405 return false;
406 }
407
408 is_valid = filename_is_safe (name);
409
410 /* Allow any filename if we are in the filesystem root. */
411 if (! is_valid && cwd_is_root (name))
412 is_valid = true;
413
414 if (! is_valid)
415 {
416 say ("Ignoring potentially dangerous file name %s\n", quotearg (name));
417 if (i < ARRAY_SIZE (invalid_names))
418 invalid_names[i] = name;
419 }
420 return is_valid;
421 }
422
423 /* Determine what kind of diff is in the remaining part of the patch file. */
424
425 static enum diff
intuit_diff_type(bool need_header,mode_t * p_file_type)426 intuit_diff_type (bool need_header, mode_t *p_file_type)
427 {
428 file_offset this_line = 0;
429 file_offset first_command_line = -1;
430 char first_ed_command_letter = 0;
431 lin fcl_line = 0; /* Pacify 'gcc -W'. */
432 bool this_is_a_command = false;
433 bool stars_this_line = false;
434 bool extended_headers = false;
435 enum nametype i;
436 struct stat st[3];
437 int stat_errno[3];
438 int version_controlled[3];
439 enum diff retval;
440 mode_t file_type;
441 size_t indent = 0;
442
443 for (i = OLD; i <= INDEX; i++)
444 if (p_name[i]) {
445 free (p_name[i]);
446 p_name[i] = 0;
447 }
448 for (i = 0; i < ARRAY_SIZE (invalid_names); i++)
449 invalid_names[i] = NULL;
450 for (i = OLD; i <= NEW; i++)
451 if (p_timestr[i])
452 {
453 free(p_timestr[i]);
454 p_timestr[i] = 0;
455 }
456 for (i = OLD; i <= NEW; i++)
457 if (p_sha1[i])
458 {
459 free (p_sha1[i]);
460 p_sha1[i] = 0;
461 }
462 p_git_diff = false;
463 for (i = OLD; i <= NEW; i++)
464 {
465 p_mode[i] = 0;
466 p_copy[i] = false;
467 p_rename[i] = false;
468 }
469
470 /* Ed and normal format patches don't have filename headers. */
471 if (diff_type == ED_DIFF || diff_type == NORMAL_DIFF)
472 need_header = false;
473
474 version_controlled[OLD] = -1;
475 version_controlled[NEW] = -1;
476 version_controlled[INDEX] = -1;
477 p_rfc934_nesting = 0;
478 p_timestamp[OLD].tv_sec = p_timestamp[NEW].tv_sec = -1;
479 p_says_nonexistent[OLD] = p_says_nonexistent[NEW] = 0;
480 Fseek (pfp, p_base, SEEK_SET);
481 p_input_line = p_bline - 1;
482 for (;;) {
483 char *s;
484 char *t;
485 file_offset previous_line = this_line;
486 bool last_line_was_command = this_is_a_command;
487 bool stars_last_line = stars_this_line;
488 size_t indent_last_line = indent;
489 char ed_command_letter;
490 bool strip_trailing_cr;
491 size_t chars_read;
492
493 indent = 0;
494 this_line = file_tell (pfp);
495 chars_read = pget_line (0, 0, false, false);
496 if (chars_read == (size_t) -1)
497 xalloc_die ();
498 if (! chars_read) {
499 if (first_ed_command_letter) {
500 /* nothing but deletes!? */
501 p_start = first_command_line;
502 p_sline = fcl_line;
503 retval = ED_DIFF;
504 goto scan_exit;
505 }
506 else {
507 p_start = this_line;
508 p_sline = p_input_line;
509 if (extended_headers)
510 {
511 /* Patch contains no hunks; any diff type will do. */
512 retval = UNI_DIFF;
513 goto scan_exit;
514 }
515 return NO_DIFF;
516 }
517 }
518 strip_trailing_cr = 2 <= chars_read && buf[chars_read - 2] == '\r';
519 for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
520 if (*s == '\t')
521 indent = (indent + 8) & ~7;
522 else
523 indent++;
524 }
525 if (ISDIGIT (*s))
526 {
527 for (t = s + 1; ISDIGIT (*t) || *t == ','; t++)
528 /* do nothing */ ;
529 if (*t == 'd' || *t == 'c' || *t == 'a')
530 {
531 for (t++; ISDIGIT (*t) || *t == ','; t++)
532 /* do nothing */ ;
533 for (; *t == ' ' || *t == '\t'; t++)
534 /* do nothing */ ;
535 if (*t == '\r')
536 t++;
537 this_is_a_command = (*t == '\n');
538 }
539 }
540 if (! need_header
541 && first_command_line < 0
542 && ((ed_command_letter = get_ed_command_letter (s))
543 || this_is_a_command)) {
544 first_command_line = this_line;
545 first_ed_command_letter = ed_command_letter;
546 fcl_line = p_input_line;
547 p_indent = indent; /* assume this for now */
548 p_strip_trailing_cr = strip_trailing_cr;
549 }
550 if (!stars_last_line && strnEQ(s, "*** ", 4))
551 {
552 fetchname (s+4, strippath, &p_name[OLD], &p_timestr[OLD],
553 &p_timestamp[OLD]);
554 need_header = false;
555 }
556 else if (strnEQ(s, "+++ ", 4))
557 {
558 /* Swap with NEW below. */
559 fetchname (s+4, strippath, &p_name[OLD], &p_timestr[OLD],
560 &p_timestamp[OLD]);
561 need_header = false;
562 p_strip_trailing_cr = strip_trailing_cr;
563 }
564 else if (strnEQ(s, "Index:", 6))
565 {
566 fetchname (s+6, strippath, &p_name[INDEX], (char **) 0, NULL);
567 need_header = false;
568 p_strip_trailing_cr = strip_trailing_cr;
569 }
570 else if (strnEQ(s, "Prereq:", 7))
571 {
572 for (t = s + 7; ISSPACE ((unsigned char) *t); t++)
573 /* do nothing */ ;
574 revision = t;
575 for (t = revision; *t; t++)
576 if (ISSPACE ((unsigned char) *t))
577 {
578 char const *u;
579 for (u = t + 1; ISSPACE ((unsigned char) *u); u++)
580 /* do nothing */ ;
581 if (*u)
582 {
583 char numbuf[LINENUM_LENGTH_BOUND + 1];
584 say ("Prereq: with multiple words at line %s of patch\n",
585 format_linenum (numbuf, this_line));
586 }
587 break;
588 }
589 if (t == revision)
590 revision = 0;
591 else {
592 char oldc = *t;
593 *t = '\0';
594 revision = xstrdup (revision);
595 *t = oldc;
596 }
597 }
598 else if (strnEQ (s, "diff --git ", 11))
599 {
600 char const *u;
601
602 if (extended_headers)
603 {
604 p_start = this_line;
605 p_sline = p_input_line;
606 /* Patch contains no hunks; any diff type will do. */
607 retval = UNI_DIFF;
608 goto scan_exit;
609 }
610
611 for (i = OLD; i <= NEW; i++)
612 {
613 free (p_name[i]);
614 p_name[i] = 0;
615 }
616 if (! ((p_name[OLD] = parse_name (s + 11, strippath, &u))
617 && ISSPACE ((unsigned char) *u)
618 && (p_name[NEW] = parse_name (u, strippath, &u))
619 && (u = skip_spaces (u), ! *u)))
620 for (i = OLD; i <= NEW; i++)
621 {
622 free (p_name[i]);
623 p_name[i] = 0;
624 }
625 p_git_diff = true;
626 need_header = false;
627 }
628 else if (p_git_diff && strnEQ (s, "index ", 6))
629 {
630 char const *u, *v;
631 if ((u = skip_hex_digits (s + 6))
632 && u[0] == '.' && u[1] == '.'
633 && (v = skip_hex_digits (u + 2))
634 && (! *v || ISSPACE ((unsigned char) *v)))
635 {
636 get_sha1(&p_sha1[OLD], s + 6, u);
637 get_sha1(&p_sha1[NEW], u + 2, v);
638 p_says_nonexistent[OLD] = sha1_says_nonexistent (p_sha1[OLD]);
639 p_says_nonexistent[NEW] = sha1_says_nonexistent (p_sha1[NEW]);
640 if (*(v = skip_spaces (v)))
641 p_mode[OLD] = p_mode[NEW] = fetchmode (v);
642 extended_headers = true;
643 }
644 }
645 else if (p_git_diff && strnEQ (s, "old mode ", 9))
646 {
647 p_mode[OLD] = fetchmode (s + 9);
648 extended_headers = true;
649 }
650 else if (p_git_diff && strnEQ (s, "new mode ", 9))
651 {
652 p_mode[NEW] = fetchmode (s + 9);
653 extended_headers = true;
654 }
655 else if (p_git_diff && strnEQ (s, "deleted file mode ", 18))
656 {
657 p_mode[OLD] = fetchmode (s + 18);
658 p_says_nonexistent[NEW] = 2;
659 extended_headers = true;
660 }
661 else if (p_git_diff && strnEQ (s, "new file mode ", 14))
662 {
663 p_mode[NEW] = fetchmode (s + 14);
664 p_says_nonexistent[OLD] = 2;
665 extended_headers = true;
666 }
667 else if (p_git_diff && strnEQ (s, "rename from ", 12))
668 {
669 /* Git leaves out the prefix in the file name in this header,
670 so we can only ignore the file name. */
671 p_rename[OLD] = true;
672 extended_headers = true;
673 }
674 else if (p_git_diff && strnEQ (s, "rename to ", 10))
675 {
676 /* Git leaves out the prefix in the file name in this header,
677 so we can only ignore the file name. */
678 p_rename[NEW] = true;
679 extended_headers = true;
680 }
681 else if (p_git_diff && strnEQ (s, "copy from ", 10))
682 {
683 /* Git leaves out the prefix in the file name in this header,
684 so we can only ignore the file name. */
685 p_copy[OLD] = true;
686 extended_headers = true;
687 }
688 else if (p_git_diff && strnEQ (s, "copy to ", 8))
689 {
690 /* Git leaves out the prefix in the file name in this header,
691 so we can only ignore the file name. */
692 p_copy[NEW] = true;
693 extended_headers = true;
694 }
695 else if (p_git_diff && strnEQ (s, "GIT binary patch", 16))
696 {
697 p_start = this_line;
698 p_sline = p_input_line;
699 retval = GIT_BINARY_DIFF;
700 goto scan_exit;
701 }
702 else
703 {
704 for (t = s; t[0] == '-' && t[1] == ' '; t += 2)
705 /* do nothing */ ;
706 if (strnEQ(t, "--- ", 4))
707 {
708 struct timespec timestamp;
709 timestamp.tv_sec = -1;
710 fetchname (t+4, strippath, &p_name[NEW], &p_timestr[NEW],
711 ×tamp);
712 need_header = false;
713 if (timestamp.tv_sec != -1)
714 {
715 p_timestamp[NEW] = timestamp;
716 p_rfc934_nesting = (t - s) >> 1;
717 }
718 p_strip_trailing_cr = strip_trailing_cr;
719 }
720 }
721 if (need_header)
722 continue;
723 if ((diff_type == NO_DIFF || diff_type == ED_DIFF) &&
724 first_command_line >= 0 &&
725 strEQ(s, ".\n") ) {
726 p_start = first_command_line;
727 p_sline = fcl_line;
728 retval = ED_DIFF;
729 goto scan_exit;
730 }
731 if ((diff_type == NO_DIFF || diff_type == UNI_DIFF)
732 && strnEQ(s, "@@ -", 4)) {
733
734 /* 'p_name', 'p_timestr', and 'p_timestamp' are backwards;
735 swap them. */
736 struct timespec ti = p_timestamp[OLD];
737 p_timestamp[OLD] = p_timestamp[NEW];
738 p_timestamp[NEW] = ti;
739 t = p_name[OLD];
740 p_name[OLD] = p_name[NEW];
741 p_name[NEW] = t;
742 t = p_timestr[OLD];
743 p_timestr[OLD] = p_timestr[NEW];
744 p_timestr[NEW] = t;
745
746 s += 4;
747 if (s[0] == '0' && !ISDIGIT (s[1]))
748 p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD].tv_sec;
749 while (*s != ' ' && *s != '\n')
750 s++;
751 while (*s == ' ')
752 s++;
753 if (s[0] == '+' && s[1] == '0' && !ISDIGIT (s[2]))
754 p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW].tv_sec;
755 p_indent = indent;
756 p_start = this_line;
757 p_sline = p_input_line;
758 retval = UNI_DIFF;
759 if (! ((p_name[OLD] || ! p_timestamp[OLD].tv_sec)
760 && (p_name[NEW] || ! p_timestamp[NEW].tv_sec))
761 && ! p_name[INDEX] && need_header)
762 {
763 char numbuf[LINENUM_LENGTH_BOUND + 1];
764 say ("missing header for unified diff at line %s of patch\n",
765 format_linenum (numbuf, p_sline));
766 }
767 goto scan_exit;
768 }
769 stars_this_line = strnEQ(s, "********", 8);
770 if ((diff_type == NO_DIFF
771 || diff_type == CONTEXT_DIFF
772 || diff_type == NEW_CONTEXT_DIFF)
773 && stars_last_line && indent_last_line == indent
774 && strnEQ (s, "*** ", 4)) {
775 s += 4;
776 if (s[0] == '0' && !ISDIGIT (s[1]))
777 p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD].tv_sec;
778 /* if this is a new context diff the character just before */
779 /* the newline is a '*'. */
780 while (*s != '\n')
781 s++;
782 p_indent = indent;
783 p_strip_trailing_cr = strip_trailing_cr;
784 p_start = previous_line;
785 p_sline = p_input_line - 1;
786 retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
787
788 {
789 /* Scan the first hunk to see whether the file contents
790 appear to have been deleted. */
791 file_offset saved_p_base = p_base;
792 lin saved_p_bline = p_bline;
793 Fseek (pfp, previous_line, SEEK_SET);
794 p_input_line -= 2;
795 if (another_hunk (retval, false)
796 && ! p_repl_lines && p_newfirst == 1)
797 p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW].tv_sec;
798 next_intuit_at (saved_p_base, saved_p_bline);
799 }
800
801 if (! ((p_name[OLD] || ! p_timestamp[OLD].tv_sec)
802 && (p_name[NEW] || ! p_timestamp[NEW].tv_sec))
803 && ! p_name[INDEX] && need_header)
804 {
805 char numbuf[LINENUM_LENGTH_BOUND + 1];
806 say ("missing header for context diff at line %s of patch\n",
807 format_linenum (numbuf, p_sline));
808 }
809 goto scan_exit;
810 }
811 if ((diff_type == NO_DIFF || diff_type == NORMAL_DIFF) &&
812 last_line_was_command &&
813 (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
814 p_start = previous_line;
815 p_sline = p_input_line - 1;
816 p_indent = indent;
817 retval = NORMAL_DIFF;
818 goto scan_exit;
819 }
820 }
821
822 scan_exit:
823
824 /* The old, new, or old and new file types may be defined. When both
825 file types are defined, make sure they are the same, or else assume
826 we do not know the file type. */
827 file_type = p_mode[OLD] & S_IFMT;
828 if (file_type)
829 {
830 mode_t new_file_type = p_mode[NEW] & S_IFMT;
831 if (new_file_type && file_type != new_file_type)
832 file_type = 0;
833 }
834 else
835 {
836 file_type = p_mode[NEW] & S_IFMT;
837 if (! file_type)
838 file_type = S_IFREG;
839 }
840 *p_file_type = file_type;
841
842 /* To intuit 'inname', the name of the file to patch,
843 use the algorithm specified by POSIX 1003.1-2001 XCU lines 25680-26599
844 (with some modifications if posixly_correct is zero):
845
846 - Take the old and new names from the context header if present,
847 and take the index name from the 'Index:' line if present and
848 if either the old and new names are both absent
849 or posixly_correct is nonzero.
850 Consider the file names to be in the order (old, new, index).
851 - If some named files exist, use the first one if posixly_correct
852 is nonzero, the best one otherwise.
853 - If patch_get is nonzero, and no named files exist,
854 but an RCS or SCCS master file exists,
855 use the first named file with an RCS or SCCS master.
856 - If no named files exist, no RCS or SCCS master was found,
857 some names are given, posixly_correct is zero,
858 and the patch appears to create a file, then use the best name
859 requiring the creation of the fewest directories.
860 - Otherwise, report failure by setting 'inname' to 0;
861 this causes our invoker to ask the user for a file name. */
862
863 i = NONE;
864
865 if (!inname)
866 {
867 enum nametype i0 = NONE;
868
869 if (! posixly_correct && (p_name[OLD] || p_name[NEW]) && p_name[INDEX])
870 {
871 free (p_name[INDEX]);
872 p_name[INDEX] = 0;
873 }
874
875 for (i = OLD; i <= INDEX; i++)
876 if (p_name[i])
877 {
878 if (i0 != NONE && strcmp (p_name[i0], p_name[i]) == 0)
879 {
880 /* It's the same name as before; reuse stat results. */
881 stat_errno[i] = stat_errno[i0];
882 if (! stat_errno[i])
883 st[i] = st[i0];
884 }
885 else
886 {
887 stat_errno[i] = stat_file (p_name[i], &st[i]);
888 if (! stat_errno[i])
889 {
890 if (lookup_file_id (&st[i]) == DELETE_LATER)
891 stat_errno[i] = ENOENT;
892 else if (posixly_correct && name_is_valid (p_name[i]))
893 break;
894 }
895 }
896 i0 = i;
897 }
898
899 if (! posixly_correct)
900 {
901 /* The best of all existing files. */
902 i = best_name (p_name, stat_errno);
903
904 if (i == NONE && patch_get)
905 {
906 enum nametype nope = NONE;
907
908 for (i = OLD; i <= INDEX; i++)
909 if (p_name[i])
910 {
911 char const *cs;
912 char *getbuf;
913 char *diffbuf;
914 bool readonly = (outfile
915 && strcmp (outfile, p_name[i]) != 0);
916
917 if (nope == NONE || strcmp (p_name[nope], p_name[i]) != 0)
918 {
919 cs = (version_controller
920 (p_name[i], readonly, (struct stat *) 0,
921 &getbuf, &diffbuf));
922 version_controlled[i] = !! cs;
923 if (cs)
924 {
925 if (version_get (p_name[i], cs, false, readonly,
926 getbuf, &st[i]))
927 stat_errno[i] = 0;
928 else
929 version_controlled[i] = 0;
930
931 free (getbuf);
932 free (diffbuf);
933
934 if (! stat_errno[i])
935 break;
936 }
937 }
938
939 nope = i;
940 }
941 }
942
943 if (i0 != NONE
944 && (i == NONE || (st[i].st_mode & S_IFMT) == file_type)
945 && maybe_reverse (p_name[i == NONE ? i0 : i], i == NONE,
946 i == NONE || st[i].st_size == 0)
947 && i == NONE)
948 i = i0;
949
950 if (i == NONE && p_says_nonexistent[reverse])
951 {
952 int newdirs[3];
953 int newdirs_min = INT_MAX;
954 int distance_from_minimum[3];
955
956 for (i = OLD; i <= INDEX; i++)
957 if (p_name[i])
958 {
959 newdirs[i] = (prefix_components (p_name[i], false)
960 - prefix_components (p_name[i], true));
961 if (newdirs[i] < newdirs_min)
962 newdirs_min = newdirs[i];
963 }
964
965 for (i = OLD; i <= INDEX; i++)
966 if (p_name[i])
967 distance_from_minimum[i] = newdirs[i] - newdirs_min;
968
969 /* The best of the filenames which create the fewest directories. */
970 i = best_name (p_name, distance_from_minimum);
971 }
972 }
973 }
974
975 if ((pch_rename () || pch_copy ())
976 && ! inname
977 && ! ((i == OLD || i == NEW) &&
978 p_name[reverse] && p_name[! reverse] &&
979 name_is_valid (p_name[reverse]) &&
980 name_is_valid (p_name[! reverse])))
981 {
982 say ("Cannot %s file without two valid file names\n", pch_rename () ? "rename" : "copy");
983 skip_rest_of_patch = true;
984 }
985
986 if (i == NONE)
987 {
988 if (inname)
989 {
990 inerrno = stat_file (inname, &instat);
991 if (inerrno || (instat.st_mode & S_IFMT) == file_type)
992 maybe_reverse (inname, inerrno, inerrno || instat.st_size == 0);
993 }
994 else
995 inerrno = -1;
996 }
997 else
998 {
999 inname = xstrdup (p_name[i]);
1000 inerrno = stat_errno[i];
1001 invc = version_controlled[i];
1002 instat = st[i];
1003 }
1004
1005 return retval;
1006 }
1007
1008 /* Count the path name components in FILENAME's prefix.
1009 If CHECKDIRS is true, count only existing directories. */
1010 static int
prefix_components(char * filename,bool checkdirs)1011 prefix_components (char *filename, bool checkdirs)
1012 {
1013 int count = 0;
1014 struct stat stat_buf;
1015 int stat_result;
1016 char *f = filename + FILE_SYSTEM_PREFIX_LEN (filename);
1017
1018 if (*f)
1019 while (*++f)
1020 if (ISSLASH (f[0]) && ! ISSLASH (f[-1]))
1021 {
1022 if (checkdirs)
1023 {
1024 *f = '\0';
1025 stat_result = safe_stat (filename, &stat_buf);
1026 *f = '/';
1027 if (! (stat_result == 0 && S_ISDIR (stat_buf.st_mode)))
1028 break;
1029 }
1030
1031 count++;
1032 }
1033
1034 return count;
1035 }
1036
1037 /* Return the index of the best of NAME[OLD], NAME[NEW], and NAME[INDEX].
1038 Ignore null names, and ignore NAME[i] if IGNORE[i] is nonzero.
1039 Return NONE if all names are ignored. */
1040 static enum nametype
best_name(char * const * name,int const * ignore)1041 best_name (char *const *name, int const *ignore)
1042 {
1043 enum nametype i;
1044 int components[3];
1045 int components_min = INT_MAX;
1046 size_t basename_len[3];
1047 size_t basename_len_min = SIZE_MAX;
1048 size_t len[3];
1049 size_t len_min = SIZE_MAX;
1050
1051 for (i = OLD; i <= INDEX; i++)
1052 if (name[i] && !ignore[i])
1053 {
1054 /* Take the names with the fewest prefix components. */
1055 components[i] = prefix_components (name[i], false);
1056 if (components_min < components[i])
1057 continue;
1058 components_min = components[i];
1059
1060 /* Of those, take the names with the shortest basename. */
1061 basename_len[i] = base_len (name[i]);
1062 if (basename_len_min < basename_len[i])
1063 continue;
1064 basename_len_min = basename_len[i];
1065
1066 /* Of those, take the shortest names. */
1067 len[i] = strlen (name[i]);
1068 if (len_min < len[i])
1069 continue;
1070 len_min = len[i];
1071 }
1072
1073 /* Of those, take the first name. */
1074 for (i = OLD; i <= INDEX; i++)
1075 if (name[i] && !ignore[i]
1076 && name_is_valid (name[i])
1077 && components[i] == components_min
1078 && basename_len[i] == basename_len_min
1079 && len[i] == len_min)
1080 break;
1081
1082 return i;
1083 }
1084
1085 /* Remember where this patch ends so we know where to start up again. */
1086
1087 static void
next_intuit_at(file_offset file_pos,lin file_line)1088 next_intuit_at (file_offset file_pos, lin file_line)
1089 {
1090 p_base = file_pos;
1091 p_bline = file_line;
1092 }
1093
1094 /* Basically a verbose fseek() to the actual diff listing. */
1095
1096 static void
skip_to(file_offset file_pos,lin file_line)1097 skip_to (file_offset file_pos, lin file_line)
1098 {
1099 FILE *i = pfp;
1100 FILE *o = stdout;
1101 int c;
1102
1103 assert(p_base <= file_pos);
1104 if ((verbosity == VERBOSE || !inname) && p_base < file_pos) {
1105 Fseek (i, p_base, SEEK_SET);
1106 say ("The text leading up to this was:\n--------------------------\n");
1107
1108 while (file_tell (i) < file_pos)
1109 {
1110 putc ('|', o);
1111 do
1112 {
1113 if ((c = getc (i)) == EOF)
1114 read_fatal ();
1115 putc (c, o);
1116 }
1117 while (c != '\n');
1118 }
1119
1120 say ("--------------------------\n");
1121 }
1122 else
1123 Fseek (i, file_pos, SEEK_SET);
1124 p_input_line = file_line - 1;
1125 }
1126
1127 /* Make this a function for better debugging. */
1128 static void
malformed(void)1129 malformed (void)
1130 {
1131 char numbuf[LINENUM_LENGTH_BOUND + 1];
1132 fatal ("malformed patch at line %s: %s",
1133 format_linenum (numbuf, p_input_line), buf);
1134 /* about as informative as "Syntax error" in C */
1135 }
1136
1137 /* Parse a line number from a string.
1138 Return the address of the first char after the number. */
1139 static char *
scan_linenum(char * s0,lin * linenum)1140 scan_linenum (char *s0, lin *linenum)
1141 {
1142 char *s;
1143 lin n = 0;
1144 bool overflow = false;
1145 char numbuf[LINENUM_LENGTH_BOUND + 1];
1146
1147 for (s = s0; ISDIGIT (*s); s++)
1148 {
1149 lin new_n = 10 * n + (*s - '0');
1150 overflow |= new_n / 10 != n;
1151 n = new_n;
1152 }
1153
1154 if (s == s0)
1155 fatal ("missing line number at line %s: %s",
1156 format_linenum (numbuf, p_input_line), buf);
1157
1158 if (overflow)
1159 fatal ("line number %.*s is too large at line %s: %s",
1160 (int) (s - s0), s0, format_linenum (numbuf, p_input_line), buf);
1161
1162 *linenum = n;
1163 return s;
1164 }
1165
1166 /* 1 if there is more of the current diff listing to process;
1167 0 if not; -1 if ran out of memory. */
1168
1169 int
another_hunk(enum diff difftype,bool rev)1170 another_hunk (enum diff difftype, bool rev)
1171 {
1172 char *s;
1173 lin context = 0;
1174 size_t chars_read;
1175 char numbuf0[LINENUM_LENGTH_BOUND + 1];
1176 char numbuf1[LINENUM_LENGTH_BOUND + 1];
1177 char numbuf2[LINENUM_LENGTH_BOUND + 1];
1178 char numbuf3[LINENUM_LENGTH_BOUND + 1];
1179
1180 set_hunkmax();
1181
1182 while (p_end >= 0) {
1183 if (p_end == p_efake)
1184 p_end = p_bfake; /* don't free twice */
1185 else
1186 free(p_line[p_end]);
1187 p_end--;
1188 }
1189 assert(p_end == -1);
1190 p_efake = -1;
1191
1192 if (p_c_function)
1193 {
1194 free (p_c_function);
1195 p_c_function = NULL;
1196 }
1197
1198 p_max = hunkmax; /* gets reduced when --- found */
1199 if (difftype == CONTEXT_DIFF || difftype == NEW_CONTEXT_DIFF) {
1200 file_offset line_beginning = file_tell (pfp);
1201 /* file pos of the current line */
1202 lin repl_beginning = 0; /* index of --- line */
1203 lin fillcnt = 0; /* #lines of missing ptrn or repl */
1204 lin fillsrc; /* index of first line to copy */
1205 lin filldst; /* index of first missing line */
1206 bool ptrn_spaces_eaten = false; /* ptrn was slightly misformed */
1207 bool some_context = false; /* (perhaps internal) context seen */
1208 bool repl_could_be_missing = true;
1209 bool ptrn_missing = false; /* The pattern was missing. */
1210 bool repl_missing = false; /* Likewise for replacement. */
1211 file_offset repl_backtrack_position = 0;
1212 /* file pos of first repl line */
1213 lin repl_patch_line; /* input line number for same */
1214 lin repl_context; /* context for same */
1215 lin ptrn_prefix_context = -1; /* lines in pattern prefix context */
1216 lin ptrn_suffix_context = -1; /* lines in pattern suffix context */
1217 lin repl_prefix_context = -1; /* lines in replac. prefix context */
1218 lin ptrn_copiable = 0; /* # of copiable lines in ptrn */
1219 lin repl_copiable = 0; /* Likewise for replacement. */
1220
1221 /* Pacify 'gcc -Wall'. */
1222 fillsrc = filldst = repl_patch_line = repl_context = 0;
1223
1224 chars_read = get_line ();
1225 if (chars_read == (size_t) -1
1226 || chars_read <= 8
1227 || strncmp (buf, "********", 8) != 0) {
1228 next_intuit_at(line_beginning,p_input_line);
1229 return chars_read == (size_t) -1 ? -1 : 0;
1230 }
1231 s = buf;
1232 while (*s == '*')
1233 s++;
1234 if (*s == ' ')
1235 {
1236 p_c_function = s;
1237 while (*s != '\n')
1238 s++;
1239 *s = '\0';
1240 p_c_function = savestr (p_c_function);
1241 if (! p_c_function)
1242 return -1;
1243 }
1244 p_hunk_beg = p_input_line + 1;
1245 while (p_end < p_max) {
1246 chars_read = get_line ();
1247 if (chars_read == (size_t) -1)
1248 return -1;
1249 if (!chars_read) {
1250 if (repl_beginning && repl_could_be_missing) {
1251 repl_missing = true;
1252 goto hunk_done;
1253 }
1254 if (p_max - p_end < 4) {
1255 strcpy (buf, " \n"); /* assume blank lines got chopped */
1256 chars_read = 3;
1257 } else {
1258 fatal ("unexpected end of file in patch");
1259 }
1260 }
1261 p_end++;
1262 if (p_end == hunkmax)
1263 fatal ("unterminated hunk starting at line %s; giving up at line %s: %s",
1264 format_linenum (numbuf0, pch_hunk_beg ()),
1265 format_linenum (numbuf1, p_input_line), buf);
1266 assert(p_end < hunkmax);
1267 p_Char[p_end] = *buf;
1268 p_len[p_end] = 0;
1269 p_line[p_end] = 0;
1270 switch (*buf) {
1271 case '*':
1272 if (strnEQ(buf, "********", 8)) {
1273 if (repl_beginning && repl_could_be_missing) {
1274 repl_missing = true;
1275 goto hunk_done;
1276 }
1277 else
1278 fatal ("unexpected end of hunk at line %s",
1279 format_linenum (numbuf0, p_input_line));
1280 }
1281 if (p_end != 0) {
1282 if (repl_beginning && repl_could_be_missing) {
1283 repl_missing = true;
1284 goto hunk_done;
1285 }
1286 fatal ("unexpected '***' at line %s: %s",
1287 format_linenum (numbuf0, p_input_line), buf);
1288 }
1289 context = 0;
1290 p_len[p_end] = strlen (buf);
1291 if (! (p_line[p_end] = savestr (buf))) {
1292 p_end--;
1293 return -1;
1294 }
1295 for (s = buf; *s && !ISDIGIT (*s); s++)
1296 /* do nothing */ ;
1297 if (strnEQ(s,"0,0",3))
1298 remove_prefix (s, 2);
1299 s = scan_linenum (s, &p_first);
1300 if (*s == ',') {
1301 while (*s && !ISDIGIT (*s))
1302 s++;
1303 scan_linenum (s, &p_ptrn_lines);
1304 p_ptrn_lines += 1 - p_first;
1305 if (p_ptrn_lines < 0)
1306 malformed ();
1307 }
1308 else if (p_first)
1309 p_ptrn_lines = 1;
1310 else {
1311 p_ptrn_lines = 0;
1312 p_first = 1;
1313 }
1314 if (p_first >= LINENUM_MAX - p_ptrn_lines ||
1315 p_ptrn_lines >= LINENUM_MAX - 6)
1316 malformed ();
1317 p_max = p_ptrn_lines + 6; /* we need this much at least */
1318 while (p_max + 1 >= hunkmax)
1319 if (! grow_hunkmax ())
1320 return -1;
1321 p_max = hunkmax;
1322 break;
1323 case '-':
1324 if (buf[1] != '-')
1325 goto change_line;
1326 if (ptrn_prefix_context == -1)
1327 ptrn_prefix_context = context;
1328 ptrn_suffix_context = context;
1329 if (repl_beginning
1330 || p_end <= 0
1331 || (p_end
1332 != p_ptrn_lines + 1 + (p_Char[p_end - 1] == '\n')))
1333 {
1334 if (p_end == 1)
1335 {
1336 /* 'Old' lines were omitted. Set up to fill
1337 them in from 'new' context lines. */
1338 ptrn_missing = true;
1339 p_end = p_ptrn_lines + 1;
1340 ptrn_prefix_context = ptrn_suffix_context = -1;
1341 fillsrc = p_end + 1;
1342 filldst = 1;
1343 fillcnt = p_ptrn_lines;
1344 }
1345 else if (! repl_beginning)
1346 fatal ("%s '---' at line %s; check line numbers at line %s",
1347 (p_end <= p_ptrn_lines
1348 ? "Premature"
1349 : "Overdue"),
1350 format_linenum (numbuf0, p_input_line),
1351 format_linenum (numbuf1, p_hunk_beg));
1352 else if (! repl_could_be_missing)
1353 fatal ("duplicate '---' at line %s; check line numbers at line %s",
1354 format_linenum (numbuf0, p_input_line),
1355 format_linenum (numbuf1,
1356 p_hunk_beg + repl_beginning));
1357 else
1358 {
1359 repl_missing = true;
1360 goto hunk_done;
1361 }
1362 }
1363 repl_beginning = p_end;
1364 repl_backtrack_position = file_tell (pfp);
1365 repl_patch_line = p_input_line;
1366 repl_context = context;
1367 p_len[p_end] = strlen (buf);
1368 if (! (p_line[p_end] = savestr (buf)))
1369 {
1370 p_end--;
1371 return -1;
1372 }
1373 p_Char[p_end] = '=';
1374 for (s = buf; *s && ! ISDIGIT (*s); s++)
1375 /* do nothing */ ;
1376 s = scan_linenum (s, &p_newfirst);
1377 if (*s == ',')
1378 {
1379 do
1380 {
1381 if (!*++s)
1382 malformed ();
1383 }
1384 while (! ISDIGIT (*s));
1385 scan_linenum (s, &p_repl_lines);
1386 p_repl_lines += 1 - p_newfirst;
1387 if (p_repl_lines < 0)
1388 malformed ();
1389 }
1390 else if (p_newfirst)
1391 p_repl_lines = 1;
1392 else
1393 {
1394 p_repl_lines = 0;
1395 p_newfirst = 1;
1396 }
1397 if (p_newfirst >= LINENUM_MAX - p_repl_lines ||
1398 p_repl_lines >= LINENUM_MAX - p_end)
1399 malformed ();
1400 p_max = p_repl_lines + p_end;
1401 while (p_max + 1 >= hunkmax)
1402 if (! grow_hunkmax ())
1403 return -1;
1404 if (p_repl_lines != ptrn_copiable
1405 && (p_prefix_context != 0
1406 || context != 0
1407 || p_repl_lines != 1))
1408 repl_could_be_missing = false;
1409 context = 0;
1410 break;
1411 case '+': case '!':
1412 repl_could_be_missing = false;
1413 change_line:
1414 s = buf + 1;
1415 chars_read--;
1416 if (*s == '\n' && canonicalize_ws) {
1417 strcpy (s, " \n");
1418 chars_read = 2;
1419 }
1420 if (*s == ' ' || *s == '\t') {
1421 s++;
1422 chars_read--;
1423 } else if (repl_beginning && repl_could_be_missing) {
1424 repl_missing = true;
1425 goto hunk_done;
1426 }
1427 if (! repl_beginning)
1428 {
1429 if (ptrn_prefix_context == -1)
1430 ptrn_prefix_context = context;
1431 }
1432 else
1433 {
1434 if (repl_prefix_context == -1)
1435 repl_prefix_context = context;
1436 }
1437 chars_read -=
1438 (1 < chars_read
1439 && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1440 && incomplete_line ());
1441 p_len[p_end] = chars_read;
1442 p_line[p_end] = savebuf (s, chars_read);
1443 if (chars_read && ! p_line[p_end]) {
1444 p_end--;
1445 return -1;
1446 }
1447 context = 0;
1448 break;
1449 case '\t': case '\n': /* assume spaces got eaten */
1450 s = buf;
1451 if (*buf == '\t') {
1452 s++;
1453 chars_read--;
1454 }
1455 if (repl_beginning && repl_could_be_missing &&
1456 (!ptrn_spaces_eaten || difftype == NEW_CONTEXT_DIFF) ) {
1457 repl_missing = true;
1458 goto hunk_done;
1459 }
1460 chars_read -=
1461 (1 < chars_read
1462 && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1463 && incomplete_line ());
1464 p_len[p_end] = chars_read;
1465 p_line[p_end] = savebuf (buf, chars_read);
1466 if (chars_read && ! p_line[p_end]) {
1467 p_end--;
1468 return -1;
1469 }
1470 if (p_end != p_ptrn_lines + 1) {
1471 ptrn_spaces_eaten |= (repl_beginning != 0);
1472 some_context = true;
1473 context++;
1474 if (repl_beginning)
1475 repl_copiable++;
1476 else
1477 ptrn_copiable++;
1478 p_Char[p_end] = ' ';
1479 }
1480 break;
1481 case ' ':
1482 s = buf + 1;
1483 chars_read--;
1484 if (*s == '\n' && canonicalize_ws) {
1485 strcpy (s, "\n");
1486 chars_read = 2;
1487 }
1488 if (*s == ' ' || *s == '\t') {
1489 s++;
1490 chars_read--;
1491 } else if (repl_beginning && repl_could_be_missing) {
1492 repl_missing = true;
1493 goto hunk_done;
1494 }
1495 some_context = true;
1496 context++;
1497 if (repl_beginning)
1498 repl_copiable++;
1499 else
1500 ptrn_copiable++;
1501 chars_read -=
1502 (1 < chars_read
1503 && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1504 && incomplete_line ());
1505 p_len[p_end] = chars_read;
1506 p_line[p_end] = savebuf (s, chars_read);
1507 if (chars_read && ! p_line[p_end]) {
1508 p_end--;
1509 return -1;
1510 }
1511 break;
1512 default:
1513 if (repl_beginning && repl_could_be_missing) {
1514 repl_missing = true;
1515 goto hunk_done;
1516 }
1517 malformed ();
1518 }
1519 }
1520
1521 hunk_done:
1522 if (p_end >=0 && !repl_beginning)
1523 fatal ("no '---' found in patch at line %s",
1524 format_linenum (numbuf0, pch_hunk_beg ()));
1525
1526 if (repl_missing) {
1527
1528 /* reset state back to just after --- */
1529 p_input_line = repl_patch_line;
1530 context = repl_context;
1531 for (p_end--; p_end > repl_beginning; p_end--)
1532 free(p_line[p_end]);
1533 Fseek (pfp, repl_backtrack_position, SEEK_SET);
1534
1535 /* redundant 'new' context lines were omitted - set */
1536 /* up to fill them in from the old file context */
1537 fillsrc = 1;
1538 filldst = repl_beginning+1;
1539 fillcnt = p_repl_lines;
1540 p_end = p_max;
1541 }
1542 else if (! ptrn_missing && ptrn_copiable != repl_copiable)
1543 fatal ("context mangled in hunk at line %s",
1544 format_linenum (numbuf0, p_hunk_beg));
1545 else if (!some_context && fillcnt == 1) {
1546 /* the first hunk was a null hunk with no context */
1547 /* and we were expecting one line -- fix it up. */
1548 while (filldst < p_end) {
1549 p_line[filldst] = p_line[filldst+1];
1550 p_Char[filldst] = p_Char[filldst+1];
1551 p_len[filldst] = p_len[filldst+1];
1552 filldst++;
1553 }
1554 #if 0
1555 repl_beginning--; /* this doesn't need to be fixed */
1556 #endif
1557 p_end--;
1558 p_first++; /* do append rather than insert */
1559 fillcnt = 0;
1560 p_ptrn_lines = 0;
1561 }
1562
1563 p_prefix_context = ((repl_prefix_context == -1
1564 || (ptrn_prefix_context != -1
1565 && ptrn_prefix_context < repl_prefix_context))
1566 ? ptrn_prefix_context : repl_prefix_context);
1567 p_suffix_context = ((ptrn_suffix_context != -1
1568 && ptrn_suffix_context < context)
1569 ? ptrn_suffix_context : context);
1570 if (p_prefix_context == -1 || p_suffix_context == -1)
1571 fatal ("replacement text or line numbers mangled in hunk at line %s",
1572 format_linenum (numbuf0, p_hunk_beg));
1573
1574 if (difftype == CONTEXT_DIFF
1575 && (fillcnt
1576 || (p_first > 1
1577 && p_prefix_context + p_suffix_context < ptrn_copiable))) {
1578 if (verbosity == VERBOSE)
1579 say ("%s\n%s\n%s\n",
1580 "(Fascinating -- this is really a new-style context diff but without",
1581 "the telltale extra asterisks on the *** line that usually indicate",
1582 "the new style...)");
1583 diff_type = difftype = NEW_CONTEXT_DIFF;
1584 }
1585
1586 /* if there were omitted context lines, fill them in now */
1587 if (fillcnt) {
1588 p_bfake = filldst; /* remember where not to free() */
1589 p_efake = filldst + fillcnt - 1;
1590 while (fillcnt-- > 0) {
1591 while (fillsrc <= p_end && fillsrc != repl_beginning
1592 && p_Char[fillsrc] != ' ')
1593 fillsrc++;
1594 if (p_end < fillsrc || fillsrc == repl_beginning)
1595 {
1596 fatal ("replacement text or line numbers mangled in hunk at line %s",
1597 format_linenum (numbuf0, p_hunk_beg));
1598 }
1599 p_line[filldst] = p_line[fillsrc];
1600 p_Char[filldst] = p_Char[fillsrc];
1601 p_len[filldst] = p_len[fillsrc];
1602 fillsrc++; filldst++;
1603 }
1604 while (fillsrc <= p_end && fillsrc != repl_beginning)
1605 {
1606 if (p_Char[fillsrc] == ' ')
1607 fatal ("replacement text or line numbers mangled in hunk at line %s",
1608 format_linenum (numbuf0, p_hunk_beg));
1609 fillsrc++;
1610 }
1611 if (debug & 64)
1612 printf ("fillsrc %s, filldst %s, rb %s, e+1 %s\n",
1613 format_linenum (numbuf0, fillsrc),
1614 format_linenum (numbuf1, filldst),
1615 format_linenum (numbuf2, repl_beginning),
1616 format_linenum (numbuf3, p_end + 1));
1617 assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
1618 assert(filldst==p_end+1 || filldst==repl_beginning);
1619 }
1620 }
1621 else if (difftype == UNI_DIFF) {
1622 file_offset line_beginning = file_tell (pfp); /* file pos of the current line */
1623 lin fillsrc; /* index of old lines */
1624 lin filldst; /* index of new lines */
1625 char ch = '\0';
1626
1627 chars_read = get_line ();
1628 if (chars_read == (size_t) -1
1629 || chars_read <= 4
1630 || strncmp (buf, "@@ -", 4) != 0) {
1631 next_intuit_at(line_beginning,p_input_line);
1632 return chars_read == (size_t) -1 ? -1 : 0;
1633 }
1634 s = scan_linenum (buf + 4, &p_first);
1635 if (*s == ',')
1636 s = scan_linenum (s + 1, &p_ptrn_lines);
1637 else
1638 p_ptrn_lines = 1;
1639 if (p_first >= LINENUM_MAX - p_ptrn_lines)
1640 malformed ();
1641 if (*s == ' ') s++;
1642 if (*s != '+')
1643 malformed ();
1644 s = scan_linenum (s + 1, &p_newfirst);
1645 if (*s == ',')
1646 s = scan_linenum (s + 1, &p_repl_lines);
1647 else
1648 p_repl_lines = 1;
1649 if (p_newfirst >= LINENUM_MAX - p_repl_lines)
1650 malformed ();
1651 if (*s == ' ') s++;
1652 if (*s++ != '@')
1653 malformed ();
1654 if (*s++ == '@' && *s == ' ')
1655 {
1656 p_c_function = s;
1657 while (*s != '\n')
1658 s++;
1659 *s = '\0';
1660 p_c_function = savestr (p_c_function);
1661 if (! p_c_function)
1662 return -1;
1663 }
1664 if (!p_ptrn_lines)
1665 p_first++; /* do append rather than insert */
1666 if (!p_repl_lines)
1667 p_newfirst++;
1668 if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1))
1669 malformed ();
1670 p_max = p_ptrn_lines + p_repl_lines + 1;
1671 while (p_max + 1 >= hunkmax)
1672 if (! grow_hunkmax ())
1673 return -1;
1674 fillsrc = 1;
1675 filldst = fillsrc + p_ptrn_lines;
1676 p_end = filldst + p_repl_lines;
1677 sprintf (buf, "*** %s,%s ****\n",
1678 format_linenum (numbuf0, p_first),
1679 format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
1680 p_len[0] = strlen (buf);
1681 if (! (p_line[0] = savestr (buf))) {
1682 p_end = -1;
1683 return -1;
1684 }
1685 p_Char[0] = '*';
1686 sprintf (buf, "--- %s,%s ----\n",
1687 format_linenum (numbuf0, p_newfirst),
1688 format_linenum (numbuf1, p_newfirst + p_repl_lines - 1));
1689 p_len[filldst] = strlen (buf);
1690 if (! (p_line[filldst] = savestr (buf))) {
1691 p_end = 0;
1692 return -1;
1693 }
1694 p_Char[filldst++] = '=';
1695 p_prefix_context = -1;
1696 p_hunk_beg = p_input_line + 1;
1697 while (fillsrc <= p_ptrn_lines || filldst <= p_end) {
1698 chars_read = get_line ();
1699 if (!chars_read) {
1700 if (p_max - filldst < 3) {
1701 strcpy (buf, " \n"); /* assume blank lines got chopped */
1702 chars_read = 2;
1703 } else {
1704 fatal ("unexpected end of file in patch");
1705 }
1706 }
1707 if (chars_read == (size_t) -1)
1708 s = 0;
1709 else if (*buf == '\t' || *buf == '\n') {
1710 ch = ' '; /* assume the space got eaten */
1711 s = savebuf (buf, chars_read);
1712 }
1713 else {
1714 ch = *buf;
1715 s = savebuf (buf+1, --chars_read);
1716 }
1717 if (chars_read && ! s)
1718 {
1719 while (--filldst > p_ptrn_lines)
1720 free(p_line[filldst]);
1721 p_end = fillsrc-1;
1722 return -1;
1723 }
1724 switch (ch) {
1725 case '-':
1726 if (fillsrc > p_ptrn_lines) {
1727 free(s);
1728 p_end = filldst-1;
1729 malformed ();
1730 }
1731 chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
1732 p_Char[fillsrc] = ch;
1733 p_line[fillsrc] = s;
1734 p_len[fillsrc++] = chars_read;
1735 break;
1736 case '=':
1737 ch = ' ';
1738 /* FALL THROUGH */
1739 case ' ':
1740 if (fillsrc > p_ptrn_lines) {
1741 free(s);
1742 while (--filldst > p_ptrn_lines)
1743 free(p_line[filldst]);
1744 p_end = fillsrc-1;
1745 malformed ();
1746 }
1747 context++;
1748 chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
1749 p_Char[fillsrc] = ch;
1750 p_line[fillsrc] = s;
1751 p_len[fillsrc++] = chars_read;
1752 s = savebuf (s, chars_read);
1753 if (chars_read && ! s) {
1754 while (--filldst > p_ptrn_lines)
1755 free(p_line[filldst]);
1756 p_end = fillsrc-1;
1757 return -1;
1758 }
1759 /* FALL THROUGH */
1760 case '+':
1761 if (filldst > p_end) {
1762 free(s);
1763 while (--filldst > p_ptrn_lines)
1764 free(p_line[filldst]);
1765 p_end = fillsrc-1;
1766 malformed ();
1767 }
1768 chars_read -= filldst == p_end && incomplete_line ();
1769 p_Char[filldst] = ch;
1770 p_line[filldst] = s;
1771 p_len[filldst++] = chars_read;
1772 break;
1773 default:
1774 p_end = filldst;
1775 malformed ();
1776 }
1777 if (ch != ' ') {
1778 if (p_prefix_context == -1)
1779 p_prefix_context = context;
1780 context = 0;
1781 }
1782 }/* while */
1783 if (p_prefix_context == -1)
1784 malformed ();
1785 p_suffix_context = context;
1786 }
1787 else { /* normal diff--fake it up */
1788 char hunk_type;
1789 int i;
1790 lin min, max;
1791 file_offset line_beginning = file_tell (pfp);
1792
1793 p_prefix_context = p_suffix_context = 0;
1794 chars_read = get_line ();
1795 if (chars_read == (size_t) -1 || !chars_read || !ISDIGIT (*buf)) {
1796 next_intuit_at(line_beginning,p_input_line);
1797 return chars_read == (size_t) -1 ? -1 : 0;
1798 }
1799 s = scan_linenum (buf, &p_first);
1800 if (*s == ',') {
1801 s = scan_linenum (s + 1, &p_ptrn_lines);
1802 p_ptrn_lines += 1 - p_first;
1803 }
1804 else
1805 p_ptrn_lines = (*s != 'a');
1806 if (p_first >= LINENUM_MAX - p_ptrn_lines)
1807 malformed ();
1808 hunk_type = *s;
1809 if (hunk_type == 'a')
1810 p_first++; /* do append rather than insert */
1811 s = scan_linenum (s + 1, &min);
1812 if (*s == ',')
1813 scan_linenum (s + 1, &max);
1814 else
1815 max = min;
1816 if (min > max || max - min == LINENUM_MAX)
1817 malformed ();
1818 if (hunk_type == 'd')
1819 min++;
1820 p_newfirst = min;
1821 p_repl_lines = max - min + 1;
1822 if (p_newfirst >= LINENUM_MAX - p_repl_lines)
1823 malformed ();
1824 if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1))
1825 malformed ();
1826 p_end = p_ptrn_lines + p_repl_lines + 1;
1827 while (p_end + 1 >= hunkmax)
1828 if (! grow_hunkmax ())
1829 {
1830 p_end = -1;
1831 return -1;
1832 }
1833 sprintf (buf, "*** %s,%s\n",
1834 format_linenum (numbuf0, p_first),
1835 format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
1836 p_len[0] = strlen (buf);
1837 if (! (p_line[0] = savestr (buf))) {
1838 p_end = -1;
1839 return -1;
1840 }
1841 p_Char[0] = '*';
1842 for (i=1; i<=p_ptrn_lines; i++) {
1843 chars_read = get_line ();
1844 if (chars_read == (size_t) -1)
1845 {
1846 p_end = i - 1;
1847 return -1;
1848 }
1849 if (!chars_read)
1850 fatal ("unexpected end of file in patch at line %s",
1851 format_linenum (numbuf0, p_input_line));
1852 if (buf[0] != '<' || (buf[1] != ' ' && buf[1] != '\t'))
1853 fatal ("'<' followed by space or tab expected at line %s of patch",
1854 format_linenum (numbuf0, p_input_line));
1855 chars_read -= 2 + (i == p_ptrn_lines && incomplete_line ());
1856 p_len[i] = chars_read;
1857 p_line[i] = savebuf (buf + 2, chars_read);
1858 if (chars_read && ! p_line[i]) {
1859 p_end = i-1;
1860 return -1;
1861 }
1862 p_Char[i] = '-';
1863 }
1864 if (hunk_type == 'c') {
1865 chars_read = get_line ();
1866 if (chars_read == (size_t) -1)
1867 {
1868 p_end = i - 1;
1869 return -1;
1870 }
1871 if (! chars_read)
1872 fatal ("unexpected end of file in patch at line %s",
1873 format_linenum (numbuf0, p_input_line));
1874 if (*buf != '-')
1875 fatal ("'---' expected at line %s of patch",
1876 format_linenum (numbuf0, p_input_line));
1877 }
1878 sprintf (buf, "--- %s,%s\n",
1879 format_linenum (numbuf0, min),
1880 format_linenum (numbuf1, max));
1881 p_len[i] = strlen (buf);
1882 if (! (p_line[i] = savestr (buf))) {
1883 p_end = i-1;
1884 return -1;
1885 }
1886 p_Char[i] = '=';
1887 for (i++; i<=p_end; i++) {
1888 chars_read = get_line ();
1889 if (chars_read == (size_t) -1)
1890 {
1891 p_end = i - 1;
1892 return -1;
1893 }
1894 if (!chars_read)
1895 fatal ("unexpected end of file in patch at line %s",
1896 format_linenum (numbuf0, p_input_line));
1897 if (buf[0] != '>' || (buf[1] != ' ' && buf[1] != '\t'))
1898 fatal ("'>' followed by space or tab expected at line %s of patch",
1899 format_linenum (numbuf0, p_input_line));
1900 chars_read -= 2 + (i == p_end && incomplete_line ());
1901 p_len[i] = chars_read;
1902 p_line[i] = savebuf (buf + 2, chars_read);
1903 if (chars_read && ! p_line[i]) {
1904 p_end = i-1;
1905 return -1;
1906 }
1907 p_Char[i] = '+';
1908 }
1909 }
1910 if (rev) /* backwards patch? */
1911 if (!pch_swap())
1912 say ("Not enough memory to swap next hunk!\n");
1913 assert (p_end + 1 < hunkmax);
1914 p_Char[p_end + 1] = '^'; /* add a stopper for apply_hunk */
1915 if (debug & 2) {
1916 lin i;
1917
1918 for (i = 0; i <= p_end + 1; i++) {
1919 fprintf (stderr, "%s %c",
1920 format_linenum (numbuf0, i),
1921 p_Char[i]);
1922 if (p_Char[i] == '*')
1923 fprintf (stderr, " %s,%s\n",
1924 format_linenum (numbuf0, p_first),
1925 format_linenum (numbuf1, p_ptrn_lines));
1926 else if (p_Char[i] == '=')
1927 fprintf (stderr, " %s,%s\n",
1928 format_linenum (numbuf0, p_newfirst),
1929 format_linenum (numbuf1, p_repl_lines));
1930 else if (p_Char[i] != '^')
1931 {
1932 fputs(" |", stderr);
1933 pch_write_line (i, stderr);
1934 }
1935 else
1936 fputc('\n', stderr);
1937 }
1938 fflush (stderr);
1939 }
1940 return 1;
1941 }
1942
1943 static size_t
get_line(void)1944 get_line (void)
1945 {
1946 return pget_line (p_indent, p_rfc934_nesting, p_strip_trailing_cr,
1947 p_pass_comments_through);
1948 }
1949
1950 /* Input a line from the patch file, worrying about indentation.
1951 Strip up to INDENT characters' worth of leading indentation.
1952 Then remove up to RFC934_NESTING instances of leading "- ".
1953 If STRIP_TRAILING_CR is true, remove any trailing carriage-return.
1954 Unless PASS_COMMENTS_THROUGH is true, ignore any resulting lines
1955 that begin with '#'; they're comments.
1956 Ignore any partial lines at end of input, but warn about them.
1957 Succeed if a line was read; it is terminated by "\n\0" for convenience.
1958 Return the number of characters read, including '\n' but not '\0'.
1959 Return -1 if we ran out of memory. */
1960
1961 static size_t
pget_line(size_t indent,int rfc934_nesting,bool strip_trailing_cr,bool pass_comments_through)1962 pget_line (size_t indent, int rfc934_nesting, bool strip_trailing_cr,
1963 bool pass_comments_through)
1964 {
1965 FILE *fp = pfp;
1966 int c;
1967 size_t i;
1968 char *b;
1969 size_t s;
1970
1971 do
1972 {
1973 i = 0;
1974 for (;;)
1975 {
1976 c = getc (fp);
1977 if (c == EOF)
1978 {
1979 if (ferror (fp))
1980 read_fatal ();
1981 return 0;
1982 }
1983 if (indent <= i)
1984 break;
1985 if (c == ' ' || c == 'X')
1986 i++;
1987 else if (c == '\t')
1988 i = (i + 8) & ~7;
1989 else
1990 break;
1991 }
1992
1993 i = 0;
1994 b = buf;
1995
1996 while (c == '-' && 0 <= --rfc934_nesting)
1997 {
1998 c = getc (fp);
1999 if (c == EOF)
2000 goto patch_ends_in_middle_of_line;
2001 if (c != ' ')
2002 {
2003 i = 1;
2004 b[0] = '-';
2005 break;
2006 }
2007 c = getc (fp);
2008 if (c == EOF)
2009 goto patch_ends_in_middle_of_line;
2010 }
2011
2012 s = bufsize;
2013
2014 for (;;)
2015 {
2016 if (i == s - 1)
2017 {
2018 s *= 2;
2019 b = realloc (b, s);
2020 if (!b)
2021 {
2022 if (!using_plan_a)
2023 xalloc_die ();
2024 return (size_t) -1;
2025 }
2026 buf = b;
2027 bufsize = s;
2028 }
2029 b[i++] = c;
2030 if (c == '\n')
2031 break;
2032 c = getc (fp);
2033 if (c == EOF)
2034 goto patch_ends_in_middle_of_line;
2035 }
2036
2037 p_input_line++;
2038 }
2039 while (*b == '#' && !pass_comments_through);
2040
2041 if (strip_trailing_cr && 2 <= i && b[i - 2] == '\r')
2042 b[i-- - 2] = '\n';
2043 b[i] = '\0';
2044 return i;
2045
2046 patch_ends_in_middle_of_line:
2047 if (ferror (fp))
2048 read_fatal ();
2049 say ("patch unexpectedly ends in middle of line\n");
2050 return 0;
2051 }
2052
2053 static bool
incomplete_line(void)2054 incomplete_line (void)
2055 {
2056 FILE *fp = pfp;
2057 int c;
2058 file_offset line_beginning = file_tell (fp);
2059
2060 if (getc (fp) == '\\')
2061 {
2062 while ((c = getc (fp)) != '\n' && c != EOF)
2063 /* do nothing */ ;
2064 return true;
2065 }
2066 else
2067 {
2068 /* We don't trust ungetc. */
2069 Fseek (pfp, line_beginning, SEEK_SET);
2070 return false;
2071 }
2072 }
2073
2074 /* Reverse the old and new portions of the current hunk. */
2075
2076 bool
pch_swap(void)2077 pch_swap (void)
2078 {
2079 char **tp_line; /* the text of the hunk */
2080 size_t *tp_len; /* length of each line */
2081 char *tp_char; /* +, -, and ! */
2082 lin i;
2083 lin n;
2084 bool blankline = false;
2085 char *s;
2086
2087 i = p_first;
2088 p_first = p_newfirst;
2089 p_newfirst = i;
2090
2091 /* make a scratch copy */
2092
2093 tp_line = p_line;
2094 tp_len = p_len;
2095 tp_char = p_Char;
2096 p_line = 0; /* force set_hunkmax to allocate again */
2097 p_len = 0;
2098 p_Char = 0;
2099 set_hunkmax();
2100 if (!p_line || !p_len || !p_Char) {
2101 free (p_line);
2102 p_line = tp_line;
2103 free (p_len);
2104 p_len = tp_len;
2105 free (p_Char);
2106 p_Char = tp_char;
2107 return false; /* not enough memory to swap hunk! */
2108 }
2109
2110 /* now turn the new into the old */
2111
2112 i = p_ptrn_lines + 1;
2113 if (tp_char[i] == '\n') { /* account for possible blank line */
2114 blankline = true;
2115 i++;
2116 }
2117 if (p_efake >= 0) { /* fix non-freeable ptr range */
2118 if (p_efake <= i)
2119 n = p_end - i + 1;
2120 else
2121 n = -i;
2122 p_efake += n;
2123 p_bfake += n;
2124 }
2125 for (n=0; i <= p_end; i++,n++) {
2126 p_line[n] = tp_line[i];
2127 p_Char[n] = tp_char[i];
2128 if (p_Char[n] == '+')
2129 p_Char[n] = '-';
2130 p_len[n] = tp_len[i];
2131 }
2132 if (blankline) {
2133 i = p_ptrn_lines + 1;
2134 p_line[n] = tp_line[i];
2135 p_Char[n] = tp_char[i];
2136 p_len[n] = tp_len[i];
2137 n++;
2138 }
2139 assert(p_Char[0] == '=');
2140 p_Char[0] = '*';
2141 for (s=p_line[0]; *s; s++)
2142 if (*s == '-')
2143 *s = '*';
2144
2145 /* now turn the old into the new */
2146
2147 assert(tp_char[0] == '*');
2148 tp_char[0] = '=';
2149 for (s=tp_line[0]; *s; s++)
2150 if (*s == '*')
2151 *s = '-';
2152 for (i=0; n <= p_end; i++,n++) {
2153 p_line[n] = tp_line[i];
2154 p_Char[n] = tp_char[i];
2155 if (p_Char[n] == '-')
2156 p_Char[n] = '+';
2157 p_len[n] = tp_len[i];
2158 }
2159 assert(i == p_ptrn_lines + 1);
2160 i = p_ptrn_lines;
2161 p_ptrn_lines = p_repl_lines;
2162 p_repl_lines = i;
2163 p_Char[p_end + 1] = '^';
2164 free (tp_line);
2165 free (tp_len);
2166 free (tp_char);
2167 return true;
2168 }
2169
2170 /* Return whether file WHICH (false = old, true = new) appears to nonexistent.
2171 Return 1 for empty, 2 for nonexistent. */
2172
2173 int
pch_says_nonexistent(bool which)2174 pch_says_nonexistent (bool which)
2175 {
2176 return p_says_nonexistent[which];
2177 }
2178
2179 const char *
pch_name(enum nametype type)2180 pch_name (enum nametype type)
2181 {
2182 return type == NONE ? NULL : p_name[type];
2183 }
2184
pch_copy(void)2185 bool pch_copy (void)
2186 {
2187 return p_copy[OLD] && p_copy[NEW];
2188 }
2189
pch_rename(void)2190 bool pch_rename (void)
2191 {
2192 return p_rename[OLD] && p_rename[NEW];
2193 }
2194
2195 /* Return the specified line position in the old file of the old context. */
2196
2197 lin
pch_first(void)2198 pch_first (void)
2199 {
2200 return p_first;
2201 }
2202
2203 /* Return the number of lines of old context. */
2204
2205 lin
pch_ptrn_lines(void)2206 pch_ptrn_lines (void)
2207 {
2208 return p_ptrn_lines;
2209 }
2210
2211 /* Return the probable line position in the new file of the first line. */
2212
2213 lin
pch_newfirst(void)2214 pch_newfirst (void)
2215 {
2216 return p_newfirst;
2217 }
2218
2219 /* Return the number of lines in the replacement text including context. */
2220
2221 lin
pch_repl_lines(void)2222 pch_repl_lines (void)
2223 {
2224 return p_repl_lines;
2225 }
2226
2227 /* Return the number of lines in the whole hunk. */
2228
2229 lin
pch_end(void)2230 pch_end (void)
2231 {
2232 return p_end;
2233 }
2234
2235 /* Return the number of context lines before the first changed line. */
2236
2237 lin
pch_prefix_context(void)2238 pch_prefix_context (void)
2239 {
2240 return p_prefix_context;
2241 }
2242
2243 /* Return the number of context lines after the last changed line. */
2244
2245 lin
pch_suffix_context(void)2246 pch_suffix_context (void)
2247 {
2248 return p_suffix_context;
2249 }
2250
2251 /* Return the length of a particular patch line. */
2252
2253 size_t
pch_line_len(lin line)2254 pch_line_len (lin line)
2255 {
2256 return p_len[line];
2257 }
2258
2259 /* Return the control character (+, -, *, !, etc) for a patch line. A '\n'
2260 indicates an empty line in a hunk. (The empty line is not part of the
2261 old or new context. For some reson, the context format allows that.) */
2262
2263 char
pch_char(lin line)2264 pch_char (lin line)
2265 {
2266 return p_Char[line];
2267 }
2268
2269 /* Return a pointer to a particular patch line. */
2270
2271 char *
pfetch(lin line)2272 pfetch (lin line)
2273 {
2274 return p_line[line];
2275 }
2276
2277 /* Output a patch line. */
2278
2279 bool
pch_write_line(lin line,FILE * file)2280 pch_write_line (lin line, FILE *file)
2281 {
2282 bool after_newline = (p_len[line] > 0) && (p_line[line][p_len[line] - 1] == '\n');
2283 if (! fwrite (p_line[line], sizeof (*p_line[line]), p_len[line], file))
2284 write_fatal ();
2285 return after_newline;
2286 }
2287
2288 /* Return where in the patch file this hunk began, for error messages. */
2289
2290 lin
pch_hunk_beg(void)2291 pch_hunk_beg (void)
2292 {
2293 return p_hunk_beg;
2294 }
2295
2296 char const *
pch_c_function(void)2297 pch_c_function (void)
2298 {
2299 return p_c_function;
2300 }
2301
2302 /* Return true if in a git-style patch. */
2303
2304 bool
pch_git_diff(void)2305 pch_git_diff (void)
2306 {
2307 return p_git_diff;
2308 }
2309
2310 char const *
pch_timestr(bool which)2311 pch_timestr (bool which)
2312 {
2313 return p_timestr[which];
2314 }
2315
2316 char const *
pch_sha1(bool which)2317 pch_sha1 (bool which)
2318 {
2319 return p_sha1[which];
2320 }
2321
2322 mode_t
pch_mode(bool which)2323 pch_mode (bool which)
2324 {
2325 return p_mode[which];
2326 }
2327
2328 /* Is the newline-terminated line a valid 'ed' command for patch
2329 input? If so, return the command character; if not, return 0.
2330 This accepts just a subset of the valid commands, but it's
2331 good enough in practice. */
2332
2333 static char _GL_ATTRIBUTE_PURE
get_ed_command_letter(char const * line)2334 get_ed_command_letter (char const *line)
2335 {
2336 char const *p = line;
2337 char letter;
2338 bool pair = false;
2339
2340 if (ISDIGIT (*p))
2341 {
2342 while (ISDIGIT (*++p))
2343 /* do nothing */ ;
2344 if (*p == ',')
2345 {
2346 if (! ISDIGIT (*++p))
2347 return 0;
2348 while (ISDIGIT (*++p))
2349 /* do nothing */ ;
2350 pair = true;
2351 }
2352 }
2353
2354 letter = *p++;
2355
2356 switch (letter)
2357 {
2358 case 'a':
2359 case 'i':
2360 if (pair)
2361 return 0;
2362 break;
2363
2364 case 'c':
2365 case 'd':
2366 break;
2367
2368 case 's':
2369 if (strncmp (p, "/.//", 4) != 0)
2370 return 0;
2371 p += 4;
2372 break;
2373
2374 default:
2375 return 0;
2376 }
2377
2378 while (*p == ' ' || *p == '\t')
2379 p++;
2380 if (*p == '\n')
2381 return letter;
2382 return 0;
2383 }
2384
2385 /* Apply an ed script by feeding ed itself. */
2386
2387 void
do_ed_script(char const * inname,char const * outname,bool * outname_needs_removal,FILE * ofp)2388 do_ed_script (char const *inname, char const *outname,
2389 bool *outname_needs_removal, FILE *ofp)
2390 {
2391 static char const editor_program[] = EDITOR_PROGRAM;
2392
2393 file_offset beginning_of_this_line;
2394 size_t chars_read;
2395 FILE *tmpfp = 0;
2396 int tmpfd;
2397 pid_t pid;
2398
2399 if (! dry_run && ! skip_rest_of_patch)
2400 {
2401 /* Write ed script to a temporary file. This causes ed to abort on
2402 invalid commands such as when line numbers or ranges exceed the
2403 number of available lines. When ed reads from a pipe, it rejects
2404 invalid commands and treats the next line as a new command, which
2405 can lead to arbitrary command execution. */
2406
2407 tmpfd = make_tempfile (&TMPEDNAME, 'e', NULL, O_RDWR | O_BINARY, 0);
2408 if (tmpfd == -1)
2409 pfatal ("Can't create temporary file %s", quotearg (TMPEDNAME));
2410 TMPEDNAME_needs_removal = true;
2411 tmpfp = fdopen (tmpfd, "w+b");
2412 if (! tmpfp)
2413 pfatal ("Can't open stream for file %s", quotearg (TMPEDNAME));
2414 }
2415
2416 for (;;) {
2417 char ed_command_letter;
2418 beginning_of_this_line = file_tell (pfp);
2419 chars_read = get_line ();
2420 if (! chars_read) {
2421 next_intuit_at(beginning_of_this_line,p_input_line);
2422 break;
2423 }
2424 ed_command_letter = get_ed_command_letter (buf);
2425 if (ed_command_letter) {
2426 if (tmpfp)
2427 if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
2428 write_fatal ();
2429 if (ed_command_letter != 'd' && ed_command_letter != 's') {
2430 p_pass_comments_through = true;
2431 while ((chars_read = get_line ()) != 0) {
2432 if (tmpfp)
2433 if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
2434 write_fatal ();
2435 if (chars_read == 2 && strEQ (buf, ".\n"))
2436 break;
2437 }
2438 p_pass_comments_through = false;
2439 }
2440 }
2441 else {
2442 next_intuit_at(beginning_of_this_line,p_input_line);
2443 break;
2444 }
2445 }
2446 if (!tmpfp)
2447 return;
2448 if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, tmpfp) == 0
2449 || fflush (tmpfp) != 0)
2450 write_fatal ();
2451
2452 if (lseek (tmpfd, 0, SEEK_SET) == -1)
2453 pfatal ("Can't rewind to the beginning of file %s", quotearg (TMPEDNAME));
2454
2455 if (! dry_run && ! skip_rest_of_patch) {
2456 int exclusive = *outname_needs_removal ? 0 : O_EXCL;
2457 *outname_needs_removal = true;
2458 if (inerrno != ENOENT)
2459 {
2460 *outname_needs_removal = true;
2461 copy_file (inname, outname, 0, exclusive, instat.st_mode, true);
2462 }
2463 fflush (stdout);
2464
2465 pid = fork();
2466 if (pid == -1)
2467 pfatal ("Can't fork");
2468 else if (pid == 0)
2469 {
2470 dup2 (tmpfd, 0);
2471 assert (outname[0] != '!' && outname[0] != '-');
2472 execlp (editor_program, editor_program, "-", outname, (char *) NULL);
2473 _exit (2);
2474 }
2475 else
2476 {
2477 int wstatus;
2478 if (waitpid (pid, &wstatus, 0) == -1
2479 || ! WIFEXITED (wstatus)
2480 || WEXITSTATUS (wstatus) != 0)
2481 fatal ("%s FAILED", editor_program);
2482 }
2483 }
2484
2485 fclose (tmpfp);
2486
2487 if (ofp)
2488 {
2489 FILE *ifp = fopen (outname, binary_transput ? "rb" : "r");
2490 int c;
2491 if (!ifp)
2492 pfatal ("can't open '%s'", outname);
2493 while ((c = getc (ifp)) != EOF)
2494 if (putc (c, ofp) == EOF)
2495 write_fatal ();
2496 if (ferror (ifp) || fclose (ifp) != 0)
2497 read_fatal ();
2498 }
2499 }
2500
2501 void
pch_normalize(enum diff format)2502 pch_normalize (enum diff format)
2503 {
2504 lin old = 1;
2505 lin new = p_ptrn_lines + 1;
2506
2507 while (p_Char[new] == '=' || p_Char[new] == '\n')
2508 new++;
2509
2510 if (format == UNI_DIFF)
2511 {
2512 /* Convert '!' markers into '-' and '+' as defined by the Unified
2513 Format. */
2514
2515 for (; old <= p_ptrn_lines; old++)
2516 if (p_Char[old] == '!')
2517 p_Char[old] = '-';
2518 for (; new <= p_end; new++)
2519 if (p_Char[new] == '!')
2520 p_Char[new] = '+';
2521 }
2522 else
2523 {
2524 /* Convert '-' and '+' markers which are part of a group into '!' as
2525 defined by the Context Format. */
2526
2527 while (old <= p_ptrn_lines)
2528 {
2529 if (p_Char[old] == '-')
2530 {
2531 if (new <= p_end && p_Char[new] == '+')
2532 {
2533 do
2534 {
2535 p_Char[old] = '!';
2536 old++;
2537 }
2538 while (old <= p_ptrn_lines && p_Char[old] == '-');
2539 do
2540 {
2541 p_Char[new] = '!';
2542 new++;
2543 }
2544 while (new <= p_end && p_Char[new] == '+');
2545 }
2546 else
2547 {
2548 do
2549 old++;
2550 while (old <= p_ptrn_lines && p_Char[old] == '-');
2551 }
2552 }
2553 else if (new <= p_end && p_Char[new] == '+')
2554 {
2555 do
2556 new++;
2557 while (new <= p_end && p_Char[new] == '+');
2558 }
2559 else
2560 {
2561 old++;
2562 new++;
2563 }
2564 }
2565 }
2566 }
2567