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 42static FILE *pfp; /* patch file pointer */ 43static 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 */ 47static int p_rfc934_nesting; /* RFC 934 nesting level */ 48static char *p_name[3]; /* filenames in patch headers */ 49static char const *invalid_names[2]; 50bool p_copy[2]; /* Does this patch create a copy? */ 51bool p_rename[2]; /* Does this patch rename a file? */ 52static char *p_timestr[2]; /* timestamps as strings */ 53static char *p_sha1[2]; /* SHA1 checksums */ 54static mode_t p_mode[2]; /* file modes */ 55static off_t p_filesize; /* size of the patch file */ 56static lin p_first; /* 1st line number */ 57static lin p_newfirst; /* 1st line number of replacement */ 58static lin p_ptrn_lines; /* # lines in pattern */ 59static lin p_repl_lines; /* # lines in replacement text */ 60static lin p_end = -1; /* last line in hunk */ 61static lin p_max; /* max allowed value of p_end */ 62static lin p_prefix_context; /* # of prefix context lines */ 63static lin p_suffix_context; /* # of suffix context lines */ 64static lin p_input_line; /* current line # from patch file */ 65static char **p_line; /* the text of the hunk */ 66static size_t *p_len; /* line length including \n if any */ 67static char *p_Char; /* +, -, and ! */ 68static lin hunkmax = INITHUNKMAX; /* size of above arrays */ 69static size_t p_indent; /* indent to patch */ 70static bool p_strip_trailing_cr; /* true if stripping trailing \r */ 71static bool p_pass_comments_through; /* true if not ignoring # lines */ 72static file_offset p_base; /* where to intuit this time */ 73static lin p_bline; /* line # of p_base */ 74static file_offset p_start; /* where intuit found a patch */ 75static lin p_sline; /* and the line number for it */ 76static lin p_hunk_beg; /* line number of current hunk */ 77static lin p_efake = -1; /* end of faked up lines--don't free */ 78static lin p_bfake = -1; /* beg of faked up lines */ 79static char *p_c_function; /* the C function a hunk is in */ 80static bool p_git_diff; /* true if this is a git style diff */ 81 82static char *scan_linenum (char *, lin *); 83static enum diff intuit_diff_type (bool, mode_t *); 84static enum nametype best_name (char * const *, int const *); 85static int prefix_components (char *, bool); 86static size_t pget_line (size_t, int, bool, bool); 87static size_t get_line (void); 88static bool incomplete_line (void); 89static bool grow_hunkmax (void); 90static void malformed (void) __attribute__ ((noreturn)); 91static void next_intuit_at (file_offset, lin); 92static void skip_to (file_offset, lin); 93static char get_ed_command_letter (char const *); 94 95/* Prepare to look for the next patch in the patch file. */ 96 97void 98re_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 112void 113open_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 170static void 171set_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 183static bool 184grow_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 201static bool 202maybe_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 229bool 230there_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 324static mode_t _GL_ATTRIBUTE_PURE 325fetchmode (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 355static void 356get_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 364static int _GL_ATTRIBUTE_PURE 365sha1_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 384static char const * _GL_ATTRIBUTE_PURE 385skip_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 394static bool 395name_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 425static enum diff 426intuit_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. */ 1010static int 1011prefix_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. */ 1040static enum nametype 1041best_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 1087static void 1088next_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 1096static void 1097skip_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. */ 1128static void 1129malformed (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. */ 1139static char * 1140scan_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 1169int 1170another_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 1331 != p_ptrn_lines + 1 + (p_Char[p_end - 1] == '\n'))) 1332 { 1333 if (p_end == 1) 1334 { 1335 /* 'Old' lines were omitted. Set up to fill 1336 them in from 'new' context lines. */ 1337 ptrn_missing = true; 1338 p_end = p_ptrn_lines + 1; 1339 ptrn_prefix_context = ptrn_suffix_context = -1; 1340 fillsrc = p_end + 1; 1341 filldst = 1; 1342 fillcnt = p_ptrn_lines; 1343 } 1344 else if (! repl_beginning) 1345 fatal ("%s '---' at line %s; check line numbers at line %s", 1346 (p_end <= p_ptrn_lines 1347 ? "Premature" 1348 : "Overdue"), 1349 format_linenum (numbuf0, p_input_line), 1350 format_linenum (numbuf1, p_hunk_beg)); 1351 else if (! repl_could_be_missing) 1352 fatal ("duplicate '---' at line %s; check line numbers at line %s", 1353 format_linenum (numbuf0, p_input_line), 1354 format_linenum (numbuf1, 1355 p_hunk_beg + repl_beginning)); 1356 else 1357 { 1358 repl_missing = true; 1359 goto hunk_done; 1360 } 1361 } 1362 repl_beginning = p_end; 1363 repl_backtrack_position = file_tell (pfp); 1364 repl_patch_line = p_input_line; 1365 repl_context = context; 1366 p_len[p_end] = strlen (buf); 1367 if (! (p_line[p_end] = savestr (buf))) 1368 { 1369 p_end--; 1370 return -1; 1371 } 1372 p_Char[p_end] = '='; 1373 for (s = buf; *s && ! ISDIGIT (*s); s++) 1374 /* do nothing */ ; 1375 s = scan_linenum (s, &p_newfirst); 1376 if (*s == ',') 1377 { 1378 do 1379 { 1380 if (!*++s) 1381 malformed (); 1382 } 1383 while (! ISDIGIT (*s)); 1384 scan_linenum (s, &p_repl_lines); 1385 p_repl_lines += 1 - p_newfirst; 1386 if (p_repl_lines < 0) 1387 malformed (); 1388 } 1389 else if (p_newfirst) 1390 p_repl_lines = 1; 1391 else 1392 { 1393 p_repl_lines = 0; 1394 p_newfirst = 1; 1395 } 1396 if (p_newfirst >= LINENUM_MAX - p_repl_lines || 1397 p_repl_lines >= LINENUM_MAX - p_end) 1398 malformed (); 1399 p_max = p_repl_lines + p_end; 1400 while (p_max + 1 >= hunkmax) 1401 if (! grow_hunkmax ()) 1402 return -1; 1403 if (p_repl_lines != ptrn_copiable 1404 && (p_prefix_context != 0 1405 || context != 0 1406 || p_repl_lines != 1)) 1407 repl_could_be_missing = false; 1408 context = 0; 1409 break; 1410 case '+': case '!': 1411 repl_could_be_missing = false; 1412 change_line: 1413 s = buf + 1; 1414 chars_read--; 1415 if (*s == '\n' && canonicalize_ws) { 1416 strcpy (s, " \n"); 1417 chars_read = 2; 1418 } 1419 if (*s == ' ' || *s == '\t') { 1420 s++; 1421 chars_read--; 1422 } else if (repl_beginning && repl_could_be_missing) { 1423 repl_missing = true; 1424 goto hunk_done; 1425 } 1426 if (! repl_beginning) 1427 { 1428 if (ptrn_prefix_context == -1) 1429 ptrn_prefix_context = context; 1430 } 1431 else 1432 { 1433 if (repl_prefix_context == -1) 1434 repl_prefix_context = context; 1435 } 1436 chars_read -= 1437 (1 < chars_read 1438 && p_end == (repl_beginning ? p_max : p_ptrn_lines) 1439 && incomplete_line ()); 1440 p_len[p_end] = chars_read; 1441 p_line[p_end] = savebuf (s, chars_read); 1442 if (chars_read && ! p_line[p_end]) { 1443 p_end--; 1444 return -1; 1445 } 1446 context = 0; 1447 break; 1448 case '\t': case '\n': /* assume spaces got eaten */ 1449 s = buf; 1450 if (*buf == '\t') { 1451 s++; 1452 chars_read--; 1453 } 1454 if (repl_beginning && repl_could_be_missing && 1455 (!ptrn_spaces_eaten || difftype == NEW_CONTEXT_DIFF) ) { 1456 repl_missing = true; 1457 goto hunk_done; 1458 } 1459 chars_read -= 1460 (1 < chars_read 1461 && p_end == (repl_beginning ? p_max : p_ptrn_lines) 1462 && incomplete_line ()); 1463 p_len[p_end] = chars_read; 1464 p_line[p_end] = savebuf (buf, chars_read); 1465 if (chars_read && ! p_line[p_end]) { 1466 p_end--; 1467 return -1; 1468 } 1469 if (p_end != p_ptrn_lines + 1) { 1470 ptrn_spaces_eaten |= (repl_beginning != 0); 1471 some_context = true; 1472 context++; 1473 if (repl_beginning) 1474 repl_copiable++; 1475 else 1476 ptrn_copiable++; 1477 p_Char[p_end] = ' '; 1478 } 1479 break; 1480 case ' ': 1481 s = buf + 1; 1482 chars_read--; 1483 if (*s == '\n' && canonicalize_ws) { 1484 strcpy (s, "\n"); 1485 chars_read = 2; 1486 } 1487 if (*s == ' ' || *s == '\t') { 1488 s++; 1489 chars_read--; 1490 } else if (repl_beginning && repl_could_be_missing) { 1491 repl_missing = true; 1492 goto hunk_done; 1493 } 1494 some_context = true; 1495 context++; 1496 if (repl_beginning) 1497 repl_copiable++; 1498 else 1499 ptrn_copiable++; 1500 chars_read -= 1501 (1 < chars_read 1502 && p_end == (repl_beginning ? p_max : p_ptrn_lines) 1503 && incomplete_line ()); 1504 p_len[p_end] = chars_read; 1505 p_line[p_end] = savebuf (s, chars_read); 1506 if (chars_read && ! p_line[p_end]) { 1507 p_end--; 1508 return -1; 1509 } 1510 break; 1511 default: 1512 if (repl_beginning && repl_could_be_missing) { 1513 repl_missing = true; 1514 goto hunk_done; 1515 } 1516 malformed (); 1517 } 1518 } 1519 1520 hunk_done: 1521 if (p_end >=0 && !repl_beginning) 1522 fatal ("no '---' found in patch at line %s", 1523 format_linenum (numbuf0, pch_hunk_beg ())); 1524 1525 if (repl_missing) { 1526 1527 /* reset state back to just after --- */ 1528 p_input_line = repl_patch_line; 1529 context = repl_context; 1530 for (p_end--; p_end > repl_beginning; p_end--) 1531 free(p_line[p_end]); 1532 Fseek (pfp, repl_backtrack_position, SEEK_SET); 1533 1534 /* redundant 'new' context lines were omitted - set */ 1535 /* up to fill them in from the old file context */ 1536 fillsrc = 1; 1537 filldst = repl_beginning+1; 1538 fillcnt = p_repl_lines; 1539 p_end = p_max; 1540 } 1541 else if (! ptrn_missing && ptrn_copiable != repl_copiable) 1542 fatal ("context mangled in hunk at line %s", 1543 format_linenum (numbuf0, p_hunk_beg)); 1544 else if (!some_context && fillcnt == 1) { 1545 /* the first hunk was a null hunk with no context */ 1546 /* and we were expecting one line -- fix it up. */ 1547 while (filldst < p_end) { 1548 p_line[filldst] = p_line[filldst+1]; 1549 p_Char[filldst] = p_Char[filldst+1]; 1550 p_len[filldst] = p_len[filldst+1]; 1551 filldst++; 1552 } 1553#if 0 1554 repl_beginning--; /* this doesn't need to be fixed */ 1555#endif 1556 p_end--; 1557 p_first++; /* do append rather than insert */ 1558 fillcnt = 0; 1559 p_ptrn_lines = 0; 1560 } 1561 1562 p_prefix_context = ((repl_prefix_context == -1 1563 || (ptrn_prefix_context != -1 1564 && ptrn_prefix_context < repl_prefix_context)) 1565 ? ptrn_prefix_context : repl_prefix_context); 1566 p_suffix_context = ((ptrn_suffix_context != -1 1567 && ptrn_suffix_context < context) 1568 ? ptrn_suffix_context : context); 1569 if (p_prefix_context == -1 || p_suffix_context == -1) 1570 fatal ("replacement text or line numbers mangled in hunk at line %s", 1571 format_linenum (numbuf0, p_hunk_beg)); 1572 1573 if (difftype == CONTEXT_DIFF 1574 && (fillcnt 1575 || (p_first > 1 1576 && p_prefix_context + p_suffix_context < ptrn_copiable))) { 1577 if (verbosity == VERBOSE) 1578 say ("%s\n%s\n%s\n", 1579"(Fascinating -- this is really a new-style context diff but without", 1580"the telltale extra asterisks on the *** line that usually indicate", 1581"the new style...)"); 1582 diff_type = difftype = NEW_CONTEXT_DIFF; 1583 } 1584 1585 /* if there were omitted context lines, fill them in now */ 1586 if (fillcnt) { 1587 p_bfake = filldst; /* remember where not to free() */ 1588 p_efake = filldst + fillcnt - 1; 1589 while (fillcnt-- > 0) { 1590 while (fillsrc <= p_end && fillsrc != repl_beginning 1591 && p_Char[fillsrc] != ' ') 1592 fillsrc++; 1593 if (p_end < fillsrc || fillsrc == repl_beginning) 1594 { 1595 fatal ("replacement text or line numbers mangled in hunk at line %s", 1596 format_linenum (numbuf0, p_hunk_beg)); 1597 } 1598 p_line[filldst] = p_line[fillsrc]; 1599 p_Char[filldst] = p_Char[fillsrc]; 1600 p_len[filldst] = p_len[fillsrc]; 1601 fillsrc++; filldst++; 1602 } 1603 while (fillsrc <= p_end && fillsrc != repl_beginning) 1604 { 1605 if (p_Char[fillsrc] == ' ') 1606 fatal ("replacement text or line numbers mangled in hunk at line %s", 1607 format_linenum (numbuf0, p_hunk_beg)); 1608 fillsrc++; 1609 } 1610 if (debug & 64) 1611 printf ("fillsrc %s, filldst %s, rb %s, e+1 %s\n", 1612 format_linenum (numbuf0, fillsrc), 1613 format_linenum (numbuf1, filldst), 1614 format_linenum (numbuf2, repl_beginning), 1615 format_linenum (numbuf3, p_end + 1)); 1616 assert(fillsrc==p_end+1 || fillsrc==repl_beginning); 1617 assert(filldst==p_end+1 || filldst==repl_beginning); 1618 } 1619 } 1620 else if (difftype == UNI_DIFF) { 1621 file_offset line_beginning = file_tell (pfp); /* file pos of the current line */ 1622 lin fillsrc; /* index of old lines */ 1623 lin filldst; /* index of new lines */ 1624 char ch = '\0'; 1625 1626 chars_read = get_line (); 1627 if (chars_read == (size_t) -1 1628 || chars_read <= 4 1629 || strncmp (buf, "@@ -", 4) != 0) { 1630 next_intuit_at(line_beginning,p_input_line); 1631 return chars_read == (size_t) -1 ? -1 : 0; 1632 } 1633 s = scan_linenum (buf + 4, &p_first); 1634 if (*s == ',') 1635 s = scan_linenum (s + 1, &p_ptrn_lines); 1636 else 1637 p_ptrn_lines = 1; 1638 if (p_first >= LINENUM_MAX - p_ptrn_lines) 1639 malformed (); 1640 if (*s == ' ') s++; 1641 if (*s != '+') 1642 malformed (); 1643 s = scan_linenum (s + 1, &p_newfirst); 1644 if (*s == ',') 1645 s = scan_linenum (s + 1, &p_repl_lines); 1646 else 1647 p_repl_lines = 1; 1648 if (p_newfirst >= LINENUM_MAX - p_repl_lines) 1649 malformed (); 1650 if (*s == ' ') s++; 1651 if (*s++ != '@') 1652 malformed (); 1653 if (*s++ == '@' && *s == ' ') 1654 { 1655 p_c_function = s; 1656 while (*s != '\n') 1657 s++; 1658 *s = '\0'; 1659 p_c_function = savestr (p_c_function); 1660 if (! p_c_function) 1661 return -1; 1662 } 1663 if (!p_ptrn_lines) 1664 p_first++; /* do append rather than insert */ 1665 if (!p_repl_lines) 1666 p_newfirst++; 1667 if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1)) 1668 malformed (); 1669 p_max = p_ptrn_lines + p_repl_lines + 1; 1670 while (p_max + 1 >= hunkmax) 1671 if (! grow_hunkmax ()) 1672 return -1; 1673 fillsrc = 1; 1674 filldst = fillsrc + p_ptrn_lines; 1675 p_end = filldst + p_repl_lines; 1676 sprintf (buf, "*** %s,%s ****\n", 1677 format_linenum (numbuf0, p_first), 1678 format_linenum (numbuf1, p_first + p_ptrn_lines - 1)); 1679 p_len[0] = strlen (buf); 1680 if (! (p_line[0] = savestr (buf))) { 1681 p_end = -1; 1682 return -1; 1683 } 1684 p_Char[0] = '*'; 1685 sprintf (buf, "--- %s,%s ----\n", 1686 format_linenum (numbuf0, p_newfirst), 1687 format_linenum (numbuf1, p_newfirst + p_repl_lines - 1)); 1688 p_len[filldst] = strlen (buf); 1689 if (! (p_line[filldst] = savestr (buf))) { 1690 p_end = 0; 1691 return -1; 1692 } 1693 p_Char[filldst++] = '='; 1694 p_prefix_context = -1; 1695 p_hunk_beg = p_input_line + 1; 1696 while (fillsrc <= p_ptrn_lines || filldst <= p_end) { 1697 chars_read = get_line (); 1698 if (!chars_read) { 1699 if (p_max - filldst < 3) { 1700 strcpy (buf, " \n"); /* assume blank lines got chopped */ 1701 chars_read = 2; 1702 } else { 1703 fatal ("unexpected end of file in patch"); 1704 } 1705 } 1706 if (chars_read == (size_t) -1) 1707 s = 0; 1708 else if (*buf == '\t' || *buf == '\n') { 1709 ch = ' '; /* assume the space got eaten */ 1710 s = savebuf (buf, chars_read); 1711 } 1712 else { 1713 ch = *buf; 1714 s = savebuf (buf+1, --chars_read); 1715 } 1716 if (chars_read && ! s) 1717 { 1718 while (--filldst > p_ptrn_lines) 1719 free(p_line[filldst]); 1720 p_end = fillsrc-1; 1721 return -1; 1722 } 1723 switch (ch) { 1724 case '-': 1725 if (fillsrc > p_ptrn_lines) { 1726 free(s); 1727 p_end = filldst-1; 1728 malformed (); 1729 } 1730 chars_read -= fillsrc == p_ptrn_lines && incomplete_line (); 1731 p_Char[fillsrc] = ch; 1732 p_line[fillsrc] = s; 1733 p_len[fillsrc++] = chars_read; 1734 break; 1735 case '=': 1736 ch = ' '; 1737 /* FALL THROUGH */ 1738 case ' ': 1739 if (fillsrc > p_ptrn_lines) { 1740 free(s); 1741 while (--filldst > p_ptrn_lines) 1742 free(p_line[filldst]); 1743 p_end = fillsrc-1; 1744 malformed (); 1745 } 1746 context++; 1747 chars_read -= fillsrc == p_ptrn_lines && incomplete_line (); 1748 p_Char[fillsrc] = ch; 1749 p_line[fillsrc] = s; 1750 p_len[fillsrc++] = chars_read; 1751 s = savebuf (s, chars_read); 1752 if (chars_read && ! s) { 1753 while (--filldst > p_ptrn_lines) 1754 free(p_line[filldst]); 1755 p_end = fillsrc-1; 1756 return -1; 1757 } 1758 /* FALL THROUGH */ 1759 case '+': 1760 if (filldst > p_end) { 1761 free(s); 1762 while (--filldst > p_ptrn_lines) 1763 free(p_line[filldst]); 1764 p_end = fillsrc-1; 1765 malformed (); 1766 } 1767 chars_read -= filldst == p_end && incomplete_line (); 1768 p_Char[filldst] = ch; 1769 p_line[filldst] = s; 1770 p_len[filldst++] = chars_read; 1771 break; 1772 default: 1773 p_end = filldst; 1774 malformed (); 1775 } 1776 if (ch != ' ') { 1777 if (p_prefix_context == -1) 1778 p_prefix_context = context; 1779 context = 0; 1780 } 1781 }/* while */ 1782 if (p_prefix_context == -1) 1783 malformed (); 1784 p_suffix_context = context; 1785 } 1786 else { /* normal diff--fake it up */ 1787 char hunk_type; 1788 int i; 1789 lin min, max; 1790 file_offset line_beginning = file_tell (pfp); 1791 1792 p_prefix_context = p_suffix_context = 0; 1793 chars_read = get_line (); 1794 if (chars_read == (size_t) -1 || !chars_read || !ISDIGIT (*buf)) { 1795 next_intuit_at(line_beginning,p_input_line); 1796 return chars_read == (size_t) -1 ? -1 : 0; 1797 } 1798 s = scan_linenum (buf, &p_first); 1799 if (*s == ',') { 1800 s = scan_linenum (s + 1, &p_ptrn_lines); 1801 p_ptrn_lines += 1 - p_first; 1802 } 1803 else 1804 p_ptrn_lines = (*s != 'a'); 1805 if (p_first >= LINENUM_MAX - p_ptrn_lines) 1806 malformed (); 1807 hunk_type = *s; 1808 if (hunk_type == 'a') 1809 p_first++; /* do append rather than insert */ 1810 s = scan_linenum (s + 1, &min); 1811 if (*s == ',') 1812 scan_linenum (s + 1, &max); 1813 else 1814 max = min; 1815 if (min > max || max - min == LINENUM_MAX) 1816 malformed (); 1817 if (hunk_type == 'd') 1818 min++; 1819 p_newfirst = min; 1820 p_repl_lines = max - min + 1; 1821 if (p_newfirst >= LINENUM_MAX - p_repl_lines) 1822 malformed (); 1823 if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1)) 1824 malformed (); 1825 p_end = p_ptrn_lines + p_repl_lines + 1; 1826 while (p_end + 1 >= hunkmax) 1827 if (! grow_hunkmax ()) 1828 { 1829 p_end = -1; 1830 return -1; 1831 } 1832 sprintf (buf, "*** %s,%s\n", 1833 format_linenum (numbuf0, p_first), 1834 format_linenum (numbuf1, p_first + p_ptrn_lines - 1)); 1835 p_len[0] = strlen (buf); 1836 if (! (p_line[0] = savestr (buf))) { 1837 p_end = -1; 1838 return -1; 1839 } 1840 p_Char[0] = '*'; 1841 for (i=1; i<=p_ptrn_lines; i++) { 1842 chars_read = get_line (); 1843 if (chars_read == (size_t) -1) 1844 { 1845 p_end = i - 1; 1846 return -1; 1847 } 1848 if (!chars_read) 1849 fatal ("unexpected end of file in patch at line %s", 1850 format_linenum (numbuf0, p_input_line)); 1851 if (buf[0] != '<' || (buf[1] != ' ' && buf[1] != '\t')) 1852 fatal ("'<' followed by space or tab expected at line %s of patch", 1853 format_linenum (numbuf0, p_input_line)); 1854 chars_read -= 2 + (i == p_ptrn_lines && incomplete_line ()); 1855 p_len[i] = chars_read; 1856 p_line[i] = savebuf (buf + 2, chars_read); 1857 if (chars_read && ! p_line[i]) { 1858 p_end = i-1; 1859 return -1; 1860 } 1861 p_Char[i] = '-'; 1862 } 1863 if (hunk_type == 'c') { 1864 chars_read = get_line (); 1865 if (chars_read == (size_t) -1) 1866 { 1867 p_end = i - 1; 1868 return -1; 1869 } 1870 if (! chars_read) 1871 fatal ("unexpected end of file in patch at line %s", 1872 format_linenum (numbuf0, p_input_line)); 1873 if (*buf != '-') 1874 fatal ("'---' expected at line %s of patch", 1875 format_linenum (numbuf0, p_input_line)); 1876 } 1877 sprintf (buf, "--- %s,%s\n", 1878 format_linenum (numbuf0, min), 1879 format_linenum (numbuf1, max)); 1880 p_len[i] = strlen (buf); 1881 if (! (p_line[i] = savestr (buf))) { 1882 p_end = i-1; 1883 return -1; 1884 } 1885 p_Char[i] = '='; 1886 for (i++; i<=p_end; i++) { 1887 chars_read = get_line (); 1888 if (chars_read == (size_t) -1) 1889 { 1890 p_end = i - 1; 1891 return -1; 1892 } 1893 if (!chars_read) 1894 fatal ("unexpected end of file in patch at line %s", 1895 format_linenum (numbuf0, p_input_line)); 1896 if (buf[0] != '>' || (buf[1] != ' ' && buf[1] != '\t')) 1897 fatal ("'>' followed by space or tab expected at line %s of patch", 1898 format_linenum (numbuf0, p_input_line)); 1899 chars_read -= 2 + (i == p_end && incomplete_line ()); 1900 p_len[i] = chars_read; 1901 p_line[i] = savebuf (buf + 2, chars_read); 1902 if (chars_read && ! p_line[i]) { 1903 p_end = i-1; 1904 return -1; 1905 } 1906 p_Char[i] = '+'; 1907 } 1908 } 1909 if (rev) /* backwards patch? */ 1910 if (!pch_swap()) 1911 say ("Not enough memory to swap next hunk!\n"); 1912 assert (p_end + 1 < hunkmax); 1913 p_Char[p_end + 1] = '^'; /* add a stopper for apply_hunk */ 1914 if (debug & 2) { 1915 lin i; 1916 1917 for (i = 0; i <= p_end + 1; i++) { 1918 fprintf (stderr, "%s %c", 1919 format_linenum (numbuf0, i), 1920 p_Char[i]); 1921 if (p_Char[i] == '*') 1922 fprintf (stderr, " %s,%s\n", 1923 format_linenum (numbuf0, p_first), 1924 format_linenum (numbuf1, p_ptrn_lines)); 1925 else if (p_Char[i] == '=') 1926 fprintf (stderr, " %s,%s\n", 1927 format_linenum (numbuf0, p_newfirst), 1928 format_linenum (numbuf1, p_repl_lines)); 1929 else if (p_Char[i] != '^') 1930 { 1931 fputs(" |", stderr); 1932 pch_write_line (i, stderr); 1933 } 1934 else 1935 fputc('\n', stderr); 1936 } 1937 fflush (stderr); 1938 } 1939 return 1; 1940} 1941 1942static size_t 1943get_line (void) 1944{ 1945 return pget_line (p_indent, p_rfc934_nesting, p_strip_trailing_cr, 1946 p_pass_comments_through); 1947} 1948 1949/* Input a line from the patch file, worrying about indentation. 1950 Strip up to INDENT characters' worth of leading indentation. 1951 Then remove up to RFC934_NESTING instances of leading "- ". 1952 If STRIP_TRAILING_CR is true, remove any trailing carriage-return. 1953 Unless PASS_COMMENTS_THROUGH is true, ignore any resulting lines 1954 that begin with '#'; they're comments. 1955 Ignore any partial lines at end of input, but warn about them. 1956 Succeed if a line was read; it is terminated by "\n\0" for convenience. 1957 Return the number of characters read, including '\n' but not '\0'. 1958 Return -1 if we ran out of memory. */ 1959 1960static size_t 1961pget_line (size_t indent, int rfc934_nesting, bool strip_trailing_cr, 1962 bool pass_comments_through) 1963{ 1964 FILE *fp = pfp; 1965 int c; 1966 size_t i; 1967 char *b; 1968 size_t s; 1969 1970 do 1971 { 1972 i = 0; 1973 for (;;) 1974 { 1975 c = getc (fp); 1976 if (c == EOF) 1977 { 1978 if (ferror (fp)) 1979 read_fatal (); 1980 return 0; 1981 } 1982 if (indent <= i) 1983 break; 1984 if (c == ' ' || c == 'X') 1985 i++; 1986 else if (c == '\t') 1987 i = (i + 8) & ~7; 1988 else 1989 break; 1990 } 1991 1992 i = 0; 1993 b = buf; 1994 1995 while (c == '-' && 0 <= --rfc934_nesting) 1996 { 1997 c = getc (fp); 1998 if (c == EOF) 1999 goto patch_ends_in_middle_of_line; 2000 if (c != ' ') 2001 { 2002 i = 1; 2003 b[0] = '-'; 2004 break; 2005 } 2006 c = getc (fp); 2007 if (c == EOF) 2008 goto patch_ends_in_middle_of_line; 2009 } 2010 2011 s = bufsize; 2012 2013 for (;;) 2014 { 2015 if (i == s - 1) 2016 { 2017 s *= 2; 2018 b = realloc (b, s); 2019 if (!b) 2020 { 2021 if (!using_plan_a) 2022 xalloc_die (); 2023 return (size_t) -1; 2024 } 2025 buf = b; 2026 bufsize = s; 2027 } 2028 b[i++] = c; 2029 if (c == '\n') 2030 break; 2031 c = getc (fp); 2032 if (c == EOF) 2033 goto patch_ends_in_middle_of_line; 2034 } 2035 2036 p_input_line++; 2037 } 2038 while (*b == '#' && !pass_comments_through); 2039 2040 if (strip_trailing_cr && 2 <= i && b[i - 2] == '\r') 2041 b[i-- - 2] = '\n'; 2042 b[i] = '\0'; 2043 return i; 2044 2045 patch_ends_in_middle_of_line: 2046 if (ferror (fp)) 2047 read_fatal (); 2048 say ("patch unexpectedly ends in middle of line\n"); 2049 return 0; 2050} 2051 2052static bool 2053incomplete_line (void) 2054{ 2055 FILE *fp = pfp; 2056 int c; 2057 file_offset line_beginning = file_tell (fp); 2058 2059 if (getc (fp) == '\\') 2060 { 2061 while ((c = getc (fp)) != '\n' && c != EOF) 2062 /* do nothing */ ; 2063 return true; 2064 } 2065 else 2066 { 2067 /* We don't trust ungetc. */ 2068 Fseek (pfp, line_beginning, SEEK_SET); 2069 return false; 2070 } 2071} 2072 2073/* Reverse the old and new portions of the current hunk. */ 2074 2075bool 2076pch_swap (void) 2077{ 2078 char **tp_line; /* the text of the hunk */ 2079 size_t *tp_len; /* length of each line */ 2080 char *tp_char; /* +, -, and ! */ 2081 lin i; 2082 lin n; 2083 bool blankline = false; 2084 char *s; 2085 2086 i = p_first; 2087 p_first = p_newfirst; 2088 p_newfirst = i; 2089 2090 /* make a scratch copy */ 2091 2092 tp_line = p_line; 2093 tp_len = p_len; 2094 tp_char = p_Char; 2095 p_line = 0; /* force set_hunkmax to allocate again */ 2096 p_len = 0; 2097 p_Char = 0; 2098 set_hunkmax(); 2099 if (!p_line || !p_len || !p_Char) { 2100 free (p_line); 2101 p_line = tp_line; 2102 free (p_len); 2103 p_len = tp_len; 2104 free (p_Char); 2105 p_Char = tp_char; 2106 return false; /* not enough memory to swap hunk! */ 2107 } 2108 2109 /* now turn the new into the old */ 2110 2111 i = p_ptrn_lines + 1; 2112 if (tp_char[i] == '\n') { /* account for possible blank line */ 2113 blankline = true; 2114 i++; 2115 } 2116 if (p_efake >= 0) { /* fix non-freeable ptr range */ 2117 if (p_efake <= i) 2118 n = p_end - i + 1; 2119 else 2120 n = -i; 2121 p_efake += n; 2122 p_bfake += n; 2123 } 2124 for (n=0; i <= p_end; i++,n++) { 2125 p_line[n] = tp_line[i]; 2126 p_Char[n] = tp_char[i]; 2127 if (p_Char[n] == '+') 2128 p_Char[n] = '-'; 2129 p_len[n] = tp_len[i]; 2130 } 2131 if (blankline) { 2132 i = p_ptrn_lines + 1; 2133 p_line[n] = tp_line[i]; 2134 p_Char[n] = tp_char[i]; 2135 p_len[n] = tp_len[i]; 2136 n++; 2137 } 2138 assert(p_Char[0] == '='); 2139 p_Char[0] = '*'; 2140 for (s=p_line[0]; *s; s++) 2141 if (*s == '-') 2142 *s = '*'; 2143 2144 /* now turn the old into the new */ 2145 2146 assert(tp_char[0] == '*'); 2147 tp_char[0] = '='; 2148 for (s=tp_line[0]; *s; s++) 2149 if (*s == '*') 2150 *s = '-'; 2151 for (i=0; n <= p_end; i++,n++) { 2152 p_line[n] = tp_line[i]; 2153 p_Char[n] = tp_char[i]; 2154 if (p_Char[n] == '-') 2155 p_Char[n] = '+'; 2156 p_len[n] = tp_len[i]; 2157 } 2158 assert(i == p_ptrn_lines + 1); 2159 i = p_ptrn_lines; 2160 p_ptrn_lines = p_repl_lines; 2161 p_repl_lines = i; 2162 p_Char[p_end + 1] = '^'; 2163 free (tp_line); 2164 free (tp_len); 2165 free (tp_char); 2166 return true; 2167} 2168 2169/* Return whether file WHICH (false = old, true = new) appears to nonexistent. 2170 Return 1 for empty, 2 for nonexistent. */ 2171 2172int 2173pch_says_nonexistent (bool which) 2174{ 2175 return p_says_nonexistent[which]; 2176} 2177 2178const char * 2179pch_name (enum nametype type) 2180{ 2181 return type == NONE ? NULL : p_name[type]; 2182} 2183 2184bool pch_copy (void) 2185{ 2186 return p_copy[OLD] && p_copy[NEW]; 2187} 2188 2189bool pch_rename (void) 2190{ 2191 return p_rename[OLD] && p_rename[NEW]; 2192} 2193 2194/* Return the specified line position in the old file of the old context. */ 2195 2196lin 2197pch_first (void) 2198{ 2199 return p_first; 2200} 2201 2202/* Return the number of lines of old context. */ 2203 2204lin 2205pch_ptrn_lines (void) 2206{ 2207 return p_ptrn_lines; 2208} 2209 2210/* Return the probable line position in the new file of the first line. */ 2211 2212lin 2213pch_newfirst (void) 2214{ 2215 return p_newfirst; 2216} 2217 2218/* Return the number of lines in the replacement text including context. */ 2219 2220lin 2221pch_repl_lines (void) 2222{ 2223 return p_repl_lines; 2224} 2225 2226/* Return the number of lines in the whole hunk. */ 2227 2228lin 2229pch_end (void) 2230{ 2231 return p_end; 2232} 2233 2234/* Return the number of context lines before the first changed line. */ 2235 2236lin 2237pch_prefix_context (void) 2238{ 2239 return p_prefix_context; 2240} 2241 2242/* Return the number of context lines after the last changed line. */ 2243 2244lin 2245pch_suffix_context (void) 2246{ 2247 return p_suffix_context; 2248} 2249 2250/* Return the length of a particular patch line. */ 2251 2252size_t 2253pch_line_len (lin line) 2254{ 2255 return p_len[line]; 2256} 2257 2258/* Return the control character (+, -, *, !, etc) for a patch line. A '\n' 2259 indicates an empty line in a hunk. (The empty line is not part of the 2260 old or new context. For some reson, the context format allows that.) */ 2261 2262char 2263pch_char (lin line) 2264{ 2265 return p_Char[line]; 2266} 2267 2268/* Return a pointer to a particular patch line. */ 2269 2270char * 2271pfetch (lin line) 2272{ 2273 return p_line[line]; 2274} 2275 2276/* Output a patch line. */ 2277 2278bool 2279pch_write_line (lin line, FILE *file) 2280{ 2281 bool after_newline = (p_len[line] > 0) && (p_line[line][p_len[line] - 1] == '\n'); 2282 if (! fwrite (p_line[line], sizeof (*p_line[line]), p_len[line], file)) 2283 write_fatal (); 2284 return after_newline; 2285} 2286 2287/* Return where in the patch file this hunk began, for error messages. */ 2288 2289lin 2290pch_hunk_beg (void) 2291{ 2292 return p_hunk_beg; 2293} 2294 2295char const * 2296pch_c_function (void) 2297{ 2298 return p_c_function; 2299} 2300 2301/* Return true if in a git-style patch. */ 2302 2303bool 2304pch_git_diff (void) 2305{ 2306 return p_git_diff; 2307} 2308 2309char const * 2310pch_timestr (bool which) 2311{ 2312 return p_timestr[which]; 2313} 2314 2315char const * 2316pch_sha1 (bool which) 2317{ 2318 return p_sha1[which]; 2319} 2320 2321mode_t 2322pch_mode (bool which) 2323{ 2324 return p_mode[which]; 2325} 2326 2327/* Is the newline-terminated line a valid 'ed' command for patch 2328 input? If so, return the command character; if not, return 0. 2329 This accepts just a subset of the valid commands, but it's 2330 good enough in practice. */ 2331 2332static char _GL_ATTRIBUTE_PURE 2333get_ed_command_letter (char const *line) 2334{ 2335 char const *p = line; 2336 char letter; 2337 bool pair = false; 2338 2339 if (ISDIGIT (*p)) 2340 { 2341 while (ISDIGIT (*++p)) 2342 /* do nothing */ ; 2343 if (*p == ',') 2344 { 2345 if (! ISDIGIT (*++p)) 2346 return 0; 2347 while (ISDIGIT (*++p)) 2348 /* do nothing */ ; 2349 pair = true; 2350 } 2351 } 2352 2353 letter = *p++; 2354 2355 switch (letter) 2356 { 2357 case 'a': 2358 case 'i': 2359 if (pair) 2360 return 0; 2361 break; 2362 2363 case 'c': 2364 case 'd': 2365 break; 2366 2367 case 's': 2368 if (strncmp (p, "/.//", 4) != 0) 2369 return 0; 2370 p += 4; 2371 break; 2372 2373 default: 2374 return 0; 2375 } 2376 2377 while (*p == ' ' || *p == '\t') 2378 p++; 2379 if (*p == '\n') 2380 return letter; 2381 return 0; 2382} 2383 2384/* Apply an ed script by feeding ed itself. */ 2385 2386void 2387do_ed_script (char const *inname, char const *outname, 2388 bool *outname_needs_removal, FILE *ofp) 2389{ 2390 static char const editor_program[] = EDITOR_PROGRAM; 2391 2392 file_offset beginning_of_this_line; 2393 size_t chars_read; 2394 FILE *tmpfp = 0; 2395 int tmpfd; 2396 pid_t pid; 2397 2398 if (! dry_run && ! skip_rest_of_patch) 2399 { 2400 /* Write ed script to a temporary file. This causes ed to abort on 2401 invalid commands such as when line numbers or ranges exceed the 2402 number of available lines. When ed reads from a pipe, it rejects 2403 invalid commands and treats the next line as a new command, which 2404 can lead to arbitrary command execution. */ 2405 2406 tmpfd = make_tempfile (&TMPEDNAME, 'e', NULL, O_RDWR | O_BINARY, 0); 2407 if (tmpfd == -1) 2408 pfatal ("Can't create temporary file %s", quotearg (TMPEDNAME)); 2409 TMPEDNAME_needs_removal = true; 2410 tmpfp = fdopen (tmpfd, "w+b"); 2411 if (! tmpfp) 2412 pfatal ("Can't open stream for file %s", quotearg (TMPEDNAME)); 2413 } 2414 2415 for (;;) { 2416 char ed_command_letter; 2417 beginning_of_this_line = file_tell (pfp); 2418 chars_read = get_line (); 2419 if (! chars_read) { 2420 next_intuit_at(beginning_of_this_line,p_input_line); 2421 break; 2422 } 2423 ed_command_letter = get_ed_command_letter (buf); 2424 if (ed_command_letter) { 2425 if (tmpfp) 2426 if (! fwrite (buf, sizeof *buf, chars_read, tmpfp)) 2427 write_fatal (); 2428 if (ed_command_letter != 'd' && ed_command_letter != 's') { 2429 p_pass_comments_through = true; 2430 while ((chars_read = get_line ()) != 0) { 2431 if (tmpfp) 2432 if (! fwrite (buf, sizeof *buf, chars_read, tmpfp)) 2433 write_fatal (); 2434 if (chars_read == 2 && strEQ (buf, ".\n")) 2435 break; 2436 } 2437 p_pass_comments_through = false; 2438 } 2439 } 2440 else { 2441 next_intuit_at(beginning_of_this_line,p_input_line); 2442 break; 2443 } 2444 } 2445 if (!tmpfp) 2446 return; 2447 if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, tmpfp) == 0 2448 || fflush (tmpfp) != 0) 2449 write_fatal (); 2450 2451 if (lseek (tmpfd, 0, SEEK_SET) == -1) 2452 pfatal ("Can't rewind to the beginning of file %s", quotearg (TMPEDNAME)); 2453 2454 if (! dry_run && ! skip_rest_of_patch) { 2455 int exclusive = *outname_needs_removal ? 0 : O_EXCL; 2456 *outname_needs_removal = true; 2457 if (inerrno != ENOENT) 2458 { 2459 *outname_needs_removal = true; 2460 copy_file (inname, outname, 0, exclusive, instat.st_mode, true); 2461 } 2462 fflush (stdout); 2463 2464 pid = fork(); 2465 if (pid == -1) 2466 pfatal ("Can't fork"); 2467 else if (pid == 0) 2468 { 2469 dup2 (tmpfd, 0); 2470 assert (outname[0] != '!' && outname[0] != '-'); 2471 execlp (editor_program, editor_program, "-", outname, (char *) NULL); 2472 _exit (2); 2473 } 2474 else 2475 { 2476 int wstatus; 2477 if (waitpid (pid, &wstatus, 0) == -1 2478 || ! WIFEXITED (wstatus) 2479 || WEXITSTATUS (wstatus) != 0) 2480 fatal ("%s FAILED", editor_program); 2481 } 2482 } 2483 2484 fclose (tmpfp); 2485 2486 if (ofp) 2487 { 2488 FILE *ifp = fopen (outname, binary_transput ? "rb" : "r"); 2489 int c; 2490 if (!ifp) 2491 pfatal ("can't open '%s'", outname); 2492 while ((c = getc (ifp)) != EOF) 2493 if (putc (c, ofp) == EOF) 2494 write_fatal (); 2495 if (ferror (ifp) || fclose (ifp) != 0) 2496 read_fatal (); 2497 } 2498} 2499 2500void 2501pch_normalize (enum diff format) 2502{ 2503 lin old = 1; 2504 lin new = p_ptrn_lines + 1; 2505 2506 while (p_Char[new] == '=' || p_Char[new] == '\n') 2507 new++; 2508 2509 if (format == UNI_DIFF) 2510 { 2511 /* Convert '!' markers into '-' and '+' as defined by the Unified 2512 Format. */ 2513 2514 for (; old <= p_ptrn_lines; old++) 2515 if (p_Char[old] == '!') 2516 p_Char[old] = '-'; 2517 for (; new <= p_end; new++) 2518 if (p_Char[new] == '!') 2519 p_Char[new] = '+'; 2520 } 2521 else 2522 { 2523 /* Convert '-' and '+' markers which are part of a group into '!' as 2524 defined by the Context Format. */ 2525 2526 while (old <= p_ptrn_lines) 2527 { 2528 if (p_Char[old] == '-') 2529 { 2530 if (new <= p_end && p_Char[new] == '+') 2531 { 2532 do 2533 { 2534 p_Char[old] = '!'; 2535 old++; 2536 } 2537 while (old <= p_ptrn_lines && p_Char[old] == '-'); 2538 do 2539 { 2540 p_Char[new] = '!'; 2541 new++; 2542 } 2543 while (new <= p_end && p_Char[new] == '+'); 2544 } 2545 else 2546 { 2547 do 2548 old++; 2549 while (old <= p_ptrn_lines && p_Char[old] == '-'); 2550 } 2551 } 2552 else if (new <= p_end && p_Char[new] == '+') 2553 { 2554 do 2555 new++; 2556 while (new <= p_end && p_Char[new] == '+'); 2557 } 2558 else 2559 { 2560 old++; 2561 new++; 2562 } 2563 } 2564 } 2565} 2566