1 # Buildsheet autogenerated by ravenadm tool -- Do not edit.
7 SDESC[standard]= BSD variant of famous patch program
8 HOMEPAGE= https://www.freebsd.org/cgi/man.cgi?patch(1)
9 CONTACT= John_Marino[draco@marino.st]
12 SPKGS[standard]= single
14 OPTIONS_AVAILABLE= none
15 OPTIONS_STANDARD= none
17 B_DEPS[sunos]= libbsd4sol:single:standard
18 B_DEPS[linux]= libbsd:single:standard
20 LICENSE= CUSTOM1:single
21 LICENSE_NAME= CUSTOM1:"Patch license from Larry Wall"
22 LICENSE_FILE= CUSTOM1:{{WRKSRC}}/LICENSE
27 cp ${FILESDIR}/* ${WRKSRC}/
29 [FILE:565:descriptions/desc.single]
30 This version of patch comes FreeBSD which means there are heavy influences
31 from DragonFly, OpenBSD and NetBSD as well.
33 The primary purpose of this port is to replace GNU patch in the
34 Ravenports system root. The BSD version of patch correctly locates
35 upwards relative paths such as "--- ../../module3-2.a/configure" while
36 GNU patch fails to find it. As this is a crucial feature, especially
37 for "extra patches", the GNU patch program has to be replaced.
39 The OpenBSD modification of handling git-style patches (the "--- a/" and
40 "+++ b/" formats are also present.
43 [FILE:36:manifests/plist.single]
45 share/man/man1/patch.1.gz
48 [FILE:1672:files/LICENSE]
50 * Copyright 1986, Larry Wall
52 * Redistribution and use in source and binary forms, with or without
53 * modification, are permitted provided that the following condition is met:
54 * 1. Redistributions of source code must retain the above copyright notice,
55 * this condition and the following disclaimer.
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
58 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
59 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
60 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
61 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
63 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
64 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * patch - a program to apply diffs to original files
71 * -C option added in 1998, original code by Marc Espie, based on FreeBSD
77 * backupfile -- declarations for making Emacs style backup file names
78 * Copyright (C) 1990 Free Software Foundation, Inc.
80 * This program is free software; you can redistribute it and/or modify it
81 * without restriction.
83 * This program is distributed in the hope that it will be useful, but WITHOUT
84 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
85 * FITNESS FOR A PARTICULAR PURPOSE.
90 [FILE:581:files/Makefile]
92 SRCS= ${PROG}.c pch.c inp.c util.c backupfile.c mkpath.c \
95 CFLAGS+= -I${PREFIX}/include -I.
98 .if "${OPSYS}" == "Linux"
99 STATIC_LIBS+= ${PREFIX}/lib/libbsd.a
101 .if "${OPSYS}" == "SunOS"
102 STATIC_LIBS+= ${PREFIX}/lib/libbsd.a
103 CFLAGS+= -I${PREFIX}/include/bsd
109 rm -f ${OBJS} ${PROG}
112 ${CC} -o ${PROG} ${.ALLSRC} ${CFLAGS} ${STATIC_LIBS}
115 ${BSD_INSTALL_PROGRAM} ${PROG} ${DESTDIR}${PREFIX}/bin/
116 ${BSD_INSTALL_MAN} ${PROG}.1 ${DESTDIR}${PREFIX}/share/man/man1
119 [FILE:5856:files/backupfile.c]
128 #include "backupfile.h"
129 #include "linux_support.h"
132 #define ISDIGIT(c) (isascii ((unsigned char)c) && isdigit ((unsigned char)c))
134 /* Which type of backup file names are generated. */
135 enum backup_type backup_type = none;
138 * The extension added to file names to produce a simple (as opposed to
139 * numbered) backup file name.
141 const char *simple_backup_suffix = "~";
143 static char *concat(const char *, const char *);
144 static char *make_version_name(const char *, int);
145 static int max_backup_version(const char *, const char *);
146 static int version_number(const char *, const char *, size_t);
147 static int argmatch(const char *, const char **);
148 static void invalid_arg(const char *, const char *, int);
151 * Return the name of the new backup file for file FILE, allocated with
152 * malloc. Return 0 if out of memory. FILE must not end with a '/' unless it
153 * is the root directory. Do not call this function if backup_type == none.
156 find_backup_file_name(const char *file)
158 char *dir, *base_versions, *tmp_file;
161 if (backup_type == simple)
162 return concat(file, simple_backup_suffix);
163 tmp_file = strdup(file);
164 if (tmp_file == NULL)
166 base_versions = concat(basename(tmp_file), ".~");
168 if (base_versions == NULL)
170 tmp_file = strdup(file);
171 if (tmp_file == NULL) {
175 dir = dirname(tmp_file);
181 highest_backup = max_backup_version(base_versions, dir);
184 if (backup_type == numbered_existing && highest_backup == 0)
185 return concat(file, simple_backup_suffix);
186 return make_version_name(file, highest_backup + 1);
190 * Return the number of the highest-numbered backup file for file FILE in
191 * directory DIR. If there are no numbered backups of FILE in DIR, or an
192 * error occurs reading DIR, return 0. FILE should already have ".~" appended
196 max_backup_version(const char *file, const char *dir)
200 int highest_version, this_version;
201 size_t file_name_length;
208 file_name_length = strlen(file);
210 while ((dp = readdir(dirp)) != NULL) {
211 if (strlen(dp->d_name) <= file_name_length)
214 this_version = version_number(file, dp->d_name, file_name_length);
215 if (this_version > highest_version)
216 highest_version = this_version;
219 return highest_version;
223 * Return a string, allocated with malloc, containing "FILE.~VERSION~".
224 * Return 0 if out of memory.
227 make_version_name(const char *file, int version)
231 if (asprintf(&backup_name, "%s.~%d~", file, version) == -1)
237 * If BACKUP is a numbered backup of BASE, return its version number;
238 * otherwise return 0. BASE_LENGTH is the length of BASE. BASE should
239 * already have ".~" appended to it.
242 version_number(const char *base, const char *backup, size_t base_length)
248 if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) {
249 for (p = &backup[base_length]; ISDIGIT(*p); ++p)
250 version = version * 10 + *p - '0';
251 if (p[0] != '~' || p[1])
258 * Return the newly-allocated concatenation of STR1 and STR2. If out of
262 concat(const char *str1, const char *str2)
266 if (asprintf(&newstr, "%s%s", str1, str2) == -1)
272 * If ARG is an unambiguous match for an element of the null-terminated array
273 * OPTLIST, return the index in OPTLIST of the matched element, else -1 if it
274 * does not match any element or -2 if it is ambiguous (is a prefix of more
278 argmatch(const char *arg, const char **optlist)
280 int i; /* Temporary index in OPTLIST. */
281 size_t arglen; /* Length of ARG. */
282 int matchind = -1; /* Index of first nonexact match. */
283 int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
285 arglen = strlen(arg);
287 /* Test all elements for either exact match or abbreviated matches. */
288 for (i = 0; optlist[i]; i++) {
289 if (!strncmp(optlist[i], arg, arglen)) {
290 if (strlen(optlist[i]) == arglen)
291 /* Exact match found. */
293 else if (matchind == -1)
294 /* First nonexact match found. */
297 /* Second nonexact match found. */
308 * Error reporting for argmatch. KIND is a description of the type of entity
309 * that was being matched. VALUE is the invalid value that was given. PROBLEM
310 * is the return value from argmatch.
313 invalid_arg(const char *kind, const char *value, int problem)
315 fprintf(stderr, "patch: ");
317 fprintf(stderr, "invalid");
318 else /* Assume -2. */
319 fprintf(stderr, "ambiguous");
320 fprintf(stderr, " %s `%s'\n", kind, value);
323 static const char *backup_args[] = {
324 "none", "never", "simple", "nil", "existing", "t", "numbered", 0
327 static enum backup_type backup_types[] = {
328 none, simple, simple, numbered_existing,
329 numbered_existing, numbered, numbered
333 * Return the type of backup indicated by VERSION. Unique abbreviations are
337 get_version(const char *version)
341 if (version == NULL || *version == '\0')
342 return numbered_existing;
343 i = argmatch(version, backup_args);
345 return backup_types[i];
346 invalid_arg("version control type", version, i);
351 [FILE:514:files/backupfile.h]
352 /* When to make backup files. */
354 /* Never make backups. */
357 /* Make simple backups of every file. */
361 * Make numbered backups of files that already have numbered backups,
362 * and simple backups of the others.
366 /* Make numbered backups of every file. */
370 extern enum backup_type backup_type;
371 extern const char *simple_backup_suffix;
373 char *find_backup_file_name(const char *file);
374 enum backup_type get_version(const char *version);
377 [FILE:1855:files/common.h]
378 #include <sys/types.h>
382 #include "linux_support.h"
388 #define MAXHUNKSIZE 200000 /* is this enough lines? */
389 #define INITHUNKMAX 125 /* initial dynamic allocation size */
390 #define INITLINELEN 4096
391 #define BUFFERSIZE 4096
392 #define LINENUM_MAX LONG_MAX
394 #define ORIGEXT ".orig"
395 #define REJEXT ".rej"
397 /* handy definitions */
399 #define strEQ(s1,s2) (strcmp(s1, s2) == 0)
400 #define strnNE(s1,s2,l) (strncmp(s1, s2, l) != 0)
401 #define strnEQ(s1,s2,l) (strncmp(s1, s2, l) == 0)
405 typedef long LINENUM; /* must be signed */
406 enum vlevel { NORMAL_LEVEL, SILENT, VERBOSE };
410 extern mode_t filemode;
412 extern char *buf; /* general purpose buffer */
413 extern size_t buf_size; /* size of general purpose buffer */
415 extern bool using_plan_a; /* try to keep everything in memory */
416 extern bool out_of_mem; /* ran out of memory in plan a */
420 extern char *filearg[MAXFILEC];
421 extern bool ok_to_create_file;
422 extern char *outname;
423 extern char *origprae;
425 extern char *TMPOUTNAME;
426 extern char *TMPINNAME;
427 extern char *TMPREJNAME;
428 extern char *TMPPATNAME;
429 extern bool toutkeep;
430 extern bool trejkeep;
438 extern enum vlevel verbosity;
440 extern bool noreverse;
441 extern bool skip_rest_of_patch;
442 extern int strippath;
443 extern bool canonicalize;
444 /* TRUE if -C was specified on command line. */
445 extern bool check_only;
446 extern bool warn_on_invalid_line;
447 extern bool last_line_missing_eol;
450 #define CONTEXT_DIFF 1
451 #define NORMAL_DIFF 2
453 #define NEW_CONTEXT_DIFF 4
456 extern int diff_type;
457 extern char *revision; /* prerequisite revision, if any */
458 extern LINENUM input_lines; /* how long is input file in lines */
464 [FILE:9806:files/inp.c]
465 #include <sys/types.h>
466 #include <sys/file.h>
467 #include <sys/stat.h>
468 #include <sys/mman.h>
486 /* Input-file-with-indexable-lines abstract type */
488 static size_t i_size; /* size of the input file */
489 static char *i_womp; /* plan a buffer for entire file */
490 static char **i_ptr; /* pointers to lines in i_womp */
491 static char empty_line[] = { '\0' };
493 static int tifd = -1; /* plan b virtual string array */
494 static char *tibuf[2]; /* plan b buffers */
495 static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
496 static size_t lines_per_buf; /* how many lines per buffer */
497 static size_t tibuflen; /* plan b buffer length */
498 static size_t tireclen; /* length of records in tmp file */
500 static bool rev_in_string(const char *);
501 static bool reallocate_lines(size_t *);
503 /* returns false if insufficient memory */
504 static bool plan_a(const char *);
506 static void plan_b(const char *);
508 /* New patch--prepare to edit another file. */
516 if (i_womp != NULL) {
517 munmap(i_womp, i_size);
522 using_plan_a = true; /* maybe the next one is smaller */
527 tibuf[0] = tibuf[1] = NULL;
528 tiline[0] = tiline[1] = -1;
533 /* Construct the line index, somehow or other. */
536 scan_input(const char *filename)
538 if (!plan_a(filename))
540 if (verbosity != SILENT) {
541 say("Patching file %s using Plan %s...\n", filename,
542 (using_plan_a ? "A" : "B"));
547 reallocate_lines(size_t *lines_allocated)
552 new_size = *lines_allocated * 3 / 2;
553 p = realloc(i_ptr, (new_size + 2) * sizeof(char *));
554 if (p == NULL) { /* shucks, it was a near thing */
555 munmap(i_womp, i_size);
559 *lines_allocated = 0;
562 *lines_allocated = new_size;
567 /* Try keeping everything in memory. */
570 plan_a(const char *filename)
574 struct stat filestat;
577 size_t iline, lines_allocated;
584 if (filename == NULL || *filename == '\0')
587 statfailed = stat(filename, &filestat);
588 if (statfailed && ok_to_create_file) {
589 if (verbosity == VERBOSE)
590 say("(Creating file %s...)\n", filename);
593 * in check_patch case, we still display `Creating file' even
594 * though we're not. The rule is that -C should be as similar
595 * to normal patch behavior as possible
599 makedirs(filename, true);
600 close(creat(filename, 0666));
601 statfailed = stat(filename, &filestat);
604 fatal("can't find %s\n", filename);
605 filemode = filestat.st_mode;
606 if (!S_ISREG(filemode))
607 fatal("%s is not a normal file--can't patch\n", filename);
608 if ((uint64_t)filestat.st_size > SIZE_MAX) {
609 say("block too large to mmap\n");
612 i_size = (size_t)filestat.st_size;
614 set_hunkmax(); /* make sure dynamic arrays are allocated */
616 return false; /* force plan b because plan a bombed */
618 if ((ifd = open(filename, O_RDONLY)) < 0)
619 pfatal("can't open file %s", filename);
622 i_womp = mmap(NULL, i_size, PROT_READ, MAP_PRIVATE, ifd, 0);
623 if (i_womp == MAP_FAILED) {
624 perror("mmap failed");
635 madvise(i_womp, i_size, MADV_SEQUENTIAL);
637 /* estimate the number of lines */
638 lines_allocated = i_size / 25;
639 if (lines_allocated < 100)
640 lines_allocated = 100;
642 if (!reallocate_lines(&lines_allocated))
645 /* now scan the buffer and build pointer array */
647 i_ptr[iline] = i_womp;
648 /* test for NUL too, to maintain the behavior of the original code */
649 for (s = i_womp, i = 0; i < i_size && *s != '\0'; s++, i++) {
651 if (iline == lines_allocated) {
652 if (!reallocate_lines(&lines_allocated))
655 /* these are NOT NUL terminated */
656 i_ptr[++iline] = s + 1;
659 /* if the last line contains no EOL, append one */
660 if (i_size > 0 && i_womp[i_size - 1] != '\n') {
661 last_line_missing_eol = true;
663 sz = s - i_ptr[iline];
668 munmap(i_womp, i_size);
673 memcpy(p, i_ptr[iline], sz);
676 /* count the extra line and make it point to some valid mem */
677 i_ptr[++iline] = empty_line;
679 last_line_missing_eol = false;
681 input_lines = iline - 1;
683 /* now check for revision, if any */
685 if (revision != NULL) {
686 if (i_womp == NULL || !rev_in_string(i_womp)) {
688 if (verbosity == VERBOSE)
689 say("Warning: this file doesn't appear "
690 "to be the %s version--patching anyway.\n",
693 fatal("this file doesn't appear to be the "
694 "%s version--aborting.\n",
697 ask("This file doesn't appear to be the "
698 "%s version--patch anyway? [n] ",
703 } else if (verbosity == VERBOSE)
704 say("Good. This file appears to be the %s version.\n",
707 return true; /* plan a will work */
710 /* Keep (virtually) nothing in memory. */
713 plan_b(const char *filename)
716 size_t i = 0, j, len, maxlen = 1;
717 char *lbuf = NULL, *p;
718 bool found_revision = (revision == NULL);
720 using_plan_a = false;
721 if ((ifp = fopen(filename, "r")) == NULL)
722 pfatal("can't open file %s", filename);
724 if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
725 pfatal("can't open file %s", TMPINNAME);
726 while ((p = fgetln(ifp, &len)) != NULL) {
727 if (p[len - 1] == '\n')
730 /* EOF without EOL, copy and add the NUL */
731 if ((lbuf = malloc(len + 1)) == NULL)
732 fatal("out of memory\n");
733 memcpy(lbuf, p, len);
737 last_line_missing_eol = true;
740 if (revision != NULL && !found_revision && rev_in_string(p))
741 found_revision = true;
743 maxlen = len; /* find longest line */
747 pfatal("can't read file %s", filename);
749 if (revision != NULL) {
750 if (!found_revision) {
752 if (verbosity == VERBOSE)
753 say("Warning: this file doesn't appear "
754 "to be the %s version--patching anyway.\n",
757 fatal("this file doesn't appear to be the "
758 "%s version--aborting.\n",
761 ask("This file doesn't appear to be the %s "
762 "version--patch anyway? [n] ",
767 } else if (verbosity == VERBOSE)
768 say("Good. This file appears to be the %s version.\n",
771 fseek(ifp, 0L, SEEK_SET); /* rewind file */
773 tibuflen = maxlen > BUFFERSIZE ? maxlen : BUFFERSIZE;
774 lines_per_buf = tibuflen / maxlen;
775 tibuf[0] = malloc(tibuflen + 1);
776 if (tibuf[0] == NULL)
777 fatal("out of memory\n");
778 tibuf[1] = malloc(tibuflen + 1);
779 if (tibuf[1] == NULL)
780 fatal("out of memory\n");
782 p = tibuf[0] + maxlen * (i % lines_per_buf);
783 if (i % lines_per_buf == 0) /* new block */
784 if (write(tifd, tibuf[0], tibuflen) !=
786 pfatal("can't write temp file");
787 if (fgets(p, maxlen + 1, ifp) == NULL) {
789 if (i % lines_per_buf != 0)
790 if (write(tifd, tibuf[0], tibuflen) !=
792 pfatal("can't write temp file");
796 /* These are '\n' terminated strings, so no need to add a NUL */
797 if (j == 0 || p[j - 1] != '\n')
802 if ((tifd = open(TMPINNAME, O_RDONLY)) < 0)
803 pfatal("can't reopen file %s", TMPINNAME);
807 * Fetch a line from the input file, \n terminated, not necessarily \0.
810 ifetch(LINENUM line, int whichbuf)
812 if (line < 1 || line > input_lines) {
813 if (warn_on_invalid_line) {
814 say("No such line %ld in input file, ignoring\n", line);
815 warn_on_invalid_line = false;
822 LINENUM offline = line % lines_per_buf;
823 LINENUM baseline = line - offline;
825 if (tiline[0] == baseline)
827 else if (tiline[1] == baseline)
830 tiline[whichbuf] = baseline;
832 if (lseek(tifd, (off_t) (baseline / lines_per_buf *
833 tibuflen), SEEK_SET) < 0)
834 pfatal("cannot seek in the temporary input file");
836 if (read(tifd, tibuf[whichbuf], tibuflen) !=
838 pfatal("error reading tmp file %s", TMPINNAME);
840 return tibuf[whichbuf] + (tireclen * offline);
845 * True if the string argument contains the revision number we want.
848 rev_in_string(const char *string)
853 if (revision == NULL)
855 patlen = strlen(revision);
856 if (strnEQ(string, revision, patlen) && isspace((unsigned char)string[patlen]))
858 for (s = string; *s; s++) {
859 if (isspace((unsigned char)*s) && strnEQ(s + 1, revision, patlen) &&
860 isspace((unsigned char)s[patlen + 1])) {
868 [FILE:83:files/inp.h]
870 void scan_input(const char *);
871 char *ifetch(LINENUM, int);
874 [FILE:917:files/linux_support.c]
875 #ifndef LINUX_SUPPORT_C
876 #define LINUX_SUPPORT_C
880 #include "linux_support.h"
883 bsd_vasprintf(char **strp, const char *fmt, va_list args)
888 va_copy(args_copy, args);
889 needed = vsnprintf(NULL, 0, fmt, args_copy);
895 *strp = malloc(needed + 1);
898 status = vsnprintf(*strp, needed + 1, fmt, args);
909 bsd_asprintf(char **strp, const char *fmt, ...)
915 status = bsd_vasprintf(strp, fmt, args);
919 #endif /* __Linux__ */
921 #endif /* LINUX_SUPPORT_C */
924 [FILE:284:files/linux_support.h]
925 #ifndef LINUX_SUPPORT_H
926 #define LINUX_SUPPORT_H
929 #include <bsd/stdio.h>
930 #include <bsd/stdlib.h>
931 #include <bsd/unistd.h>
932 #include <bsd/string.h>
934 #define asprintf bsd_asprintf
936 int bsd_asprintf(char **strp, const char *fmt, ...);
940 #endif /* LINUX_SUPPORT_H */
943 [FILE:715:files/mkpath.c]
944 #include <sys/types.h>
945 #include <sys/stat.h>
952 /* Code taken directly from mkdir(1).
954 * mkpath -- create directories.
967 slash += strspn(slash, "/");
968 slash += strcspn(slash, "/");
970 done = (*slash == '\0');
973 if (stat(path, &sb)) {
974 if (errno != ENOENT || (mkdir(path, 0777) &&
979 } else if (!S_ISDIR(sb.st_mode)) {
980 warnx("%s: %s", path, strerror(ENOTDIR));
992 [FILE:19111:files/patch.1]
993 .Dd September 6, 2017
998 .Nd apply a diff file to an original
1002 .Op Fl bCcEeflNnRstuv
1003 .Op Fl B Ar backup-prefix
1005 .Op Fl d Ar directory
1006 .Op Fl F Ar max-fuzz
1007 .Op Fl i Ar patchfile
1008 .Op Fl o Ar out-file
1009 .Op Fl p Ar strip-count
1010 .Op Fl r Ar rej-name
1011 .Op Fl V Cm t | nil | never | none
1013 .Op Fl z Ar backup-ext
1016 .Op Ar origfile Op Ar patchfile
1019 .Pf \*(Lt Ar patchfile
1022 will take a patch file containing any of the four forms of difference
1023 listing produced by the
1025 program and apply those differences to an original file,
1026 producing a patched version.
1029 is omitted, or is a hyphen, the patch will be read from the standard input.
1032 will attempt to determine the type of the diff listing, unless overruled by a
1039 Context diffs (old-style, new-style, and unified) and
1040 normal diffs are applied directly by the
1042 program itself, whereas ed diffs are simply fed to the
1048 contains more than one patch,
1050 will try to apply each of them as if they came from separate patch files.
1051 This means, among other things, that it is assumed that the name of the file
1052 to patch must be determined for each diff listing, and that the garbage before
1053 each diff listing will be examined for interesting things such as file names
1054 and revision level (see the section on
1055 .Sx Filename Determination
1058 The options are as follows:
1061 .Fl B Ar backup-prefix ,
1062 .Fl Fl prefix Ar backup-prefix
1064 Causes the next argument to be interpreted as a prefix to the backup file
1066 If this argument is specified, any argument to
1069 .It Fl b , Fl Fl backup
1070 Save a backup copy of the file before it is modified.
1071 By default the original file is saved with a backup extension of
1073 unless the file already has a numbered backup, in which case a numbered
1075 This is equivalent to specifying
1076 .Qo Fl V Cm existing Qc .
1077 This option is currently the default, unless
1080 .It Fl C , Fl Fl check , Fl Fl dry-run
1081 Checks that the patch would apply cleanly, but does not modify anything.
1082 .It Fl c , Fl Fl context
1085 to interpret the patch file as a context diff.
1088 .Fl Fl ifdef Ar symbol
1094 construct to mark changes.
1095 The argument following will be used as the differentiating symbol.
1096 Note that, unlike the C compiler, there must be a space between the
1100 .Fl d Ar directory ,
1101 .Fl Fl directory Ar directory
1105 to interpret the next argument as a directory,
1106 and change the working directory to it before doing anything else.
1107 .It Fl E , Fl Fl remove-empty-files
1110 to remove output files that are empty after the patches have been applied.
1111 This option is useful when applying patches that create or remove files.
1115 to interpret the patch file as an
1120 .Fl Fl fuzz Ar max-fuzz
1122 Sets the maximum fuzz factor.
1123 This option only applies to context diffs, and causes
1125 to ignore up to that many lines in looking for places to install a hunk.
1126 Note that a larger fuzz factor increases the odds of a faulty patch.
1127 The default fuzz factor is 2, and it may not be set to more than
1128 the number of lines of context in the context diff, ordinarily 3.
1129 .It Fl f , Fl Fl force
1132 to assume that the user knows exactly what he or she is doing, and to not
1134 It assumes the following:
1135 skip patches for which a file to patch cannot be found;
1136 patch files even though they have the wrong version for the
1139 and assume that patches are not reversed even if they look like they are.
1140 This option does not suppress commentary; use
1144 .Fl i Ar patchfile ,
1145 .Fl Fl input Ar patchfile
1147 Causes the next argument to be interpreted as the input file name
1148 (i.e., a patchfile).
1149 This option may be specified multiple times.
1150 .It Fl l , Fl Fl ignore-whitespace
1151 Causes the pattern matching to be done loosely, in case the tabs and
1152 spaces have been munged in your input file.
1153 Any sequence of whitespace in the pattern line will match any sequence
1155 Normal characters must still match exactly.
1156 Each line of the context must still match a line in the input file.
1157 .It Fl N , Fl Fl forward
1160 to ignore patches that it thinks are reversed or already applied.
1163 .It Fl n , Fl Fl normal
1166 to interpret the patch file as a normal diff.
1169 .Fl Fl output Ar out-file
1171 Causes the next argument to be interpreted as the output file name.
1173 .Fl p Ar strip-count ,
1174 .Fl Fl strip Ar strip-count
1176 Sets the pathname strip count,
1177 which controls how pathnames found in the patch file are treated,
1178 in case you keep your files in a different directory than the person who sent
1180 The strip count specifies how many slashes are to be stripped from
1181 the front of the pathname.
1182 (Any intervening directory names also go away.)
1183 For example, supposing the file name in the patch file was
1184 .Pa /u/howard/src/blurfl/blurfl.c :
1188 gives the entire pathname unmodified.
1193 .D1 Pa u/howard/src/blurfl/blurfl.c
1195 without the leading slash.
1200 .D1 Pa blurfl/blurfl.c
1204 at all just gives you
1206 unless all of the directories in the leading path
1207 .Pq Pa u/howard/src/blurfl
1208 exist and that path is relative,
1209 in which case you get the entire pathname unmodified.
1210 Whatever you end up with is looked for either in the current directory,
1211 or the directory specified by the
1214 .It Fl R , Fl Fl reverse
1217 that this patch was created with the old and new files swapped.
1218 (Yes, I am afraid that does happen occasionally, human nature being what it
1221 will attempt to swap each hunk around before applying it.
1222 Rejects will come out in the swapped format.
1225 option will not work with ed diff scripts because there is too little
1226 information to reconstruct the reverse operation.
1228 If the first hunk of a patch fails,
1230 will reverse the hunk to see if it can be applied that way.
1231 If it can, you will be asked if you want to have the
1234 If it cannot, the patch will continue to be applied normally.
1235 (Note: this method cannot detect a reversed patch if it is a normal diff
1236 and if the first command is an append (i.e., it should have been a delete)
1237 since appends always succeed, due to the fact that a null context will match
1239 Luckily, most patches add or change lines rather than delete them, so most
1240 reversed normal diffs will begin with a delete, which will fail, triggering
1244 .Fl Fl reject-file Ar rej-name
1246 Causes the next argument to be interpreted as the reject file name.
1248 .Fl s , Fl Fl quiet ,
1253 do its work silently, unless an error occurs.
1254 .It Fl t , Fl Fl batch
1257 in that it suppresses questions, but makes some different assumptions:
1258 skip patches for which a file to patch cannot be found (the same as
1260 skip patches for which the file has the wrong version for the
1263 and assume that patches are reversed if they look like they are.
1264 .It Fl u , Fl Fl unified
1267 to interpret the patch file as a unified context diff (a unidiff).
1269 .Fl V Cm t | nil | never | none ,
1270 .Fl Fl version-control Cm t | nil | never | none
1272 Causes the next argument to be interpreted as a method for creating
1274 The type of backups made can also be given in the
1275 .Ev PATCH_VERSION_CONTROL
1278 environment variables, which are overridden by this option.
1281 option overrides this option, causing the prefix to always be used for
1282 making backup file names.
1284 .Ev PATCH_VERSION_CONTROL
1287 environment variables and the argument to the
1289 option are like the GNU Emacs
1291 variable; they also recognize synonyms that are more descriptive.
1292 The valid values are (unique abbreviations are accepted):
1293 .Bl -tag -width Ds -offset indent
1295 Always make numbered backups.
1296 .It Cm nil , existing
1297 Make numbered backups of files that already have them,
1298 simple backups of the others.
1299 .It Cm never , simple
1300 Always make simple backups.
1302 Do not make backups.
1304 .It Fl v , Fl Fl version
1307 to print out its revision header and patch level.
1310 .Fl Fl debug Ar number
1312 Sets internal debugging flags, and is of interest only to
1316 .Fl z Ar backup-ext ,
1317 .Fl Fl suffix Ar backup-ext
1319 Causes the next argument to be interpreted as the backup extension, to be
1323 Provides extra information during processing.
1327 conformance, specifically:
1330 Backup files are not created unless the
1332 option is specified.
1334 If unspecified, the file name used is the first of the old, new and
1335 index files that exists.
1338 .Ss Patch Application
1340 will try to skip any leading garbage, apply the diff,
1341 and then skip any trailing garbage.
1342 Thus you could feed an article or message containing a
1346 If the entire diff is indented by a consistent amount,
1347 this will be taken into account.
1349 With context diffs, and to a lesser extent with normal diffs,
1351 can detect when the line numbers mentioned in the patch are incorrect,
1352 and will attempt to find the correct place to apply each hunk of the patch.
1353 As a first guess, it takes the line number mentioned for the hunk, plus or
1354 minus any offset used in applying the previous hunk.
1355 If that is not the correct place,
1357 will scan both forwards and backwards for a set of lines matching the context
1361 looks for a place where all lines of the context match.
1362 If no such place is found, and it is a context diff, and the maximum fuzz factor
1363 is set to 1 or more, then another scan takes place ignoring the first and last
1365 If that fails, and the maximum fuzz factor is set to 2 or more,
1366 the first two and last two lines of context are ignored,
1367 and another scan is made.
1368 .Pq The default maximum fuzz factor is 2.
1372 cannot find a place to install that hunk of the patch, it will put the hunk
1373 out to a reject file, which normally is the name of the output file plus
1375 (Note that the rejected hunk will come out in context diff form whether the
1376 input patch was a context diff or a normal diff.
1377 If the input was a normal diff, many of the contexts will simply be null.)
1378 The line numbers on the hunks in the reject file may be different than
1379 in the patch file: they reflect the approximate location patch thinks the
1380 failed hunks belong in the new file rather than the old one.
1382 As each hunk is completed, you will be told whether the hunk succeeded or
1383 failed, and which line (in the new file)
1385 thought the hunk should go on.
1386 If this is different from the line number specified in the diff,
1387 you will be told the offset.
1388 A single large offset MAY be an indication that a hunk was installed in the
1390 You will also be told if a fuzz factor was used to make the match, in which
1391 case you should also be slightly suspicious.
1392 .Ss Filename Determination
1393 If no original file is specified on the command line,
1395 will try to figure out from the leading garbage what the name of the file
1397 When checking a prospective file name, pathname components are stripped
1400 option and the file's existence and writability are checked relative
1401 to the current working directory (or the directory specified by the
1405 If the diff is a context or unified diff,
1407 is able to determine the old and new file names from the diff header.
1408 For context diffs, the
1410 file is specified in the line beginning with
1414 file is specified in the line beginning with
1416 For a unified diff, the
1418 file is specified in the line beginning with
1422 file is specified in the line beginning with
1426 line in the leading garbage (regardless of the diff type),
1428 will use the file name from that line as the
1433 will choose the file name by performing the following steps, with the first
1439 is operating in strict
1441 mode, the first of the
1446 file names that exist is used.
1449 will examine either the
1453 file names or, for a non-context diff, the
1455 file name, and choose the file name with the fewest path components,
1456 the shortest basename, and the shortest total file name length (in that order).
1458 If no suitable file was found to patch, the patch file is a context or
1459 unified diff, and the old file was zero length, the new file name is
1462 If the file name still cannot be determined,
1464 will prompt the user for the file name to use.
1467 Additionally, if the leading garbage contains a
1471 will take the first word from the prerequisites line (normally a version
1472 number) and check the input file to see if that word can be found.
1475 will ask for confirmation before proceeding.
1477 The upshot of all this is that you should be able to say, while in a news
1478 interface, the following:
1480 .Dl | patch -d /usr/src/local/blurfl
1482 and patch a file in the blurfl directory directly from the article containing
1485 By default, the patched version is put in place of the original, with
1486 the original file backed up to the same name with the extension
1488 or as specified by the
1494 The extension used for making backup files may also be specified in the
1495 .Ev SIMPLE_BACKUP_SUFFIX
1496 environment variable, which is overridden by the options above.
1498 If the backup file is a symbolic or hard link to the original file,
1500 creates a new backup file name by changing the first lowercase letter
1501 in the last component of the file's name into uppercase.
1502 If there are no more lowercase letters in the name,
1503 it removes the first character from the name.
1504 It repeats this process until it comes up with a
1505 backup file that does not already exist or is not linked to the original file.
1507 You may also specify where you want the output to go with the
1509 option; if that file already exists, it is backed up first.
1510 .Ss Notes For Patch Senders
1511 There are several things you should bear in mind if you are going to
1512 be sending out patches:
1514 First, you can save people a lot of grief by keeping a
1516 file which is patched to increment the patch level as the first diff in the
1517 patch file you send out.
1520 line in with the patch, it will not let them apply
1521 patches out of order without some warning.
1523 Second, make sure you have specified the file names right, either in a
1524 context diff header, or with an
1527 If you are patching something in a subdirectory, be sure to tell the patch
1532 Third, you can create a file by sending out a diff that compares a
1533 null file to the file you want to create.
1534 This will only work if the file you want to create does not exist already in
1535 the target directory.
1537 Fourth, take care not to send out reversed patches, since it makes people wonder
1538 whether they already applied the patch.
1540 Fifth, while you may be able to get away with putting 582 diff listings into
1541 one file, it is probably wiser to group related patches into separate files in
1542 case something goes haywire.
1544 .Bl -tag -width "PATCH_VERSION_CONTROL" -compact
1545 .It Ev POSIXLY_CORRECT
1550 option has been specified.
1551 .It Ev SIMPLE_BACKUP_SUFFIX
1552 Extension to use for backup file names instead of
1555 Directory to put temporary files in; default is
1557 .It Ev PATCH_VERSION_CONTROL
1558 Selects when numbered backup files are made.
1559 .It Ev VERSION_CONTROL
1561 .Ev PATCH_VERSION_CONTROL .
1564 .Bl -tag -width "$TMPDIR/patch*" -compact
1565 .It Pa $TMPDIR/patch*
1569 used to read input when
1576 utility exits with one of the following values:
1578 .Bl -tag -width Ds -offset indent -compact
1580 Successful completion.
1582 One or more lines were written to a reject file.
1587 When applying a set of patches in a loop it behooves you to check this
1588 exit status so you do not apply a later patch to a partially patched file.
1590 Too many to list here, but generally indicative that
1592 couldn't parse your patch file.
1596 indicates that there is unprocessed text in the patch file and that
1598 is attempting to intuit whether there is a patch in that text and, if so,
1599 what kind of patch it is.
1605 utility is compliant with the
1608 except as detailed above for the
1616 are extensions to that specification.
1619 with many other contributors.
1622 cannot tell if the line numbers are off in an ed script, and can only detect
1623 bad line numbers in a normal diff when it finds a
1628 A context diff using fuzz factor 3 may have the same problem.
1629 Until a suitable interactive interface is added, you should probably do
1630 a context diff in these cases to see if the changes made sense.
1631 Of course, compiling without errors is a pretty good indication that the patch
1632 worked, but not always.
1635 usually produces the correct results, even when it has to do a lot of
1637 However, the results are guaranteed to be correct only when the patch is
1638 applied to exactly the same version of the file that the patch was
1641 Could be smarter about partial matches, excessively deviant offsets and
1642 swapped code, but that would take an extra pass.
1646 will fail if you try to check several patches in succession that build on
1650 code would have to be restructured to keep temporary files around so that it
1651 can handle this situation.
1653 If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
1656 is incapable of patching both versions, and, if it works at all, will likely
1657 patch the wrong one, and tell you that it succeeded to boot.
1659 If you apply a patch you have already applied,
1661 will think it is a reversed patch, and offer to un-apply the patch.
1662 This could be construed as a feature.
1665 [FILE:26069:files/patch.c]
1666 #include <sys/types.h>
1667 #include <sys/stat.h>
1681 #include "backupfile.h"
1682 #include "pathnames.h"
1685 #define NAME_MAX 255
1688 mode_t filemode = 0644;
1690 char *buf; /* general purpose buffer */
1691 size_t buf_size; /* size of the general purpose buffer */
1693 bool using_plan_a = true; /* try to keep everything in memory */
1694 bool out_of_mem = false; /* ran out of memory in plan a */
1698 char *filearg[MAXFILEC];
1699 bool ok_to_create_file = false;
1700 char *outname = NULL;
1701 char *origprae = NULL;
1706 bool toutkeep = false;
1707 bool trejkeep = false;
1708 bool warn_on_invalid_line;
1709 bool last_line_missing_eol;
1717 bool reverse = false;
1718 bool noreverse = false;
1719 bool skip_rest_of_patch = false;
1720 int strippath = 957;
1721 bool canonicalize = false;
1722 bool check_only = false;
1724 char *revision = NULL; /* prerequisite revision, if any */
1725 LINENUM input_lines = 0; /* how long is input file in lines */
1726 int posix = 0; /* strict POSIX mode? */
1727 enum vlevel verbosity = NORMAL_LEVEL;
1729 static void reinitialize_almost_everything(void);
1730 static void get_some_switches(void);
1731 static LINENUM locate_hunk(LINENUM);
1732 static void abort_context_hunk(void);
1733 static void rej_line(int, LINENUM);
1734 static void abort_hunk(void);
1735 static void apply_hunk(LINENUM);
1736 static void init_output(const char *);
1737 static void init_reject(const char *);
1738 static void copy_till(LINENUM, bool);
1739 static bool spew_output(void);
1740 static void dump_line(LINENUM, bool);
1741 static bool patch_match(LINENUM, LINENUM, LINENUM);
1742 static bool similar(const char *, const char *, int);
1743 static void usage(void);
1745 /* true if -E was specified on command line. */
1746 static bool remove_empty_files = false;
1748 /* true if -R was specified on command line. */
1749 static bool reverse_flag_specified = false;
1751 static bool Vflag = false;
1753 /* buffer holding the name of the rejected patch file. */
1754 static char rejname[NAME_MAX + 1];
1756 /* how many input lines have been irretractibly output */
1757 static LINENUM last_frozen_line = 0;
1759 static int Argc; /* guess */
1761 static int Argc_last; /* for restarting plan_b */
1762 static char **Argv_last;
1764 static FILE *ofp = NULL; /* output file pointer */
1765 static FILE *rejfp = NULL; /* reject file pointer */
1767 static int filec = 0; /* how many file arguments? */
1768 static LINENUM last_offset = 0;
1769 static LINENUM maxfuzz = 2;
1771 /* patch using ifdef, ifndef, etc. */
1772 static bool do_defines = false;
1774 static char if_defined[128];
1776 static char not_defined[128];
1778 static const char else_defined[] = "#else\n";
1780 static char end_defined[128];
1783 /* Apply a set of diffs as appropriate. */
1786 main(int argc, char *argv[])
1788 int error = 0, hunk, failed, i, fd;
1789 bool patch_seen, reverse_seen;
1790 LINENUM where = 0, newwhere, fuzz, mymaxfuzz;
1794 setvbuf(stdout, NULL, _IOLBF, 0);
1795 setvbuf(stderr, NULL, _IOLBF, 0);
1796 for (i = 0; i < MAXFILEC; i++)
1799 buf_size = INITLINELEN;
1800 buf = malloc((unsigned)(buf_size));
1802 fatal("out of memory\n");
1804 /* Cons up the names of the temporary files. */
1805 if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
1807 for (i = strlen(tmpdir) - 1; i > 0 && tmpdir[i] == '/'; i--)
1810 if (asprintf(&TMPOUTNAME, "%.*s/patchoXXXXXXXXXX", i, tmpdir) == -1)
1811 fatal("cannot allocate memory");
1812 if ((fd = mkstemp(TMPOUTNAME)) < 0)
1813 pfatal("can't create %s", TMPOUTNAME);
1816 if (asprintf(&TMPINNAME, "%.*s/patchiXXXXXXXXXX", i, tmpdir) == -1)
1817 fatal("cannot allocate memory");
1818 if ((fd = mkstemp(TMPINNAME)) < 0)
1819 pfatal("can't create %s", TMPINNAME);
1822 if (asprintf(&TMPREJNAME, "%.*s/patchrXXXXXXXXXX", i, tmpdir) == -1)
1823 fatal("cannot allocate memory");
1824 if ((fd = mkstemp(TMPREJNAME)) < 0)
1825 pfatal("can't create %s", TMPREJNAME);
1828 if (asprintf(&TMPPATNAME, "%.*s/patchpXXXXXXXXXX", i, tmpdir) == -1)
1829 fatal("cannot allocate memory");
1830 if ((fd = mkstemp(TMPPATNAME)) < 0)
1831 pfatal("can't create %s", TMPPATNAME);
1834 v = getenv("SIMPLE_BACKUP_SUFFIX");
1836 simple_backup_suffix = v;
1838 simple_backup_suffix = ORIGEXT;
1840 /* parse switches */
1843 get_some_switches();
1846 if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL)
1847 v = getenv("VERSION_CONTROL");
1848 if (v != NULL || !posix)
1849 backup_type = get_version(v); /* OK to pass NULL. */
1852 /* make sure we clean up /tmp in case of disaster */
1856 for (open_patch_file(filearg[1]); there_is_another_patch();
1857 reinitialize_almost_everything()) {
1858 /* for each patch in patch file */
1862 warn_on_invalid_line = true;
1864 if (outname == NULL)
1865 outname = xstrdup(filearg[0]);
1867 /* for ed script just up and do it and exit */
1868 if (diff_type == ED_DIFF) {
1872 /* initialize the patched file */
1873 if (!skip_rest_of_patch)
1874 init_output(TMPOUTNAME);
1876 /* initialize reject file */
1877 init_reject(TMPREJNAME);
1879 /* find out where all the lines are */
1880 if (!skip_rest_of_patch)
1881 scan_input(filearg[0]);
1884 * from here on, open no standard i/o files, because
1885 * malloc might misfire and we can't catch it easily
1888 /* apply each hunk of patch */
1891 reverse_seen = false;
1893 while (another_hunk()) {
1896 mymaxfuzz = pch_context();
1897 if (maxfuzz < mymaxfuzz)
1898 mymaxfuzz = maxfuzz;
1899 if (!skip_rest_of_patch) {
1901 where = locate_hunk(fuzz);
1902 if (hunk == 1 && where == 0 && !force && !reverse_seen) {
1903 /* dwim for reversed patch? */
1906 say("Not enough memory to try swapped hunk! Assuming unswapped.\n");
1911 where = locate_hunk(fuzz);
1913 /* didn't find it swapped */
1915 /* put it back to normal */
1916 fatal("lost hunk on alloc error!\n");
1918 } else if (noreverse) {
1920 /* put it back to normal */
1921 fatal("lost hunk on alloc error!\n");
1923 say("Ignoring previously applied (or reversed) patch.\n");
1924 skip_rest_of_patch = true;
1926 if (verbosity != SILENT)
1927 say("%seversed (or previously applied) patch detected! %s -R.",
1928 reverse ? "R" : "Unr",
1929 reverse ? "Assuming" : "Ignoring");
1931 ask("%seversed (or previously applied) patch detected! %s -R? [y] ",
1932 reverse ? "R" : "Unr",
1933 reverse ? "Assume" : "Ignore");
1935 ask("Apply anyway? [n] ");
1937 skip_rest_of_patch = true;
1939 reverse_seen = true;
1943 /* put it back to normal */
1944 fatal("lost hunk on alloc error!\n");
1948 } while (!skip_rest_of_patch && where == 0 &&
1949 ++fuzz <= mymaxfuzz);
1951 if (skip_rest_of_patch) { /* just got decided */
1952 if (ferror(ofp) || fclose(ofp)) {
1953 say("Error writing %s\n",
1960 newwhere = pch_newfirst() + last_offset;
1961 if (skip_rest_of_patch) {
1964 if (verbosity != SILENT)
1965 say("Hunk #%d ignored at %ld.\n",
1967 } else if (where == 0) {
1970 if (verbosity != SILENT)
1971 say("Hunk #%d failed at %ld.\n",
1975 if (verbosity == VERBOSE
1976 || (verbosity != SILENT && (fuzz != 0 || last_offset)))
1978 say("Hunk #%d succeeded at %ld",
1981 say(" with fuzz %ld", fuzz);
1983 say(" (offset %ld line%s)",
1985 last_offset == 1L ? "" : "s");
1991 if (out_of_mem && using_plan_a) {
1994 say("\n\nRan out of memory using Plan A--trying again...\n\n");
2004 fatal("Internal error: hunk should not be 0\n");
2006 /* finish spewing out the new file */
2007 if (!skip_rest_of_patch && !spew_output()) {
2008 say("Can't write %s\n", TMPOUTNAME);
2012 /* and put the output where desired */
2014 if (!skip_rest_of_patch) {
2015 struct stat statbuf;
2016 char *realout = outname;
2019 if (move_file(TMPOUTNAME, outname) < 0) {
2021 realout = TMPOUTNAME;
2022 chmod(TMPOUTNAME, filemode);
2024 chmod(outname, filemode);
2026 if (remove_empty_files &&
2027 stat(realout, &statbuf) == 0 &&
2028 statbuf.st_size == 0) {
2029 if (verbosity == VERBOSE)
2030 say("Removing %s (empty after patching).\n",
2036 if (ferror(rejfp) || fclose(rejfp)) {
2037 say("Error writing %s\n", rejname);
2043 if (*rejname == '\0') {
2044 if (strlcpy(rejname, outname,
2045 sizeof(rejname)) >= sizeof(rejname))
2046 fatal("filename %s is too long\n", outname);
2047 if (strlcat(rejname, REJEXT,
2048 sizeof(rejname)) >= sizeof(rejname))
2049 fatal("filename %s is too long\n", outname);
2052 say("%d out of %d hunks %s--saving rejects to %s\n",
2053 failed, hunk, skip_rest_of_patch ? "ignored" : "failed", rejname);
2055 say("%d out of %d hunks %s while patching %s\n",
2056 failed, hunk, skip_rest_of_patch ? "ignored" : "failed", filearg[0]);
2057 if (!check_only && move_file(TMPREJNAME, rejname) < 0)
2070 /* Prepare to find the next patch to do in the patch file. */
2073 reinitialize_almost_everything(void)
2079 last_frozen_line = 0;
2096 reverse = reverse_flag_specified;
2097 skip_rest_of_patch = false;
2099 get_some_switches();
2102 /* Process switches and filenames. */
2105 get_some_switches(void)
2107 const char *options = "b::B:cCd:D:eEfF:i:lnNo:p:r:RstuvV:x:z:";
2108 static struct option longopts[] = {
2109 {"backup", no_argument, 0, 'b'},
2110 {"batch", no_argument, 0, 't'},
2111 {"check", no_argument, 0, 'C'},
2112 {"context", no_argument, 0, 'c'},
2113 {"debug", required_argument, 0, 'x'},
2114 {"directory", required_argument, 0, 'd'},
2115 {"dry-run", no_argument, 0, 'C'},
2116 {"ed", no_argument, 0, 'e'},
2117 {"force", no_argument, 0, 'f'},
2118 {"forward", no_argument, 0, 'N'},
2119 {"fuzz", required_argument, 0, 'F'},
2120 {"ifdef", required_argument, 0, 'D'},
2121 {"input", required_argument, 0, 'i'},
2122 {"ignore-whitespace", no_argument, 0, 'l'},
2123 {"normal", no_argument, 0, 'n'},
2124 {"output", required_argument, 0, 'o'},
2125 {"prefix", required_argument, 0, 'B'},
2126 {"quiet", no_argument, 0, 's'},
2127 {"reject-file", required_argument, 0, 'r'},
2128 {"remove-empty-files", no_argument, 0, 'E'},
2129 {"reverse", no_argument, 0, 'R'},
2130 {"silent", no_argument, 0, 's'},
2131 {"strip", required_argument, 0, 'p'},
2132 {"suffix", required_argument, 0, 'z'},
2133 {"unified", no_argument, 0, 'u'},
2134 {"version", no_argument, 0, 'v'},
2135 {"version-control", required_argument, 0, 'V'},
2136 {"posix", no_argument, &posix, 1},
2137 {"verbose", no_argument, 0, 2},
2148 optreset = optind = 1;
2150 while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
2153 verbosity = VERBOSE;
2156 if (backup_type == none)
2157 backup_type = numbered_existing;
2160 if (verbosity != SILENT)
2161 say("Warning, the ``-b suffix'' option has been"
2162 " obsoleted by the -z option.\n");
2165 /* must directly follow 'b' case for backwards compat */
2166 simple_backup_suffix = xstrdup(optarg);
2169 origprae = xstrdup(optarg);
2172 diff_type = CONTEXT_DIFF;
2178 if (chdir(optarg) < 0)
2179 pfatal("can't cd to %s", optarg);
2183 if (!isalpha((unsigned char)*optarg) && *optarg != '_')
2184 fatal("argument to -D is not an identifier\n");
2185 snprintf(if_defined, sizeof if_defined,
2186 "#ifdef %s\n", optarg);
2187 snprintf(not_defined, sizeof not_defined,
2188 "#ifndef %s\n", optarg);
2189 snprintf(end_defined, sizeof end_defined,
2190 "#endif /* %s */\n", optarg);
2193 diff_type = ED_DIFF;
2196 remove_empty_files = true;
2202 maxfuzz = atoi(optarg);
2205 if (++filec == MAXFILEC)
2206 fatal("too many file arguments\n");
2207 filearg[filec] = xstrdup(optarg);
2210 canonicalize = true;
2213 diff_type = NORMAL_DIFF;
2219 outname = xstrdup(optarg);
2222 strippath = atoi(optarg);
2225 if (strlcpy(rejname, optarg,
2226 sizeof(rejname)) >= sizeof(rejname))
2227 fatal("argument for -r is too long\n");
2231 reverse_flag_specified = true;
2240 diff_type = UNI_DIFF;
2246 backup_type = get_version(optarg);
2251 debug = atoi(optarg);
2264 filearg[0] = xstrdup(*Argv++);
2267 if (++filec == MAXFILEC)
2268 fatal("too many file arguments\n");
2269 filearg[filec] = xstrdup(*Argv++);
2274 if (getenv("POSIXLY_CORRECT") != NULL)
2282 "usage: patch [-bCcEeflNnRstuv] [-B backup-prefix] [-D symbol] [-d directory]\n"
2283 " [-F max-fuzz] [-i patchfile] [-o out-file] [-p strip-count]\n"
2284 " [-r rej-name] [-V t | nil | never | none] [-x number]\n"
2285 " [-z backup-ext] [--posix] [origfile [patchfile]]\n"
2286 " patch <patchfile\n");
2287 my_exit(EXIT_FAILURE);
2291 * Attempt to find the right place to apply this hunk of patch.
2294 locate_hunk(LINENUM fuzz)
2296 LINENUM first_guess = pch_first() + last_offset;
2298 LINENUM pat_lines = pch_ptrn_lines();
2299 LINENUM max_pos_offset = input_lines - first_guess - pat_lines + 1;
2300 LINENUM max_neg_offset = first_guess - last_frozen_line - 1 + pch_context();
2302 if (pat_lines == 0) { /* null range matches always */
2303 if (verbosity == VERBOSE && fuzz == 0 && (diff_type == CONTEXT_DIFF
2304 || diff_type == NEW_CONTEXT_DIFF
2305 || diff_type == UNI_DIFF)) {
2306 say("Empty context always matches.\n");
2308 return (first_guess);
2310 if (max_neg_offset >= first_guess) /* do not try lines < 0 */
2311 max_neg_offset = first_guess - 1;
2312 if (first_guess <= input_lines && patch_match(first_guess, 0, fuzz))
2314 for (offset = 1; ; offset++) {
2315 bool check_after = (offset <= max_pos_offset);
2316 bool check_before = (offset <= max_neg_offset);
2318 if (check_after && patch_match(first_guess, offset, fuzz)) {
2321 say("Offset changing from %ld to %ld\n",
2322 last_offset, offset);
2324 last_offset = offset;
2325 return first_guess + offset;
2326 } else if (check_before && patch_match(first_guess, -offset, fuzz)) {
2329 say("Offset changing from %ld to %ld\n",
2330 last_offset, -offset);
2332 last_offset = -offset;
2333 return first_guess - offset;
2334 } else if (!check_before && !check_after)
2339 /* We did not find the pattern, dump out the hunk so they can handle it. */
2342 abort_context_hunk(void)
2345 const LINENUM pat_end = pch_end();
2347 * add in last_offset to guess the same as the previous successful
2350 const LINENUM oldfirst = pch_first() + last_offset;
2351 const LINENUM newfirst = pch_newfirst() + last_offset;
2352 const LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
2353 const LINENUM newlast = newfirst + pch_repl_lines() - 1;
2354 const char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : "");
2355 const char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----");
2357 fprintf(rejfp, "***************\n");
2358 for (i = 0; i <= pat_end; i++) {
2359 switch (pch_char(i)) {
2361 if (oldlast < oldfirst)
2362 fprintf(rejfp, "*** 0%s\n", stars);
2363 else if (oldlast == oldfirst)
2364 fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
2366 fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst,
2370 if (newlast < newfirst)
2371 fprintf(rejfp, "--- 0%s\n", minuses);
2372 else if (newlast == newfirst)
2373 fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
2375 fprintf(rejfp, "--- %ld,%ld%s\n", newfirst,
2379 fprintf(rejfp, "%s", pfetch(i));
2385 fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
2388 fatal("fatal internal error in abort_context_hunk\n");
2394 rej_line(int ch, LINENUM i)
2397 const char *line = pfetch(i);
2401 fprintf(rejfp, "%c%s", ch, line);
2402 if (len == 0 || line[len - 1] != '\n') {
2403 if (len >= USHRT_MAX)
2404 fprintf(rejfp, "\n\\ Line too long\n");
2406 fprintf(rejfp, "\n\\ No newline at end of line\n");
2413 LINENUM i, j, split;
2415 const LINENUM pat_end = pch_end();
2416 const LINENUM oldfirst = pch_first() + last_offset;
2417 const LINENUM newfirst = pch_newfirst() + last_offset;
2419 if (diff_type != UNI_DIFF) {
2420 abort_context_hunk();
2424 for (i = 0; i <= pat_end; i++) {
2425 if (pch_char(i) == '=') {
2431 fprintf(rejfp, "malformed hunk: no split found\n");
2436 fprintf(rejfp, "@@ -%ld,%ld +%ld,%ld @@\n",
2437 pch_ptrn_lines() ? oldfirst : 0,
2438 pch_ptrn_lines(), newfirst, pch_repl_lines());
2439 while (i < split || j <= pat_end) {
2440 ch1 = i < split ? pch_char(i) : -1;
2441 ch2 = j <= pat_end ? pch_char(j) : -1;
2445 } else if (ch1 == ' ' && ch2 == ' ') {
2449 } else if (ch1 == '!' && ch2 == '!') {
2450 while (i < split && ch1 == '!') {
2453 ch1 = i < split ? pch_char(i) : -1;
2455 while (j <= pat_end && ch2 == '!') {
2458 ch2 = j <= pat_end ? pch_char(j) : -1;
2460 } else if (ch1 == '*') {
2462 } else if (ch2 == '+' || ch2 == ' ') {
2466 fprintf(rejfp, "internal error on (%ld %ld %ld)\n",
2475 /* We found where to apply it (we hope), so do it. */
2478 apply_hunk(LINENUM where)
2481 const LINENUM lastline = pch_ptrn_lines();
2482 LINENUM new = lastline + 1;
2487 int def_state = OUTSIDE;
2488 const LINENUM pat_end = pch_end();
2491 while (pch_char(new) == '=' || pch_char(new) == '\n')
2494 while (old <= lastline) {
2495 if (pch_char(old) == '-') {
2496 copy_till(where + old - 1, false);
2498 if (def_state == OUTSIDE) {
2499 fputs(not_defined, ofp);
2500 def_state = IN_IFNDEF;
2501 } else if (def_state == IN_IFDEF) {
2502 fputs(else_defined, ofp);
2503 def_state = IN_ELSE;
2505 fputs(pfetch(old), ofp);
2509 } else if (new > pat_end) {
2511 } else if (pch_char(new) == '+') {
2512 copy_till(where + old - 1, false);
2514 if (def_state == IN_IFNDEF) {
2515 fputs(else_defined, ofp);
2516 def_state = IN_ELSE;
2517 } else if (def_state == OUTSIDE) {
2518 fputs(if_defined, ofp);
2519 def_state = IN_IFDEF;
2522 fputs(pfetch(new), ofp);
2524 } else if (pch_char(new) != pch_char(old)) {
2525 say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
2526 pch_hunk_beg() + old,
2527 pch_hunk_beg() + new);
2529 say("oldchar = '%c', newchar = '%c'\n",
2530 pch_char(old), pch_char(new));
2533 } else if (pch_char(new) == '!') {
2534 copy_till(where + old - 1, false);
2536 fputs(not_defined, ofp);
2537 def_state = IN_IFNDEF;
2539 while (pch_char(old) == '!') {
2541 fputs(pfetch(old), ofp);
2547 fputs(else_defined, ofp);
2548 def_state = IN_ELSE;
2550 while (pch_char(new) == '!') {
2551 fputs(pfetch(new), ofp);
2555 if (pch_char(new) != ' ')
2556 fatal("Internal error: expected ' '\n");
2559 if (do_defines && def_state != OUTSIDE) {
2560 fputs(end_defined, ofp);
2561 def_state = OUTSIDE;
2565 if (new <= pat_end && pch_char(new) == '+') {
2566 copy_till(where + old - 1, false);
2568 if (def_state == OUTSIDE) {
2569 fputs(if_defined, ofp);
2570 def_state = IN_IFDEF;
2571 } else if (def_state == IN_IFNDEF) {
2572 fputs(else_defined, ofp);
2573 def_state = IN_ELSE;
2576 while (new <= pat_end && pch_char(new) == '+') {
2577 fputs(pfetch(new), ofp);
2581 if (do_defines && def_state != OUTSIDE) {
2582 fputs(end_defined, ofp);
2587 * Open the new file.
2590 init_output(const char *name)
2592 ofp = fopen(name, "w");
2594 pfatal("can't create %s", name);
2598 * Open a file to put hunks we can't locate.
2601 init_reject(const char *name)
2603 rejfp = fopen(name, "w");
2605 pfatal("can't create %s", name);
2609 * Copy input file to output, up to wherever hunk is to be applied.
2610 * If endoffile is true, treat the last line specially since it may
2614 copy_till(LINENUM lastline, bool endoffile)
2616 if (last_frozen_line > lastline)
2617 fatal("misordered hunks! output would be garbled\n");
2618 while (last_frozen_line < lastline) {
2619 if (++last_frozen_line == lastline && endoffile)
2620 dump_line(last_frozen_line, !last_line_missing_eol);
2622 dump_line(last_frozen_line, true);
2627 * Finish copying the input file to the output file.
2636 say("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
2639 copy_till(input_lines, true); /* dump remainder of file */
2640 rv = ferror(ofp) == 0 && fclose(ofp) == 0;
2646 * Copy one line from input to output.
2649 dump_line(LINENUM line, bool write_newline)
2653 s = ifetch(line, 0);
2656 /* Note: string is not NUL terminated. */
2657 for (; *s != '\n'; s++)
2664 * Does the patch pattern match at line base+offset?
2667 patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
2669 LINENUM pline = 1 + fuzz;
2671 LINENUM pat_lines = pch_ptrn_lines() - fuzz;
2672 const char *ilineptr;
2673 const char *plineptr;
2674 unsigned short plinelen;
2676 for (iline = base + offset + fuzz; pline <= pat_lines; pline++, iline++) {
2677 ilineptr = ifetch(iline, offset >= 0);
2678 if (ilineptr == NULL)
2680 plineptr = pfetch(pline);
2681 plinelen = pch_line_len(pline);
2683 if (!similar(ilineptr, plineptr, plinelen))
2685 } else if (strnNE(ilineptr, plineptr, plinelen))
2687 if (iline == input_lines) {
2689 * We are looking at the last line of the file.
2690 * If the file has no eol, the patch line should
2691 * not have one either and vice-versa. Note that
2694 if (last_line_missing_eol) {
2695 if (plineptr[plinelen - 1] == '\n')
2698 if (plineptr[plinelen - 1] != '\n')
2707 * Do two lines match with canonicalized white space?
2710 similar(const char *a, const char *b, int len)
2713 if (isspace((unsigned char)*b)) { /* whitespace (or \n) to match? */
2714 if (!isspace((unsigned char)*a)) /* no corresponding whitespace? */
2716 while (len && isspace((unsigned char)*b) && *b != '\n')
2717 b++, len--; /* skip pattern whitespace */
2718 while (isspace((unsigned char)*a) && *a != '\n')
2719 a++; /* skip target whitespace */
2720 if (*a == '\n' || *b == '\n')
2721 return (*a == *b); /* should end in sync */
2722 } else if (*a++ != *b++) /* match non-whitespace chars */
2725 len--; /* probably not necessary */
2727 return true; /* actually, this is not reached */
2728 /* since there is always a \n */
2732 [FILE:49:files/pathnames.h]
2734 #define _PATH_RED "/bin/red"
2737 [FILE:39374:files/pch.c]
2738 #include <sys/types.h>
2739 #include <sys/stat.h>
2753 #include "pathnames.h"
2755 /* Patch (diff listing) abstract type. */
2757 static off_t p_filesize; /* size of the patch file */
2758 static LINENUM p_first; /* 1st line number */
2759 static LINENUM p_newfirst; /* 1st line number of replacement */
2760 static LINENUM p_ptrn_lines; /* # lines in pattern */
2761 static LINENUM p_repl_lines; /* # lines in replacement text */
2762 static LINENUM p_end = -1; /* last line in hunk */
2763 static LINENUM p_max; /* max allowed value of p_end */
2764 static LINENUM p_context = 3; /* # of context lines */
2765 static LINENUM p_input_line = 0; /* current line # from patch file */
2766 static char **p_line = NULL;/* the text of the hunk */
2767 static unsigned short *p_len = NULL; /* length of each line */
2768 static char *p_char = NULL; /* +, -, and ! */
2769 static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */
2770 static int p_indent; /* indent to patch */
2771 static off_t p_base; /* where to intuit this time */
2772 static LINENUM p_bline; /* line # of p_base */
2773 static off_t p_start; /* where intuit found a patch */
2774 static LINENUM p_sline; /* and the line number for it */
2775 static LINENUM p_hunk_beg; /* line number of current hunk */
2776 static LINENUM p_efake = -1; /* end of faked up lines--don't free */
2777 static LINENUM p_bfake = -1; /* beg of faked up lines */
2778 static FILE *pfp = NULL; /* patch file pointer */
2779 static char *bestguess = NULL; /* guess at correct filename */
2781 static void grow_hunkmax(void);
2782 static int intuit_diff_type(void);
2783 static void next_intuit_at(off_t, LINENUM);
2784 static void skip_to(off_t, LINENUM);
2785 static size_t pgets(bool _do_indent);
2786 static char *best_name(const struct file_name *, bool);
2787 static char *posix_name(const struct file_name *, bool);
2788 static size_t num_components(const char *);
2789 static LINENUM strtolinenum(char *, char **);
2792 * Prepare to look for the next patch in the patch file.
2801 p_end = (LINENUM) - 1;
2807 * Open the patch file at the beginning of time.
2810 open_patch_file(const char *filename)
2812 struct stat filestat;
2815 if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) {
2816 pfp = fopen(TMPPATNAME, "w");
2818 pfatal("can't create %s", TMPPATNAME);
2819 while ((nr = fread(buf, 1, buf_size, stdin)) > 0) {
2820 nw = fwrite(buf, 1, nr, pfp);
2822 pfatal("write error to %s", TMPPATNAME);
2824 if (ferror(pfp) || fclose(pfp))
2825 pfatal("can't write %s", TMPPATNAME);
2826 filename = TMPPATNAME;
2828 pfp = fopen(filename, "r");
2830 pfatal("patch file %s not found", filename);
2831 if (fstat(fileno(pfp), &filestat))
2832 pfatal("can't stat %s", filename);
2833 p_filesize = filestat.st_size;
2834 next_intuit_at(0, 1L); /* start at the beginning */
2839 * Make sure our dynamically realloced tables are malloced to begin with.
2845 p_line = malloc(hunkmax * sizeof(char *));
2847 p_len = malloc(hunkmax * sizeof(unsigned short));
2849 p_char = malloc(hunkmax * sizeof(char));
2853 * Enlarge the arrays containing the current hunk of patch.
2858 int new_hunkmax = hunkmax * 2;
2860 if (p_line == NULL || p_len == NULL || p_char == NULL)
2861 fatal("Internal memory allocation error\n");
2863 p_line = reallocf(p_line, new_hunkmax * sizeof(char *));
2864 p_len = reallocf(p_len, new_hunkmax * sizeof(unsigned short));
2865 p_char = reallocf(p_char, new_hunkmax * sizeof(char));
2867 if (p_line != NULL && p_len != NULL && p_char != NULL) {
2868 hunkmax = new_hunkmax;
2873 fatal("out of memory\n");
2874 out_of_mem = true; /* whatever is null will be allocated again */
2875 /* from within plan_a(), of all places */
2878 /* True if the remainder of the patch file contains a diff of some sort. */
2881 there_is_another_patch(void)
2883 bool exists = false;
2885 if (p_base != 0 && p_base >= p_filesize) {
2886 if (verbosity == VERBOSE)
2890 if (verbosity == VERBOSE)
2892 diff_type = intuit_diff_type();
2895 if (verbosity == VERBOSE)
2896 say(" Ignoring the trailing garbage.\ndone\n");
2898 say(" I can't seem to find a patch in there anywhere.\n");
2901 if (verbosity == VERBOSE)
2902 say(" %sooks like %s to me...\n",
2903 (p_base == 0 ? "L" : "The next patch l"),
2904 diff_type == UNI_DIFF ? "a unified diff" :
2905 diff_type == CONTEXT_DIFF ? "a context diff" :
2906 diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
2907 diff_type == NORMAL_DIFF ? "a normal diff" :
2909 if (p_indent && (verbosity == VERBOSE))
2910 say("(Patch is indented %d space%s.)\n", p_indent,
2911 p_indent == 1 ? "" : "s");
2912 skip_to(p_start, p_sline);
2913 while (filearg[0] == NULL) {
2914 if (force || batch) {
2915 say("No file to patch. Skipping...\n");
2916 filearg[0] = xstrdup(bestguess);
2917 skip_rest_of_patch = true;
2920 ask("File to patch: ");
2923 bestguess = xstrdup(buf);
2924 filearg[0] = fetchname(buf, &exists, 0);
2927 int def_skip = *bestguess == '\0';
2928 ask("No file found--skip this patch? [%c] ",
2929 def_skip ? 'y' : 'n');
2930 if (*buf == 'n' || (!def_skip && *buf != 'y'))
2932 if (verbosity != SILENT)
2933 say("Skipping patch...\n");
2935 filearg[0] = fetchname(bestguess, &exists, 0);
2936 skip_rest_of_patch = true;
2944 p4_fetchname(struct file_name *name, char *str)
2948 /* Skip leading whitespace. */
2949 while (isspace((unsigned char)*str))
2952 /* Remove the file revision number. */
2953 for (t = str, h = NULL; *t != '\0' && !isspace((unsigned char)*t); t++)
2959 name->path = fetchname(str, &name->exists, strippath);
2962 /* Determine what kind of diff is in the remaining part of the patch file. */
2965 intuit_diff_type(void)
2967 off_t this_line = 0, previous_line;
2968 off_t first_command_line = -1;
2969 LINENUM fcl_line = -1;
2970 bool last_line_was_command = false, this_is_a_command = false;
2971 bool stars_last_line = false, stars_this_line = false;
2974 struct file_name names[MAX_FILE];
2975 int piece_of_git = 0;
2977 memset(names, 0, sizeof(names));
2978 ok_to_create_file = false;
2979 fseeko(pfp, p_base, SEEK_SET);
2980 p_input_line = p_bline - 1;
2982 previous_line = this_line;
2983 last_line_was_command = this_is_a_command;
2984 stars_last_line = stars_this_line;
2985 this_line = ftello(pfp);
2988 if (pgets(false) == 0) {
2989 if (first_command_line >= 0) {
2990 /* nothing but deletes!? */
2991 p_start = first_command_line;
2996 p_start = this_line;
2997 p_sline = p_input_line;
3002 for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
3004 indent += 8 - (indent % 8);
3008 for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)
3010 this_is_a_command = (isdigit((unsigned char)*s) &&
3011 (*t == 'd' || *t == 'c' || *t == 'a'));
3012 if (first_command_line < 0 && this_is_a_command) {
3013 first_command_line = this_line;
3014 fcl_line = p_input_line;
3015 p_indent = indent; /* assume this for now */
3017 if (!stars_last_line && strnEQ(s, "*** ", 4))
3018 names[OLD_FILE].path = fetchname(s + 4,
3019 &names[OLD_FILE].exists, strippath);
3020 else if (strnEQ(s, "--- ", 4)) {
3022 if (piece_of_git && strippath == 957)
3024 names[NEW_FILE].path = fetchname(s + off,
3025 &names[NEW_FILE].exists, strippath);
3026 } else if (strnEQ(s, "+++ ", 4)) {
3027 /* pretend it is the old name */
3029 if (piece_of_git && strippath == 957)
3031 names[OLD_FILE].path = fetchname(s + off,
3032 &names[OLD_FILE].exists, strippath);
3033 } else if (strnEQ(s, "Index:", 6))
3034 names[INDEX_FILE].path = fetchname(s + 6,
3035 &names[INDEX_FILE].exists, strippath);
3036 else if (strnEQ(s, "Prereq:", 7)) {
3037 for (t = s + 7; isspace((unsigned char)*t); t++)
3039 revision = xstrdup(t);
3041 *t && !isspace((unsigned char)*t); t++)
3044 if (*revision == '\0') {
3048 } else if (strnEQ(s, "diff --git a/", 13)) {
3049 /* Git-style diffs. */
3051 } else if (strnEQ(s, "==== ", 5)) {
3052 /* Perforce-style diffs. */
3053 if ((t = strstr(s + 5, " - ")) != NULL)
3054 p4_fetchname(&names[NEW_FILE], t + 3);
3055 p4_fetchname(&names[OLD_FILE], s + 5);
3057 if ((!diff_type || diff_type == ED_DIFF) &&
3058 first_command_line >= 0 &&
3061 p_start = first_command_line;
3066 if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
3067 if (strnEQ(s + 4, "0,0", 3))
3068 ok_to_create_file = true;
3070 p_start = this_line;
3071 p_sline = p_input_line;
3075 stars_this_line = strnEQ(s, "********", 8);
3076 if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
3077 strnEQ(s, "*** ", 4)) {
3078 if (strtolinenum(s + 4, &s) == 0)
3079 ok_to_create_file = true;
3081 * If this is a new context diff the character just
3082 * at the end of the line is a '*'.
3084 while (*s && *s != '\n')
3087 p_start = previous_line;
3088 p_sline = p_input_line - 1;
3089 retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
3092 if ((!diff_type || diff_type == NORMAL_DIFF) &&
3093 last_line_was_command &&
3094 (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) {
3095 p_start = previous_line;
3096 p_sline = p_input_line - 1;
3098 retval = NORMAL_DIFF;
3103 if (retval == UNI_DIFF) {
3104 /* unswap old and new */
3105 struct file_name tmp = names[OLD_FILE];
3106 names[OLD_FILE] = names[NEW_FILE];
3107 names[NEW_FILE] = tmp;
3109 if (filearg[0] == NULL) {
3111 filearg[0] = posix_name(names, ok_to_create_file);
3113 /* Ignore the Index: name for context diffs, like GNU */
3114 if (names[OLD_FILE].path != NULL ||
3115 names[NEW_FILE].path != NULL) {
3116 free(names[INDEX_FILE].path);
3117 names[INDEX_FILE].path = NULL;
3119 filearg[0] = best_name(names, ok_to_create_file);
3125 if (filearg[0] != NULL)
3126 bestguess = xstrdup(filearg[0]);
3127 else if (!ok_to_create_file) {
3129 * We don't want to create a new file but we need a
3130 * filename to set bestguess. Avoid setting filearg[0]
3131 * so the file is not created automatically.
3134 bestguess = posix_name(names, true);
3136 bestguess = best_name(names, true);
3138 free(names[OLD_FILE].path);
3139 free(names[NEW_FILE].path);
3140 free(names[INDEX_FILE].path);
3145 * Remember where this patch ends so we know where to start up again.
3148 next_intuit_at(off_t file_pos, LINENUM file_line)
3151 p_bline = file_line;
3155 * Basically a verbose fseeko() to the actual diff listing.
3158 skip_to(off_t file_pos, LINENUM file_line)
3162 if (p_base > file_pos)
3163 fatal("Internal error: seek %lld>%lld\n",
3164 (long long)p_base, (long long)file_pos);
3165 if (verbosity == VERBOSE && p_base < file_pos) {
3166 fseeko(pfp, p_base, SEEK_SET);
3167 say("The text leading up to this was:\n--------------------------\n");
3168 while (ftello(pfp) < file_pos) {
3171 fatal("Unexpected end of file\n");
3174 say("--------------------------\n");
3176 fseeko(pfp, file_pos, SEEK_SET);
3177 p_input_line = file_line - 1;
3180 /* Make this a function for better debugging. */
3184 fatal("malformed patch at line %ld: %s", p_input_line, buf);
3185 /* about as informative as "Syntax error" in C */
3189 * True if the line has been discarded (i.e. it is a line saying
3190 * "\ No newline at end of file".)
3193 remove_special_line(void)
3201 } while (c != EOF && c != '\n');
3206 fseeko(pfp, -1, SEEK_CUR);
3212 * True if there is more of the current diff listing to process.
3217 off_t line_beginning; /* file pos of the current line */
3218 LINENUM repl_beginning; /* index of --- line */
3219 LINENUM fillcnt; /* #lines of missing ptrn or repl */
3220 LINENUM fillsrc; /* index of first line to copy */
3221 LINENUM filldst; /* index of first missing line */
3222 bool ptrn_spaces_eaten; /* ptrn was slightly malformed */
3223 bool repl_could_be_missing; /* no + or ! lines in this hunk */
3224 bool repl_missing; /* we are now backtracking */
3225 off_t repl_backtrack_position; /* file pos of first repl line */
3226 LINENUM repl_patch_line; /* input line number for same */
3227 LINENUM ptrn_copiable; /* # of copiable lines in ptrn */
3232 while (p_end >= 0) {
3233 if (p_end == p_efake)
3234 p_end = p_bfake; /* don't free twice */
3236 free(p_line[p_end]);
3241 p_max = hunkmax; /* gets reduced when --- found */
3242 if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
3243 line_beginning = ftello(pfp);
3248 ptrn_spaces_eaten = false;
3249 repl_could_be_missing = true;
3250 repl_missing = false;
3251 repl_backtrack_position = 0;
3252 repl_patch_line = 0;
3257 if (len == 0 || strnNE(buf, "********", 8)) {
3258 next_intuit_at(line_beginning, p_input_line);
3262 p_hunk_beg = p_input_line + 1;
3263 while (p_end < p_max) {
3264 line_beginning = ftello(pfp);
3268 if (p_max - p_end < 4) {
3269 /* assume blank lines got chopped */
3270 strlcpy(buf, " \n", buf_size);
3272 if (repl_beginning && repl_could_be_missing) {
3273 repl_missing = true;
3276 fatal("unexpected end of file in patch\n");
3280 if (p_end >= hunkmax)
3281 fatal("Internal error: hunk larger than hunk "
3283 p_char[p_end] = *buf;
3284 p_line[p_end] = NULL;
3287 if (strnEQ(buf, "********", 8)) {
3288 if (repl_beginning && repl_could_be_missing) {
3289 repl_missing = true;
3292 fatal("unexpected end of hunk "
3297 if (repl_beginning && repl_could_be_missing) {
3298 repl_missing = true;
3301 fatal("unexpected *** at line %ld: %s",
3305 p_line[p_end] = savestr(buf);
3311 *s && !isdigit((unsigned char)*s); s++)
3315 if (strnEQ(s, "0,0", 3))
3316 memmove(s, s + 2, strlen(s + 2) + 1);
3317 p_first = strtolinenum(s, &s);
3320 *s && !isdigit((unsigned char)*s); s++)
3324 p_ptrn_lines = strtolinenum(s, &s) - p_first + 1;
3325 if (p_ptrn_lines < 0)
3333 if (p_first >= LINENUM_MAX - p_ptrn_lines ||
3334 p_ptrn_lines >= LINENUM_MAX - 6)
3337 /* we need this much at least */
3338 p_max = p_ptrn_lines + 6;
3339 while (p_max >= hunkmax)
3344 if (buf[1] == '-') {
3345 if (repl_beginning ||
3346 (p_end != p_ptrn_lines + 1 +
3347 (p_char[p_end - 1] == '\n'))) {
3350 * `old' lines were omitted;
3351 * set up to fill them in
3352 * from 'new' context lines.
3354 p_end = p_ptrn_lines + 1;
3355 fillsrc = p_end + 1;
3357 fillcnt = p_ptrn_lines;
3359 if (repl_beginning) {
3360 if (repl_could_be_missing) {
3361 repl_missing = true;
3364 fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n",
3365 p_input_line, p_hunk_beg + repl_beginning);
3367 fatal("%s \"---\" at line %ld--check line numbers at line %ld\n",
3368 (p_end <= p_ptrn_lines
3371 p_input_line, p_hunk_beg);
3375 repl_beginning = p_end;
3376 repl_backtrack_position = ftello(pfp);
3377 repl_patch_line = p_input_line;
3378 p_line[p_end] = savestr(buf);
3383 p_char[p_end] = '=';
3384 for (s = buf; *s && !isdigit((unsigned char)*s); s++)
3388 p_newfirst = strtolinenum(s, &s);
3390 for (; *s && !isdigit((unsigned char)*s); s++)
3394 p_repl_lines = strtolinenum(s, &s) -
3396 if (p_repl_lines < 0)
3398 } else if (p_newfirst)
3404 if (p_newfirst >= LINENUM_MAX - p_repl_lines ||
3405 p_repl_lines >= LINENUM_MAX - p_end)
3407 p_max = p_repl_lines + p_end;
3408 if (p_max > MAXHUNKSIZE)
3409 fatal("hunk too large (%ld lines) at line %ld: %s",
3410 p_max, p_input_line, buf);
3411 while (p_max >= hunkmax)
3413 if (p_repl_lines != ptrn_copiable &&
3414 (p_context != 0 || p_repl_lines != 1))
3415 repl_could_be_missing = false;
3421 repl_could_be_missing = false;
3423 if (buf[1] == '\n' && canonicalize)
3424 strlcpy(buf + 1, " \n", buf_size - 1);
3425 if (!isspace((unsigned char)buf[1]) &&
3426 buf[1] != '>' && buf[1] != '<' &&
3427 repl_beginning && repl_could_be_missing) {
3428 repl_missing = true;
3432 if (context < p_context)
3433 p_context = context;
3436 p_line[p_end] = savestr(buf + 2);
3441 if (p_end == p_ptrn_lines) {
3442 if (remove_special_line()) {
3445 l = strlen(p_line[p_end]) - 1;
3446 (p_line[p_end])[l] = 0;
3451 case '\n': /* assume the 2 spaces got eaten */
3452 if (repl_beginning && repl_could_be_missing &&
3453 (!ptrn_spaces_eaten ||
3454 diff_type == NEW_CONTEXT_DIFF)) {
3455 repl_missing = true;
3458 p_line[p_end] = savestr(buf);
3463 if (p_end != p_ptrn_lines + 1) {
3464 ptrn_spaces_eaten |= (repl_beginning != 0);
3466 if (!repl_beginning)
3468 p_char[p_end] = ' ';
3472 if (!isspace((unsigned char)buf[1]) &&
3473 repl_beginning && repl_could_be_missing) {
3474 repl_missing = true;
3478 if (!repl_beginning)
3480 p_line[p_end] = savestr(buf + 2);
3487 if (repl_beginning && repl_could_be_missing) {
3488 repl_missing = true;
3493 /* set up p_len for strncmp() so we don't have to */
3494 /* assume null termination */
3496 p_len[p_end] = strlen(p_line[p_end]);
3502 if (p_end >= 0 && !repl_beginning)
3503 fatal("no --- found in patch at line %ld\n", pch_hunk_beg());
3507 /* reset state back to just after --- */
3508 p_input_line = repl_patch_line;
3509 for (p_end--; p_end > repl_beginning; p_end--)
3510 free(p_line[p_end]);
3511 fseeko(pfp, repl_backtrack_position, SEEK_SET);
3513 /* redundant 'new' context lines were omitted - set */
3514 /* up to fill them in from the old file context */
3515 if (!p_context && p_repl_lines == 1) {
3520 filldst = repl_beginning + 1;
3521 fillcnt = p_repl_lines;
3523 } else if (!p_context && fillcnt == 1) {
3524 /* the first hunk was a null hunk with no context */
3525 /* and we were expecting one line -- fix it up. */
3526 while (filldst < p_end) {
3527 p_line[filldst] = p_line[filldst + 1];
3528 p_char[filldst] = p_char[filldst + 1];
3529 p_len[filldst] = p_len[filldst + 1];
3533 repl_beginning--; /* this doesn't need to be fixed */
3536 p_first++; /* do append rather than insert */
3540 if (diff_type == CONTEXT_DIFF &&
3541 (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) {
3542 if (verbosity == VERBOSE)
3544 "(Fascinating--this is really a new-style context diff but without",
3545 "the telltale extra asterisks on the *** line that usually indicate",
3546 "the new style...)");
3547 diff_type = NEW_CONTEXT_DIFF;
3549 /* if there were omitted context lines, fill them in now */
3551 p_bfake = filldst; /* remember where not to free() */
3552 p_efake = filldst + fillcnt - 1;
3553 while (fillcnt-- > 0) {
3554 while (fillsrc <= p_end && p_char[fillsrc] != ' ')
3556 if (fillsrc > p_end)
3557 fatal("replacement text or line numbers mangled in hunk at line %ld\n",
3559 p_line[filldst] = p_line[fillsrc];
3560 p_char[filldst] = p_char[fillsrc];
3561 p_len[filldst] = p_len[fillsrc];
3565 while (fillsrc <= p_end && fillsrc != repl_beginning &&
3566 p_char[fillsrc] != ' ')
3570 printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
3571 fillsrc, filldst, repl_beginning, p_end + 1);
3573 if (fillsrc != p_end + 1 && fillsrc != repl_beginning)
3575 if (filldst != p_end + 1 && filldst != repl_beginning)
3578 if (p_line[p_end] != NULL) {
3579 if (remove_special_line()) {
3581 (p_line[p_end])[p_len[p_end]] = 0;
3584 } else if (diff_type == UNI_DIFF) {
3585 LINENUM fillold; /* index of old lines */
3586 LINENUM fillnew; /* index of new lines */
3589 line_beginning = ftello(pfp); /* file pos of the current line */
3592 if (len == 0 || strnNE(buf, "@@ -", 4)) {
3593 next_intuit_at(line_beginning, p_input_line);
3599 p_first = strtolinenum(s, &s);
3601 p_ptrn_lines = strtolinenum(s + 1, &s);
3606 if (*s != '+' || !*++s)
3608 p_newfirst = strtolinenum(s, &s);
3610 p_repl_lines = strtolinenum(s + 1, &s);
3617 if (p_first >= LINENUM_MAX - p_ptrn_lines ||
3618 p_newfirst > LINENUM_MAX - p_repl_lines ||
3619 p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3622 p_first++; /* do append rather than insert */
3623 p_max = p_ptrn_lines + p_repl_lines + 1;
3624 while (p_max >= hunkmax)
3627 fillnew = fillold + p_ptrn_lines;
3628 p_end = fillnew + p_repl_lines;
3629 snprintf(buf, buf_size, "*** %ld,%ld ****\n", p_first,
3630 p_first + p_ptrn_lines - 1);
3631 p_line[0] = savestr(buf);
3637 snprintf(buf, buf_size, "--- %ld,%ld ----\n", p_newfirst,
3638 p_newfirst + p_repl_lines - 1);
3639 p_line[fillnew] = savestr(buf);
3644 p_char[fillnew++] = '=';
3647 p_hunk_beg = p_input_line + 1;
3648 while (fillold <= p_ptrn_lines || fillnew <= p_end) {
3649 line_beginning = ftello(pfp);
3653 if (p_max - fillnew < 3) {
3654 /* assume blank lines got chopped */
3655 strlcpy(buf, " \n", buf_size);
3657 fatal("unexpected end of file in patch\n");
3660 if (*buf == '\t' || *buf == '\n') {
3661 ch = ' '; /* assume the space got eaten */
3665 s = savestr(buf + 1);
3668 while (--fillnew > p_ptrn_lines)
3669 free(p_line[fillnew]);
3670 p_end = fillold - 1;
3675 if (fillold > p_ptrn_lines) {
3677 p_end = fillnew - 1;
3680 p_char[fillold] = ch;
3681 p_line[fillold] = s;
3682 p_len[fillold++] = strlen(s);
3683 if (fillold > p_ptrn_lines) {
3684 if (remove_special_line()) {
3685 p_len[fillold - 1] -= 1;
3686 s[p_len[fillold - 1]] = 0;
3694 if (fillold > p_ptrn_lines) {
3696 while (--fillnew > p_ptrn_lines)
3697 free(p_line[fillnew]);
3698 p_end = fillold - 1;
3702 p_char[fillold] = ch;
3703 p_line[fillold] = s;
3704 p_len[fillold++] = strlen(s);
3707 while (--fillnew > p_ptrn_lines)
3708 free(p_line[fillnew]);
3709 p_end = fillold - 1;
3712 if (fillold > p_ptrn_lines) {
3713 if (remove_special_line()) {
3714 p_len[fillold - 1] -= 1;
3715 s[p_len[fillold - 1]] = 0;
3720 if (fillnew > p_end) {
3722 while (--fillnew > p_ptrn_lines)
3723 free(p_line[fillnew]);
3724 p_end = fillold - 1;
3727 p_char[fillnew] = ch;
3728 p_line[fillnew] = s;
3729 p_len[fillnew++] = strlen(s);
3730 if (fillold > p_ptrn_lines) {
3731 if (remove_special_line()) {
3732 p_len[fillnew - 1] -= 1;
3733 s[p_len[fillnew - 1]] = 0;
3741 if (ch != ' ' && context > 0) {
3742 if (context < p_context)
3743 p_context = context;
3747 } else { /* normal diff--fake it up */
3752 line_beginning = ftello(pfp);
3756 if (len == 0 || !isdigit((unsigned char)*buf)) {
3757 next_intuit_at(line_beginning, p_input_line);
3760 p_first = strtolinenum(buf, &s);
3762 p_ptrn_lines = strtolinenum(s + 1, &s) - p_first + 1;
3763 if (p_ptrn_lines < 0)
3766 p_ptrn_lines = (*s != 'a');
3768 if (hunk_type == 'a')
3769 p_first++; /* do append rather than insert */
3770 min = strtolinenum(s + 1, &s);
3772 max = strtolinenum(s + 1, &s);
3775 if (min < 0 || min > max || max - min == LINENUM_MAX)
3777 if (hunk_type == 'd')
3780 p_repl_lines = max - min + 1;
3781 if (p_newfirst > LINENUM_MAX - p_repl_lines ||
3782 p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3784 p_end = p_ptrn_lines + p_repl_lines + 1;
3785 if (p_end > MAXHUNKSIZE)
3786 fatal("hunk too large (%ld lines) at line %ld: %s",
3787 p_end, p_input_line, buf);
3788 while (p_end >= hunkmax)
3790 snprintf(buf, buf_size, "*** %ld,%ld\n", p_first,
3791 p_first + p_ptrn_lines - 1);
3792 p_line[0] = savestr(buf);
3798 for (i = 1; i <= p_ptrn_lines; i++) {
3802 fatal("unexpected end of file in patch at line %ld\n",
3805 fatal("< expected at line %ld of patch\n",
3807 p_line[i] = savestr(buf + 2);
3812 p_len[i] = strlen(p_line[i]);
3816 if (remove_special_line()) {
3818 (p_line[i - 1])[p_len[i - 1]] = 0;
3820 if (hunk_type == 'c') {
3824 fatal("unexpected end of file in patch at line %ld\n",
3827 fatal("--- expected at line %ld of patch\n",
3830 snprintf(buf, buf_size, "--- %ld,%ld\n", min, max);
3831 p_line[i] = savestr(buf);
3837 for (i++; i <= p_end; i++) {
3841 fatal("unexpected end of file in patch at line %ld\n",
3844 fatal("> expected at line %ld of patch\n",
3846 p_line[i] = savestr(buf + 2);
3851 p_len[i] = strlen(p_line[i]);
3855 if (remove_special_line()) {
3857 (p_line[i - 1])[p_len[i - 1]] = 0;
3860 if (reverse) /* backwards patch? */
3862 say("Not enough memory to swap next hunk!\n");
3868 for (i = 0; i <= p_end; i++) {
3869 if (i == p_ptrn_lines)
3873 fprintf(stderr, "%3ld %c %c %s", i, p_char[i],
3874 special, p_line[i]);
3879 if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */
3880 p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */
3885 * Input a line from the patch file.
3886 * Worry about indentation if do_indent is true.
3887 * The line is read directly into the buf global variable which
3888 * is resized if necessary in order to hold the complete line.
3889 * Returns the number of characters read including the terminating
3893 pgets(bool do_indent)
3897 int indent = 0, skipped = 0;
3899 line = fgetln(pfp, &len);
3901 if (len + 1 > buf_size) {
3902 while (len + 1 > buf_size)
3905 buf = malloc(buf_size);
3907 fatal("out of memory\n");
3909 if (do_indent == 1 && p_indent) {
3911 indent < p_indent && (*line == ' ' || *line == '\t' || *line == 'X');
3912 line++, skipped++) {
3914 indent += 8 - (indent %7);
3919 memcpy(buf, line, len - skipped);
3920 buf[len - skipped] = '\0';
3927 * Reverse the old and new portions of the current hunk.
3932 char **tp_line; /* the text of the hunk */
3933 unsigned short *tp_len;/* length of each line */
3934 char *tp_char; /* +, -, and ! */
3937 bool blankline = false;
3941 p_first = p_newfirst;
3944 /* make a scratch copy */
3949 p_line = NULL; /* force set_hunkmax to allocate again */
3953 if (p_line == NULL || p_len == NULL || p_char == NULL) {
3961 return false; /* not enough memory to swap hunk! */
3963 /* now turn the new into the old */
3965 i = p_ptrn_lines + 1;
3966 if (tp_char[i] == '\n') { /* account for possible blank line */
3970 if (p_efake >= 0) { /* fix non-freeable ptr range */
3978 for (n = 0; i <= p_end; i++, n++) {
3979 p_line[n] = tp_line[i];
3980 p_char[n] = tp_char[i];
3981 if (p_char[n] == '+')
3983 p_len[n] = tp_len[i];
3986 i = p_ptrn_lines + 1;
3987 p_line[n] = tp_line[i];
3988 p_char[n] = tp_char[i];
3989 p_len[n] = tp_len[i];
3992 if (p_char[0] != '=')
3993 fatal("Malformed patch at line %ld: expected '=' found '%c'\n",
3994 p_input_line, p_char[0]);
3996 for (s = p_line[0]; *s; s++)
4000 /* now turn the old into the new */
4002 if (p_char[0] != '*')
4003 fatal("Malformed patch at line %ld: expected '*' found '%c'\n",
4004 p_input_line, p_char[0]);
4006 for (s = tp_line[0]; *s; s++)
4009 for (i = 0; n <= p_end; i++, n++) {
4010 p_line[n] = tp_line[i];
4011 p_char[n] = tp_char[i];
4012 if (p_char[n] == '-')
4014 p_len[n] = tp_len[i];
4017 if (i != p_ptrn_lines + 1)
4018 fatal("Malformed patch at line %ld: expected %ld lines, "
4020 p_input_line, p_ptrn_lines + 1, i);
4023 p_ptrn_lines = p_repl_lines;
4034 * Return the specified line position in the old file of the old context.
4043 * Return the number of lines of old context.
4046 pch_ptrn_lines(void)
4048 return p_ptrn_lines;
4052 * Return the probable line position in the new file of the first line.
4061 * Return the number of lines in the replacement text including context.
4064 pch_repl_lines(void)
4066 return p_repl_lines;
4070 * Return the number of lines in the whole hunk.
4079 * Return the number of context lines before the first changed line.
4088 * Return the length of a particular patch line.
4091 pch_line_len(LINENUM line)
4097 * Return the control character (+, -, *, !, etc) for a patch line.
4100 pch_char(LINENUM line)
4102 return p_char[line];
4106 * Return a pointer to a particular patch line.
4109 pfetch(LINENUM line)
4111 return p_line[line];
4115 * Return where in the patch file this hunk began, for error messages.
4124 * Apply an ed script by feeding ed itself.
4130 off_t beginning_of_this_line;
4131 FILE *pipefp = NULL;
4134 if (!skip_rest_of_patch) {
4135 if (copy_file(filearg[0], TMPOUTNAME) < 0) {
4137 fatal("can't create temp file %s", TMPOUTNAME);
4139 snprintf(buf, buf_size, "%s%s%s", _PATH_RED,
4140 verbosity == VERBOSE ? " " : " -s ", TMPOUTNAME);
4141 pipefp = popen(buf, "w");
4144 beginning_of_this_line = ftello(pfp);
4145 if (pgets(true) == 0) {
4146 next_intuit_at(beginning_of_this_line, p_input_line);
4150 for (t = buf; isdigit((unsigned char)*t) || *t == ','; t++)
4152 /* POSIX defines allowed commands as {a,c,d,i,s} */
4153 if (isdigit((unsigned char)*buf) &&
4154 (*t == 'a' || *t == 'c' || *t == 'd' || *t == 'i' || *t == 's')) {
4160 t = strchr(buf, '\0') - 1;
4161 while (--t >= buf && *t == '\\')
4162 continuation = !continuation;
4163 if (!continuation ||
4169 } else if (*t != 'd') {
4170 while (pgets(true)) {
4174 if (strEQ(buf, ".\n"))
4179 next_intuit_at(beginning_of_this_line, p_input_line);
4185 fprintf(pipefp, "w\n");
4186 fprintf(pipefp, "q\n");
4191 if (move_file(TMPOUTNAME, outname) < 0) {
4193 chmod(TMPOUTNAME, filemode);
4195 chmod(outname, filemode);
4201 * Choose the name of the file to be patched based on POSIX rules.
4202 * NOTE: the POSIX rules are amazingly stupid and we only follow them
4203 * if the user specified --posix or set POSIXLY_CORRECT.
4206 posix_name(const struct file_name *names, bool assume_exists)
4212 * POSIX states that the filename will be chosen from one
4213 * of the old, new and index names (in that order) if
4214 * the file exists relative to CWD after -p stripping.
4216 for (i = 0; i < MAX_FILE; i++) {
4217 if (names[i].path != NULL && names[i].exists) {
4218 path = names[i].path;
4222 if (path == NULL && !assume_exists) {
4224 * No files found, check to see if the diff could be
4225 * creating a new file.
4227 if (path == NULL && ok_to_create_file &&
4228 names[NEW_FILE].path != NULL)
4229 path = names[NEW_FILE].path;
4232 return path ? xstrdup(path) : NULL;
4236 compare_names(const struct file_name *names, bool assume_exists)
4238 size_t min_components, min_baselen, min_len, tmp;
4244 * The "best" name is the one with the fewest number of path
4245 * components, the shortest basename length, and the shortest
4246 * overall length (in that order). We only use the Index: file
4247 * if neither of the old or new files could be intuited from
4250 min_components = min_baselen = min_len = SIZE_MAX;
4251 for (i = INDEX_FILE; i >= OLD_FILE; i--) {
4252 path = names[i].path;
4253 if (path == NULL || (!names[i].exists && !assume_exists))
4255 if ((tmp = num_components(path)) > min_components)
4257 if (tmp < min_components) {
4258 min_components = tmp;
4261 if ((tmp = strlen(basename(path))) > min_baselen)
4263 if (tmp < min_baselen) {
4267 if ((tmp = strlen(path)) > min_len)
4276 * Choose the name of the file to be patched based the "best" one
4280 best_name(const struct file_name *names, bool assume_exists)
4284 best = compare_names(names, assume_exists);
4286 /* No match? Check to see if the diff could be creating a new file. */
4287 if (best == NULL && ok_to_create_file)
4288 best = names[NEW_FILE].path;
4290 return best ? xstrdup(best) : NULL;
4294 num_components(const char *path)
4299 for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) {
4301 cp++; /* skip consecutive slashes */
4307 * Convert number at NPTR into LINENUM and save address of first
4308 * character that is not a digit in ENDPTR. If conversion is not
4309 * possible, call fatal.
4312 strtolinenum(char *nptr, char **endptr)
4319 for (p = nptr; isdigit((unsigned char)*p); p++)
4328 rv = strtonum(nptr, 0, LINENUM_MAX, &errstr);
4330 fatal("invalid line number at line %ld: `%s' is %s\n",
4331 p_input_line, nptr, errstr);
4340 [FILE:608:files/pch.h]
4343 #define INDEX_FILE 2
4351 void re_patch(void);
4352 void open_patch_file(const char *);
4353 void set_hunkmax(void);
4354 bool there_is_another_patch(void);
4355 bool another_hunk(void);
4356 bool pch_swap(void);
4357 char *pfetch(LINENUM);
4358 unsigned short pch_line_len(LINENUM);
4359 LINENUM pch_first(void);
4360 LINENUM pch_ptrn_lines(void);
4361 LINENUM pch_newfirst(void);
4362 LINENUM pch_repl_lines(void);
4363 LINENUM pch_end(void);
4364 LINENUM pch_context(void);
4365 LINENUM pch_hunk_beg(void);
4366 char pch_char(LINENUM);
4367 void do_ed_script(void);
4370 [FILE:8191:files/util.c]
4371 #include <sys/stat.h>
4388 #include "backupfile.h"
4389 #include "pathnames.h"
4391 /* Rename a file, copying it if necessary. */
4394 move_file(const char *from, const char *to)
4401 if (strEQ(to, "-")) {
4404 say("Moving %s to stdout.\n", from);
4406 fromfd = open(from, O_RDONLY);
4408 pfatal("internal error, can't reopen %s", from);
4409 while ((i = read(fromfd, buf, buf_size)) > 0)
4410 if (write(STDOUT_FILENO, buf, i) != i)
4411 pfatal("write failed");
4415 if (backup_file(to) < 0) {
4416 say("Can't backup %s, output is in %s: %s\n", to, from,
4422 say("Moving %s to %s.\n", from, to);
4424 if (rename(from, to) < 0) {
4425 if (errno != EXDEV || copy_file(from, to) < 0) {
4426 say("Can't create %s, output is in %s: %s\n",
4427 to, from, strerror(errno));
4434 /* Backup the original file. */
4437 backup_file(const char *orig)
4439 struct stat filestat;
4440 char bakname[PATH_MAX], *s, *simplename;
4444 if (backup_type == none || stat(orig, &filestat) != 0)
4445 return 0; /* nothing to do */
4447 * If the user used zero prefixes or suffixes, then
4448 * he doesn't want backups. Yet we have to remove
4449 * orig to break possible hardlinks.
4451 if ((origprae && *origprae == 0) || *simple_backup_suffix == 0) {
4455 orig_device = filestat.st_dev;
4456 orig_inode = filestat.st_ino;
4459 if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
4460 strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
4461 fatal("filename %s too long for buffer\n", origprae);
4463 if ((s = find_backup_file_name(orig)) == NULL)
4464 fatal("out of memory\n");
4465 if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
4466 fatal("filename %s too long for buffer\n", s);
4470 if ((simplename = strrchr(bakname, '/')) != NULL)
4471 simplename = simplename + 1;
4473 simplename = bakname;
4476 * Find a backup name that is not the same file. Change the
4477 * first lowercase char into uppercase; if that isn't
4478 * sufficient, chop off the first char and try again.
4480 while (stat(bakname, &filestat) == 0 &&
4481 orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
4482 /* Skip initial non-lowercase chars. */
4483 for (s = simplename; *s && !islower((unsigned char)*s); s++)
4486 *s = toupper((unsigned char)*s);
4488 memmove(simplename, simplename + 1,
4489 strlen(simplename + 1) + 1);
4493 say("Moving %s to %s.\n", orig, bakname);
4495 if (rename(orig, bakname) < 0) {
4496 if (errno != EXDEV || copy_file(orig, bakname) < 0)
4506 copy_file(const char *from, const char *to)
4511 tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
4514 fromfd = open(from, O_RDONLY, 0);
4516 pfatal("internal error, can't reopen %s", from);
4517 while ((i = read(fromfd, buf, buf_size)) > 0)
4518 if (write(tofd, buf, i) != i)
4519 pfatal("write to %s failed", to);
4526 * Allocate a unique area for a string.
4529 savestr(const char *s)
4540 fatal("out of memory\n");
4546 * Allocate a unique area for a string. Call fatal if out of memory.
4549 xstrdup(const char *s)
4557 fatal("out of memory\n");
4562 * Vanilla terminal output (buffered).
4565 say(const char *fmt, ...)
4570 vfprintf(stdout, fmt, ap);
4576 * Terminal output, pun intended.
4579 fatal(const char *fmt, ...)
4584 fprintf(stderr, "patch: **** ");
4585 vfprintf(stderr, fmt, ap);
4591 * Say something from patch, something from the system, then silence . . .
4594 pfatal(const char *fmt, ...)
4599 fprintf(stderr, "patch: **** ");
4601 vfprintf(stderr, fmt, ap);
4603 fprintf(stderr, ": %s\n", strerror(errnum));
4608 * Get a response from the user via /dev/tty
4611 ask(const char *fmt, ...)
4615 static int ttyfd = -1;
4618 vfprintf(stdout, fmt, ap);
4622 ttyfd = open(_PATH_TTY, O_RDONLY);
4624 if ((nr = read(ttyfd, buf, buf_size)) > 0 &&
4625 buf[nr - 1] == '\n')
4628 if (ttyfd < 0 || nr <= 0) {
4629 /* no tty or error reading, pretend user entered 'return' */
4636 * How to handle certain events when not in a critical region.
4639 set_signals(int reset)
4641 static int hup_exit = 0;
4642 static int int_exit = 0;
4645 signal (SIGHUP, hup_exit ? my_exit : SIG_IGN);
4646 signal (SIGINT, int_exit ? my_exit : SIG_IGN);
4648 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
4650 signal (SIGHUP, my_exit);
4652 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
4654 signal (SIGINT, my_exit);
4660 * How to handle certain events when in a critical region.
4663 ignore_signals(void)
4665 signal(SIGHUP, SIG_IGN);
4666 signal(SIGINT, SIG_IGN);
4670 * Make sure we'll have the directories to create a file. If `striplast' is
4671 * true, ignore the last element of `filename'.
4675 makedirs(const char *filename, bool striplast)
4679 if ((tmpbuf = strdup(filename)) == NULL)
4680 fatal("out of memory\n");
4683 char *s = strrchr(tmpbuf, '/');
4686 return; /* nothing to be done */
4690 if (mkpath(tmpbuf) != 0)
4691 pfatal("creation of %s failed", tmpbuf);
4696 * Make filenames more reasonable.
4699 fetchname(const char *at, bool *exists, int strip_leading)
4701 char *fullname, *name, *t;
4703 struct stat filestat;
4705 if (at == NULL || *at == '\0')
4707 while (isspace((unsigned char)*at))
4711 say("fetchname %s %d\n", at, strip_leading);
4713 /* So files can be created by diffing against /dev/null. */
4714 if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1))
4716 name = fullname = t = savestr(at);
4718 tab = strchr(t, '\t') != NULL;
4719 /* Strip off up to `strip_leading' path components and NUL terminate. */
4720 for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') ||
4721 !isspace((unsigned char)*t)); t++) {
4722 if (t[0] == '/' && t[1] != '/' && t[1] != '\0')
4723 if (--sleading >= 0)
4729 * If no -p option was given (957 is the default value!), we were
4730 * given a relative pathname, and the leading directories that we
4731 * just stripped off all exist, put them back on.
4733 if (strip_leading == 957 && name != fullname && *fullname != '/') {
4735 if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
4740 name = savestr(name);
4743 *exists = stat(name, &filestat) == 0;
4750 printf("patch 2.0-12u11 Ravenports\n");
4751 my_exit(EXIT_SUCCESS);
4755 * Exit with cleanup.
4770 [FILE:759:files/util.h]
4771 char *fetchname(const char *, bool *, int);
4772 int backup_file(const char *);
4773 int move_file(const char *, const char *);
4774 int copy_file(const char *, const char *);
4775 void say(const char *, ...)
4776 __attribute__((__format__(__printf__, 1, 2)));
4777 void fatal(const char *, ...)
4778 __attribute__((__format__(__printf__, 1, 2)));
4779 void pfatal(const char *, ...)
4780 __attribute__((__format__(__printf__, 1, 2)));
4781 void ask(const char *, ...)
4782 __attribute__((__format__(__printf__, 1, 2)));
4783 char *savestr(const char *);
4784 char *xstrdup(const char *);
4785 void set_signals(int);
4786 void ignore_signals(void);
4787 void makedirs(const char *, bool);
4789 void my_exit(int) __attribute__((noreturn));
4792 extern int mkpath(char *);