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[linux]= libbsd:single:standard
19 LICENSE= CUSTOM1:single
20 LICENSE_NAME= CUSTOM1:"Patch license from Larry Wall"
22 LICENSE_FILE= CUSTOM1:{{WRKSRC}}/LICENSE
26 cp ${FILESDIR}/* ${WRKSRC}/
28 [FILE:565:descriptions/desc.single]
29 This version of patch comes FreeBSD which means there are heavy influences
30 from DragonFly, OpenBSD and NetBSD as well.
32 The primary purpose of this port is to replace GNU patch in the
33 Ravenports system root. The BSD version of patch correctly locates
34 upwards relative paths such as "--- ../../module3-2.a/configure" while
35 GNU patch fails to find it. As this is a crucial feature, especially
36 for "extra patches", the GNU patch program has to be replaced.
38 The OpenBSD modification of handling git-style patches (the "--- a/" and
39 "+++ b/" formats are also present.
42 [FILE:36:manifests/plist.single]
44 share/man/man1/patch.1.gz
47 [FILE:1672:files/LICENSE]
49 * Copyright 1986, Larry Wall
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following condition is met:
53 * 1. Redistributions of source code must retain the above copyright notice,
54 * this condition and the following disclaimer.
56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
57 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
58 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
59 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
60 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
63 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * patch - a program to apply diffs to original files
70 * -C option added in 1998, original code by Marc Espie, based on FreeBSD
76 * backupfile -- declarations for making Emacs style backup file names
77 * Copyright (C) 1990 Free Software Foundation, Inc.
79 * This program is free software; you can redistribute it and/or modify it
80 * without restriction.
82 * This program is distributed in the hope that it will be useful, but WITHOUT
83 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
84 * FITNESS FOR A PARTICULAR PURPOSE.
89 [FILE:479:files/Makefile]
91 SRCS= ${PROG}.c pch.c inp.c util.c backupfile.c mkpath.c \
94 CFLAGS+= -I${PREFIX}/include -I.
97 .if "${OPSYS}" == "Linux"
98 STATIC_LIBS+= ${PREFIX}/lib/libbsd.a
105 rm -f ${OBJS} ${PROG}
108 ${CC} -o ${PROG} ${.ALLSRC} ${CFLAGS} ${STATIC_LIBS}
111 ${BSD_INSTALL_PROGRAM} ${PROG} ${DESTDIR}${PREFIX}/bin/
112 ${BSD_INSTALL_MAN} ${PROG}.1 ${DESTDIR}${PREFIX}/share/man/man1
115 [FILE:5856:files/backupfile.c]
124 #include "backupfile.h"
125 #include "linux_support.h"
128 #define ISDIGIT(c) (isascii ((unsigned char)c) && isdigit ((unsigned char)c))
130 /* Which type of backup file names are generated. */
131 enum backup_type backup_type = none;
134 * The extension added to file names to produce a simple (as opposed to
135 * numbered) backup file name.
137 const char *simple_backup_suffix = "~";
139 static char *concat(const char *, const char *);
140 static char *make_version_name(const char *, int);
141 static int max_backup_version(const char *, const char *);
142 static int version_number(const char *, const char *, size_t);
143 static int argmatch(const char *, const char **);
144 static void invalid_arg(const char *, const char *, int);
147 * Return the name of the new backup file for file FILE, allocated with
148 * malloc. Return 0 if out of memory. FILE must not end with a '/' unless it
149 * is the root directory. Do not call this function if backup_type == none.
152 find_backup_file_name(const char *file)
154 char *dir, *base_versions, *tmp_file;
157 if (backup_type == simple)
158 return concat(file, simple_backup_suffix);
159 tmp_file = strdup(file);
160 if (tmp_file == NULL)
162 base_versions = concat(basename(tmp_file), ".~");
164 if (base_versions == NULL)
166 tmp_file = strdup(file);
167 if (tmp_file == NULL) {
171 dir = dirname(tmp_file);
177 highest_backup = max_backup_version(base_versions, dir);
180 if (backup_type == numbered_existing && highest_backup == 0)
181 return concat(file, simple_backup_suffix);
182 return make_version_name(file, highest_backup + 1);
186 * Return the number of the highest-numbered backup file for file FILE in
187 * directory DIR. If there are no numbered backups of FILE in DIR, or an
188 * error occurs reading DIR, return 0. FILE should already have ".~" appended
192 max_backup_version(const char *file, const char *dir)
196 int highest_version, this_version;
197 size_t file_name_length;
204 file_name_length = strlen(file);
206 while ((dp = readdir(dirp)) != NULL) {
207 if (strlen(dp->d_name) <= file_name_length)
210 this_version = version_number(file, dp->d_name, file_name_length);
211 if (this_version > highest_version)
212 highest_version = this_version;
215 return highest_version;
219 * Return a string, allocated with malloc, containing "FILE.~VERSION~".
220 * Return 0 if out of memory.
223 make_version_name(const char *file, int version)
227 if (asprintf(&backup_name, "%s.~%d~", file, version) == -1)
233 * If BACKUP is a numbered backup of BASE, return its version number;
234 * otherwise return 0. BASE_LENGTH is the length of BASE. BASE should
235 * already have ".~" appended to it.
238 version_number(const char *base, const char *backup, size_t base_length)
244 if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) {
245 for (p = &backup[base_length]; ISDIGIT(*p); ++p)
246 version = version * 10 + *p - '0';
247 if (p[0] != '~' || p[1])
254 * Return the newly-allocated concatenation of STR1 and STR2. If out of
258 concat(const char *str1, const char *str2)
262 if (asprintf(&newstr, "%s%s", str1, str2) == -1)
268 * If ARG is an unambiguous match for an element of the null-terminated array
269 * OPTLIST, return the index in OPTLIST of the matched element, else -1 if it
270 * does not match any element or -2 if it is ambiguous (is a prefix of more
274 argmatch(const char *arg, const char **optlist)
276 int i; /* Temporary index in OPTLIST. */
277 size_t arglen; /* Length of ARG. */
278 int matchind = -1; /* Index of first nonexact match. */
279 int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
281 arglen = strlen(arg);
283 /* Test all elements for either exact match or abbreviated matches. */
284 for (i = 0; optlist[i]; i++) {
285 if (!strncmp(optlist[i], arg, arglen)) {
286 if (strlen(optlist[i]) == arglen)
287 /* Exact match found. */
289 else if (matchind == -1)
290 /* First nonexact match found. */
293 /* Second nonexact match found. */
304 * Error reporting for argmatch. KIND is a description of the type of entity
305 * that was being matched. VALUE is the invalid value that was given. PROBLEM
306 * is the return value from argmatch.
309 invalid_arg(const char *kind, const char *value, int problem)
311 fprintf(stderr, "patch: ");
313 fprintf(stderr, "invalid");
314 else /* Assume -2. */
315 fprintf(stderr, "ambiguous");
316 fprintf(stderr, " %s `%s'\n", kind, value);
319 static const char *backup_args[] = {
320 "none", "never", "simple", "nil", "existing", "t", "numbered", 0
323 static enum backup_type backup_types[] = {
324 none, simple, simple, numbered_existing,
325 numbered_existing, numbered, numbered
329 * Return the type of backup indicated by VERSION. Unique abbreviations are
333 get_version(const char *version)
337 if (version == NULL || *version == '\0')
338 return numbered_existing;
339 i = argmatch(version, backup_args);
341 return backup_types[i];
342 invalid_arg("version control type", version, i);
347 [FILE:514:files/backupfile.h]
348 /* When to make backup files. */
350 /* Never make backups. */
353 /* Make simple backups of every file. */
357 * Make numbered backups of files that already have numbered backups,
358 * and simple backups of the others.
362 /* Make numbered backups of every file. */
366 extern enum backup_type backup_type;
367 extern const char *simple_backup_suffix;
369 char *find_backup_file_name(const char *file);
370 enum backup_type get_version(const char *version);
373 [FILE:1855:files/common.h]
374 #include <sys/types.h>
378 #include "linux_support.h"
384 #define MAXHUNKSIZE 200000 /* is this enough lines? */
385 #define INITHUNKMAX 125 /* initial dynamic allocation size */
386 #define INITLINELEN 4096
387 #define BUFFERSIZE 4096
388 #define LINENUM_MAX LONG_MAX
390 #define ORIGEXT ".orig"
391 #define REJEXT ".rej"
393 /* handy definitions */
395 #define strEQ(s1,s2) (strcmp(s1, s2) == 0)
396 #define strnNE(s1,s2,l) (strncmp(s1, s2, l) != 0)
397 #define strnEQ(s1,s2,l) (strncmp(s1, s2, l) == 0)
401 typedef long LINENUM; /* must be signed */
402 enum vlevel { NORMAL_LEVEL, SILENT, VERBOSE };
406 extern mode_t filemode;
408 extern char *buf; /* general purpose buffer */
409 extern size_t buf_size; /* size of general purpose buffer */
411 extern bool using_plan_a; /* try to keep everything in memory */
412 extern bool out_of_mem; /* ran out of memory in plan a */
416 extern char *filearg[MAXFILEC];
417 extern bool ok_to_create_file;
418 extern char *outname;
419 extern char *origprae;
421 extern char *TMPOUTNAME;
422 extern char *TMPINNAME;
423 extern char *TMPREJNAME;
424 extern char *TMPPATNAME;
425 extern bool toutkeep;
426 extern bool trejkeep;
434 extern enum vlevel verbosity;
436 extern bool noreverse;
437 extern bool skip_rest_of_patch;
438 extern int strippath;
439 extern bool canonicalize;
440 /* TRUE if -C was specified on command line. */
441 extern bool check_only;
442 extern bool warn_on_invalid_line;
443 extern bool last_line_missing_eol;
446 #define CONTEXT_DIFF 1
447 #define NORMAL_DIFF 2
449 #define NEW_CONTEXT_DIFF 4
452 extern int diff_type;
453 extern char *revision; /* prerequisite revision, if any */
454 extern LINENUM input_lines; /* how long is input file in lines */
460 [FILE:9806:files/inp.c]
461 #include <sys/types.h>
462 #include <sys/file.h>
463 #include <sys/stat.h>
464 #include <sys/mman.h>
482 /* Input-file-with-indexable-lines abstract type */
484 static size_t i_size; /* size of the input file */
485 static char *i_womp; /* plan a buffer for entire file */
486 static char **i_ptr; /* pointers to lines in i_womp */
487 static char empty_line[] = { '\0' };
489 static int tifd = -1; /* plan b virtual string array */
490 static char *tibuf[2]; /* plan b buffers */
491 static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
492 static size_t lines_per_buf; /* how many lines per buffer */
493 static size_t tibuflen; /* plan b buffer length */
494 static size_t tireclen; /* length of records in tmp file */
496 static bool rev_in_string(const char *);
497 static bool reallocate_lines(size_t *);
499 /* returns false if insufficient memory */
500 static bool plan_a(const char *);
502 static void plan_b(const char *);
504 /* New patch--prepare to edit another file. */
512 if (i_womp != NULL) {
513 munmap(i_womp, i_size);
518 using_plan_a = true; /* maybe the next one is smaller */
523 tibuf[0] = tibuf[1] = NULL;
524 tiline[0] = tiline[1] = -1;
529 /* Construct the line index, somehow or other. */
532 scan_input(const char *filename)
534 if (!plan_a(filename))
536 if (verbosity != SILENT) {
537 say("Patching file %s using Plan %s...\n", filename,
538 (using_plan_a ? "A" : "B"));
543 reallocate_lines(size_t *lines_allocated)
548 new_size = *lines_allocated * 3 / 2;
549 p = realloc(i_ptr, (new_size + 2) * sizeof(char *));
550 if (p == NULL) { /* shucks, it was a near thing */
551 munmap(i_womp, i_size);
555 *lines_allocated = 0;
558 *lines_allocated = new_size;
563 /* Try keeping everything in memory. */
566 plan_a(const char *filename)
570 struct stat filestat;
573 size_t iline, lines_allocated;
580 if (filename == NULL || *filename == '\0')
583 statfailed = stat(filename, &filestat);
584 if (statfailed && ok_to_create_file) {
585 if (verbosity == VERBOSE)
586 say("(Creating file %s...)\n", filename);
589 * in check_patch case, we still display `Creating file' even
590 * though we're not. The rule is that -C should be as similar
591 * to normal patch behavior as possible
595 makedirs(filename, true);
596 close(creat(filename, 0666));
597 statfailed = stat(filename, &filestat);
600 fatal("can't find %s\n", filename);
601 filemode = filestat.st_mode;
602 if (!S_ISREG(filemode))
603 fatal("%s is not a normal file--can't patch\n", filename);
604 if ((uint64_t)filestat.st_size > SIZE_MAX) {
605 say("block too large to mmap\n");
608 i_size = (size_t)filestat.st_size;
610 set_hunkmax(); /* make sure dynamic arrays are allocated */
612 return false; /* force plan b because plan a bombed */
614 if ((ifd = open(filename, O_RDONLY)) < 0)
615 pfatal("can't open file %s", filename);
618 i_womp = mmap(NULL, i_size, PROT_READ, MAP_PRIVATE, ifd, 0);
619 if (i_womp == MAP_FAILED) {
620 perror("mmap failed");
631 madvise(i_womp, i_size, MADV_SEQUENTIAL);
633 /* estimate the number of lines */
634 lines_allocated = i_size / 25;
635 if (lines_allocated < 100)
636 lines_allocated = 100;
638 if (!reallocate_lines(&lines_allocated))
641 /* now scan the buffer and build pointer array */
643 i_ptr[iline] = i_womp;
644 /* test for NUL too, to maintain the behavior of the original code */
645 for (s = i_womp, i = 0; i < i_size && *s != '\0'; s++, i++) {
647 if (iline == lines_allocated) {
648 if (!reallocate_lines(&lines_allocated))
651 /* these are NOT NUL terminated */
652 i_ptr[++iline] = s + 1;
655 /* if the last line contains no EOL, append one */
656 if (i_size > 0 && i_womp[i_size - 1] != '\n') {
657 last_line_missing_eol = true;
659 sz = s - i_ptr[iline];
664 munmap(i_womp, i_size);
669 memcpy(p, i_ptr[iline], sz);
672 /* count the extra line and make it point to some valid mem */
673 i_ptr[++iline] = empty_line;
675 last_line_missing_eol = false;
677 input_lines = iline - 1;
679 /* now check for revision, if any */
681 if (revision != NULL) {
682 if (i_womp == NULL || !rev_in_string(i_womp)) {
684 if (verbosity == VERBOSE)
685 say("Warning: this file doesn't appear "
686 "to be the %s version--patching anyway.\n",
689 fatal("this file doesn't appear to be the "
690 "%s version--aborting.\n",
693 ask("This file doesn't appear to be the "
694 "%s version--patch anyway? [n] ",
699 } else if (verbosity == VERBOSE)
700 say("Good. This file appears to be the %s version.\n",
703 return true; /* plan a will work */
706 /* Keep (virtually) nothing in memory. */
709 plan_b(const char *filename)
712 size_t i = 0, j, len, maxlen = 1;
713 char *lbuf = NULL, *p;
714 bool found_revision = (revision == NULL);
716 using_plan_a = false;
717 if ((ifp = fopen(filename, "r")) == NULL)
718 pfatal("can't open file %s", filename);
720 if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
721 pfatal("can't open file %s", TMPINNAME);
722 while ((p = fgetln(ifp, &len)) != NULL) {
723 if (p[len - 1] == '\n')
726 /* EOF without EOL, copy and add the NUL */
727 if ((lbuf = malloc(len + 1)) == NULL)
728 fatal("out of memory\n");
729 memcpy(lbuf, p, len);
733 last_line_missing_eol = true;
736 if (revision != NULL && !found_revision && rev_in_string(p))
737 found_revision = true;
739 maxlen = len; /* find longest line */
743 pfatal("can't read file %s", filename);
745 if (revision != NULL) {
746 if (!found_revision) {
748 if (verbosity == VERBOSE)
749 say("Warning: this file doesn't appear "
750 "to be the %s version--patching anyway.\n",
753 fatal("this file doesn't appear to be the "
754 "%s version--aborting.\n",
757 ask("This file doesn't appear to be the %s "
758 "version--patch anyway? [n] ",
763 } else if (verbosity == VERBOSE)
764 say("Good. This file appears to be the %s version.\n",
767 fseek(ifp, 0L, SEEK_SET); /* rewind file */
769 tibuflen = maxlen > BUFFERSIZE ? maxlen : BUFFERSIZE;
770 lines_per_buf = tibuflen / maxlen;
771 tibuf[0] = malloc(tibuflen + 1);
772 if (tibuf[0] == NULL)
773 fatal("out of memory\n");
774 tibuf[1] = malloc(tibuflen + 1);
775 if (tibuf[1] == NULL)
776 fatal("out of memory\n");
778 p = tibuf[0] + maxlen * (i % lines_per_buf);
779 if (i % lines_per_buf == 0) /* new block */
780 if (write(tifd, tibuf[0], tibuflen) !=
782 pfatal("can't write temp file");
783 if (fgets(p, maxlen + 1, ifp) == NULL) {
785 if (i % lines_per_buf != 0)
786 if (write(tifd, tibuf[0], tibuflen) !=
788 pfatal("can't write temp file");
792 /* These are '\n' terminated strings, so no need to add a NUL */
793 if (j == 0 || p[j - 1] != '\n')
798 if ((tifd = open(TMPINNAME, O_RDONLY)) < 0)
799 pfatal("can't reopen file %s", TMPINNAME);
803 * Fetch a line from the input file, \n terminated, not necessarily \0.
806 ifetch(LINENUM line, int whichbuf)
808 if (line < 1 || line > input_lines) {
809 if (warn_on_invalid_line) {
810 say("No such line %ld in input file, ignoring\n", line);
811 warn_on_invalid_line = false;
818 LINENUM offline = line % lines_per_buf;
819 LINENUM baseline = line - offline;
821 if (tiline[0] == baseline)
823 else if (tiline[1] == baseline)
826 tiline[whichbuf] = baseline;
828 if (lseek(tifd, (off_t) (baseline / lines_per_buf *
829 tibuflen), SEEK_SET) < 0)
830 pfatal("cannot seek in the temporary input file");
832 if (read(tifd, tibuf[whichbuf], tibuflen) !=
834 pfatal("error reading tmp file %s", TMPINNAME);
836 return tibuf[whichbuf] + (tireclen * offline);
841 * True if the string argument contains the revision number we want.
844 rev_in_string(const char *string)
849 if (revision == NULL)
851 patlen = strlen(revision);
852 if (strnEQ(string, revision, patlen) && isspace((unsigned char)string[patlen]))
854 for (s = string; *s; s++) {
855 if (isspace((unsigned char)*s) && strnEQ(s + 1, revision, patlen) &&
856 isspace((unsigned char)s[patlen + 1])) {
864 [FILE:83:files/inp.h]
866 void scan_input(const char *);
867 char *ifetch(LINENUM, int);
870 [FILE:917:files/linux_support.c]
871 #ifndef LINUX_SUPPORT_C
872 #define LINUX_SUPPORT_C
876 #include "linux_support.h"
879 bsd_vasprintf(char **strp, const char *fmt, va_list args)
884 va_copy(args_copy, args);
885 needed = vsnprintf(NULL, 0, fmt, args_copy);
891 *strp = malloc(needed + 1);
894 status = vsnprintf(*strp, needed + 1, fmt, args);
905 bsd_asprintf(char **strp, const char *fmt, ...)
911 status = bsd_vasprintf(strp, fmt, args);
915 #endif /* __Linux__ */
917 #endif /* LINUX_SUPPORT_C */
920 [FILE:284:files/linux_support.h]
921 #ifndef LINUX_SUPPORT_H
922 #define LINUX_SUPPORT_H
925 #include <bsd/stdio.h>
926 #include <bsd/stdlib.h>
927 #include <bsd/unistd.h>
928 #include <bsd/string.h>
930 #define asprintf bsd_asprintf
932 int bsd_asprintf(char **strp, const char *fmt, ...);
936 #endif /* LINUX_SUPPORT_H */
939 [FILE:715:files/mkpath.c]
940 #include <sys/types.h>
941 #include <sys/stat.h>
948 /* Code taken directly from mkdir(1).
950 * mkpath -- create directories.
963 slash += strspn(slash, "/");
964 slash += strcspn(slash, "/");
966 done = (*slash == '\0');
969 if (stat(path, &sb)) {
970 if (errno != ENOENT || (mkdir(path, 0777) &&
975 } else if (!S_ISDIR(sb.st_mode)) {
976 warnx("%s: %s", path, strerror(ENOTDIR));
988 [FILE:19111:files/patch.1]
989 .Dd September 6, 2017
994 .Nd apply a diff file to an original
998 .Op Fl bCcEeflNnRstuv
999 .Op Fl B Ar backup-prefix
1001 .Op Fl d Ar directory
1002 .Op Fl F Ar max-fuzz
1003 .Op Fl i Ar patchfile
1004 .Op Fl o Ar out-file
1005 .Op Fl p Ar strip-count
1006 .Op Fl r Ar rej-name
1007 .Op Fl V Cm t | nil | never | none
1009 .Op Fl z Ar backup-ext
1012 .Op Ar origfile Op Ar patchfile
1015 .Pf \*(Lt Ar patchfile
1018 will take a patch file containing any of the four forms of difference
1019 listing produced by the
1021 program and apply those differences to an original file,
1022 producing a patched version.
1025 is omitted, or is a hyphen, the patch will be read from the standard input.
1028 will attempt to determine the type of the diff listing, unless overruled by a
1035 Context diffs (old-style, new-style, and unified) and
1036 normal diffs are applied directly by the
1038 program itself, whereas ed diffs are simply fed to the
1044 contains more than one patch,
1046 will try to apply each of them as if they came from separate patch files.
1047 This means, among other things, that it is assumed that the name of the file
1048 to patch must be determined for each diff listing, and that the garbage before
1049 each diff listing will be examined for interesting things such as file names
1050 and revision level (see the section on
1051 .Sx Filename Determination
1054 The options are as follows:
1057 .Fl B Ar backup-prefix ,
1058 .Fl Fl prefix Ar backup-prefix
1060 Causes the next argument to be interpreted as a prefix to the backup file
1062 If this argument is specified, any argument to
1065 .It Fl b , Fl Fl backup
1066 Save a backup copy of the file before it is modified.
1067 By default the original file is saved with a backup extension of
1069 unless the file already has a numbered backup, in which case a numbered
1071 This is equivalent to specifying
1072 .Qo Fl V Cm existing Qc .
1073 This option is currently the default, unless
1076 .It Fl C , Fl Fl check , Fl Fl dry-run
1077 Checks that the patch would apply cleanly, but does not modify anything.
1078 .It Fl c , Fl Fl context
1081 to interpret the patch file as a context diff.
1084 .Fl Fl ifdef Ar symbol
1090 construct to mark changes.
1091 The argument following will be used as the differentiating symbol.
1092 Note that, unlike the C compiler, there must be a space between the
1096 .Fl d Ar directory ,
1097 .Fl Fl directory Ar directory
1101 to interpret the next argument as a directory,
1102 and change the working directory to it before doing anything else.
1103 .It Fl E , Fl Fl remove-empty-files
1106 to remove output files that are empty after the patches have been applied.
1107 This option is useful when applying patches that create or remove files.
1111 to interpret the patch file as an
1116 .Fl Fl fuzz Ar max-fuzz
1118 Sets the maximum fuzz factor.
1119 This option only applies to context diffs, and causes
1121 to ignore up to that many lines in looking for places to install a hunk.
1122 Note that a larger fuzz factor increases the odds of a faulty patch.
1123 The default fuzz factor is 2, and it may not be set to more than
1124 the number of lines of context in the context diff, ordinarily 3.
1125 .It Fl f , Fl Fl force
1128 to assume that the user knows exactly what he or she is doing, and to not
1130 It assumes the following:
1131 skip patches for which a file to patch cannot be found;
1132 patch files even though they have the wrong version for the
1135 and assume that patches are not reversed even if they look like they are.
1136 This option does not suppress commentary; use
1140 .Fl i Ar patchfile ,
1141 .Fl Fl input Ar patchfile
1143 Causes the next argument to be interpreted as the input file name
1144 (i.e., a patchfile).
1145 This option may be specified multiple times.
1146 .It Fl l , Fl Fl ignore-whitespace
1147 Causes the pattern matching to be done loosely, in case the tabs and
1148 spaces have been munged in your input file.
1149 Any sequence of whitespace in the pattern line will match any sequence
1151 Normal characters must still match exactly.
1152 Each line of the context must still match a line in the input file.
1153 .It Fl N , Fl Fl forward
1156 to ignore patches that it thinks are reversed or already applied.
1159 .It Fl n , Fl Fl normal
1162 to interpret the patch file as a normal diff.
1165 .Fl Fl output Ar out-file
1167 Causes the next argument to be interpreted as the output file name.
1169 .Fl p Ar strip-count ,
1170 .Fl Fl strip Ar strip-count
1172 Sets the pathname strip count,
1173 which controls how pathnames found in the patch file are treated,
1174 in case you keep your files in a different directory than the person who sent
1176 The strip count specifies how many slashes are to be stripped from
1177 the front of the pathname.
1178 (Any intervening directory names also go away.)
1179 For example, supposing the file name in the patch file was
1180 .Pa /u/howard/src/blurfl/blurfl.c :
1184 gives the entire pathname unmodified.
1189 .D1 Pa u/howard/src/blurfl/blurfl.c
1191 without the leading slash.
1196 .D1 Pa blurfl/blurfl.c
1200 at all just gives you
1202 unless all of the directories in the leading path
1203 .Pq Pa u/howard/src/blurfl
1204 exist and that path is relative,
1205 in which case you get the entire pathname unmodified.
1206 Whatever you end up with is looked for either in the current directory,
1207 or the directory specified by the
1210 .It Fl R , Fl Fl reverse
1213 that this patch was created with the old and new files swapped.
1214 (Yes, I am afraid that does happen occasionally, human nature being what it
1217 will attempt to swap each hunk around before applying it.
1218 Rejects will come out in the swapped format.
1221 option will not work with ed diff scripts because there is too little
1222 information to reconstruct the reverse operation.
1224 If the first hunk of a patch fails,
1226 will reverse the hunk to see if it can be applied that way.
1227 If it can, you will be asked if you want to have the
1230 If it cannot, the patch will continue to be applied normally.
1231 (Note: this method cannot detect a reversed patch if it is a normal diff
1232 and if the first command is an append (i.e., it should have been a delete)
1233 since appends always succeed, due to the fact that a null context will match
1235 Luckily, most patches add or change lines rather than delete them, so most
1236 reversed normal diffs will begin with a delete, which will fail, triggering
1240 .Fl Fl reject-file Ar rej-name
1242 Causes the next argument to be interpreted as the reject file name.
1244 .Fl s , Fl Fl quiet ,
1249 do its work silently, unless an error occurs.
1250 .It Fl t , Fl Fl batch
1253 in that it suppresses questions, but makes some different assumptions:
1254 skip patches for which a file to patch cannot be found (the same as
1256 skip patches for which the file has the wrong version for the
1259 and assume that patches are reversed if they look like they are.
1260 .It Fl u , Fl Fl unified
1263 to interpret the patch file as a unified context diff (a unidiff).
1265 .Fl V Cm t | nil | never | none ,
1266 .Fl Fl version-control Cm t | nil | never | none
1268 Causes the next argument to be interpreted as a method for creating
1270 The type of backups made can also be given in the
1271 .Ev PATCH_VERSION_CONTROL
1274 environment variables, which are overridden by this option.
1277 option overrides this option, causing the prefix to always be used for
1278 making backup file names.
1280 .Ev PATCH_VERSION_CONTROL
1283 environment variables and the argument to the
1285 option are like the GNU Emacs
1287 variable; they also recognize synonyms that are more descriptive.
1288 The valid values are (unique abbreviations are accepted):
1289 .Bl -tag -width Ds -offset indent
1291 Always make numbered backups.
1292 .It Cm nil , existing
1293 Make numbered backups of files that already have them,
1294 simple backups of the others.
1295 .It Cm never , simple
1296 Always make simple backups.
1298 Do not make backups.
1300 .It Fl v , Fl Fl version
1303 to print out its revision header and patch level.
1306 .Fl Fl debug Ar number
1308 Sets internal debugging flags, and is of interest only to
1312 .Fl z Ar backup-ext ,
1313 .Fl Fl suffix Ar backup-ext
1315 Causes the next argument to be interpreted as the backup extension, to be
1319 Provides extra information during processing.
1323 conformance, specifically:
1326 Backup files are not created unless the
1328 option is specified.
1330 If unspecified, the file name used is the first of the old, new and
1331 index files that exists.
1334 .Ss Patch Application
1336 will try to skip any leading garbage, apply the diff,
1337 and then skip any trailing garbage.
1338 Thus you could feed an article or message containing a
1342 If the entire diff is indented by a consistent amount,
1343 this will be taken into account.
1345 With context diffs, and to a lesser extent with normal diffs,
1347 can detect when the line numbers mentioned in the patch are incorrect,
1348 and will attempt to find the correct place to apply each hunk of the patch.
1349 As a first guess, it takes the line number mentioned for the hunk, plus or
1350 minus any offset used in applying the previous hunk.
1351 If that is not the correct place,
1353 will scan both forwards and backwards for a set of lines matching the context
1357 looks for a place where all lines of the context match.
1358 If no such place is found, and it is a context diff, and the maximum fuzz factor
1359 is set to 1 or more, then another scan takes place ignoring the first and last
1361 If that fails, and the maximum fuzz factor is set to 2 or more,
1362 the first two and last two lines of context are ignored,
1363 and another scan is made.
1364 .Pq The default maximum fuzz factor is 2.
1368 cannot find a place to install that hunk of the patch, it will put the hunk
1369 out to a reject file, which normally is the name of the output file plus
1371 (Note that the rejected hunk will come out in context diff form whether the
1372 input patch was a context diff or a normal diff.
1373 If the input was a normal diff, many of the contexts will simply be null.)
1374 The line numbers on the hunks in the reject file may be different than
1375 in the patch file: they reflect the approximate location patch thinks the
1376 failed hunks belong in the new file rather than the old one.
1378 As each hunk is completed, you will be told whether the hunk succeeded or
1379 failed, and which line (in the new file)
1381 thought the hunk should go on.
1382 If this is different from the line number specified in the diff,
1383 you will be told the offset.
1384 A single large offset MAY be an indication that a hunk was installed in the
1386 You will also be told if a fuzz factor was used to make the match, in which
1387 case you should also be slightly suspicious.
1388 .Ss Filename Determination
1389 If no original file is specified on the command line,
1391 will try to figure out from the leading garbage what the name of the file
1393 When checking a prospective file name, pathname components are stripped
1396 option and the file's existence and writability are checked relative
1397 to the current working directory (or the directory specified by the
1401 If the diff is a context or unified diff,
1403 is able to determine the old and new file names from the diff header.
1404 For context diffs, the
1406 file is specified in the line beginning with
1410 file is specified in the line beginning with
1412 For a unified diff, the
1414 file is specified in the line beginning with
1418 file is specified in the line beginning with
1422 line in the leading garbage (regardless of the diff type),
1424 will use the file name from that line as the
1429 will choose the file name by performing the following steps, with the first
1435 is operating in strict
1437 mode, the first of the
1442 file names that exist is used.
1445 will examine either the
1449 file names or, for a non-context diff, the
1451 file name, and choose the file name with the fewest path components,
1452 the shortest basename, and the shortest total file name length (in that order).
1454 If no suitable file was found to patch, the patch file is a context or
1455 unified diff, and the old file was zero length, the new file name is
1458 If the file name still cannot be determined,
1460 will prompt the user for the file name to use.
1463 Additionally, if the leading garbage contains a
1467 will take the first word from the prerequisites line (normally a version
1468 number) and check the input file to see if that word can be found.
1471 will ask for confirmation before proceeding.
1473 The upshot of all this is that you should be able to say, while in a news
1474 interface, the following:
1476 .Dl | patch -d /usr/src/local/blurfl
1478 and patch a file in the blurfl directory directly from the article containing
1481 By default, the patched version is put in place of the original, with
1482 the original file backed up to the same name with the extension
1484 or as specified by the
1490 The extension used for making backup files may also be specified in the
1491 .Ev SIMPLE_BACKUP_SUFFIX
1492 environment variable, which is overridden by the options above.
1494 If the backup file is a symbolic or hard link to the original file,
1496 creates a new backup file name by changing the first lowercase letter
1497 in the last component of the file's name into uppercase.
1498 If there are no more lowercase letters in the name,
1499 it removes the first character from the name.
1500 It repeats this process until it comes up with a
1501 backup file that does not already exist or is not linked to the original file.
1503 You may also specify where you want the output to go with the
1505 option; if that file already exists, it is backed up first.
1506 .Ss Notes For Patch Senders
1507 There are several things you should bear in mind if you are going to
1508 be sending out patches:
1510 First, you can save people a lot of grief by keeping a
1512 file which is patched to increment the patch level as the first diff in the
1513 patch file you send out.
1516 line in with the patch, it will not let them apply
1517 patches out of order without some warning.
1519 Second, make sure you have specified the file names right, either in a
1520 context diff header, or with an
1523 If you are patching something in a subdirectory, be sure to tell the patch
1528 Third, you can create a file by sending out a diff that compares a
1529 null file to the file you want to create.
1530 This will only work if the file you want to create does not exist already in
1531 the target directory.
1533 Fourth, take care not to send out reversed patches, since it makes people wonder
1534 whether they already applied the patch.
1536 Fifth, while you may be able to get away with putting 582 diff listings into
1537 one file, it is probably wiser to group related patches into separate files in
1538 case something goes haywire.
1540 .Bl -tag -width "PATCH_VERSION_CONTROL" -compact
1541 .It Ev POSIXLY_CORRECT
1546 option has been specified.
1547 .It Ev SIMPLE_BACKUP_SUFFIX
1548 Extension to use for backup file names instead of
1551 Directory to put temporary files in; default is
1553 .It Ev PATCH_VERSION_CONTROL
1554 Selects when numbered backup files are made.
1555 .It Ev VERSION_CONTROL
1557 .Ev PATCH_VERSION_CONTROL .
1560 .Bl -tag -width "$TMPDIR/patch*" -compact
1561 .It Pa $TMPDIR/patch*
1565 used to read input when
1572 utility exits with one of the following values:
1574 .Bl -tag -width Ds -offset indent -compact
1576 Successful completion.
1578 One or more lines were written to a reject file.
1583 When applying a set of patches in a loop it behooves you to check this
1584 exit status so you do not apply a later patch to a partially patched file.
1586 Too many to list here, but generally indicative that
1588 couldn't parse your patch file.
1592 indicates that there is unprocessed text in the patch file and that
1594 is attempting to intuit whether there is a patch in that text and, if so,
1595 what kind of patch it is.
1601 utility is compliant with the
1604 except as detailed above for the
1612 are extensions to that specification.
1615 with many other contributors.
1618 cannot tell if the line numbers are off in an ed script, and can only detect
1619 bad line numbers in a normal diff when it finds a
1624 A context diff using fuzz factor 3 may have the same problem.
1625 Until a suitable interactive interface is added, you should probably do
1626 a context diff in these cases to see if the changes made sense.
1627 Of course, compiling without errors is a pretty good indication that the patch
1628 worked, but not always.
1631 usually produces the correct results, even when it has to do a lot of
1633 However, the results are guaranteed to be correct only when the patch is
1634 applied to exactly the same version of the file that the patch was
1637 Could be smarter about partial matches, excessively deviant offsets and
1638 swapped code, but that would take an extra pass.
1642 will fail if you try to check several patches in succession that build on
1646 code would have to be restructured to keep temporary files around so that it
1647 can handle this situation.
1649 If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
1652 is incapable of patching both versions, and, if it works at all, will likely
1653 patch the wrong one, and tell you that it succeeded to boot.
1655 If you apply a patch you have already applied,
1657 will think it is a reversed patch, and offer to un-apply the patch.
1658 This could be construed as a feature.
1661 [FILE:26069:files/patch.c]
1662 #include <sys/types.h>
1663 #include <sys/stat.h>
1677 #include "backupfile.h"
1678 #include "pathnames.h"
1681 #define NAME_MAX 255
1684 mode_t filemode = 0644;
1686 char *buf; /* general purpose buffer */
1687 size_t buf_size; /* size of the general purpose buffer */
1689 bool using_plan_a = true; /* try to keep everything in memory */
1690 bool out_of_mem = false; /* ran out of memory in plan a */
1694 char *filearg[MAXFILEC];
1695 bool ok_to_create_file = false;
1696 char *outname = NULL;
1697 char *origprae = NULL;
1702 bool toutkeep = false;
1703 bool trejkeep = false;
1704 bool warn_on_invalid_line;
1705 bool last_line_missing_eol;
1713 bool reverse = false;
1714 bool noreverse = false;
1715 bool skip_rest_of_patch = false;
1716 int strippath = 957;
1717 bool canonicalize = false;
1718 bool check_only = false;
1720 char *revision = NULL; /* prerequisite revision, if any */
1721 LINENUM input_lines = 0; /* how long is input file in lines */
1722 int posix = 0; /* strict POSIX mode? */
1723 enum vlevel verbosity = NORMAL_LEVEL;
1725 static void reinitialize_almost_everything(void);
1726 static void get_some_switches(void);
1727 static LINENUM locate_hunk(LINENUM);
1728 static void abort_context_hunk(void);
1729 static void rej_line(int, LINENUM);
1730 static void abort_hunk(void);
1731 static void apply_hunk(LINENUM);
1732 static void init_output(const char *);
1733 static void init_reject(const char *);
1734 static void copy_till(LINENUM, bool);
1735 static bool spew_output(void);
1736 static void dump_line(LINENUM, bool);
1737 static bool patch_match(LINENUM, LINENUM, LINENUM);
1738 static bool similar(const char *, const char *, int);
1739 static void usage(void);
1741 /* true if -E was specified on command line. */
1742 static bool remove_empty_files = false;
1744 /* true if -R was specified on command line. */
1745 static bool reverse_flag_specified = false;
1747 static bool Vflag = false;
1749 /* buffer holding the name of the rejected patch file. */
1750 static char rejname[NAME_MAX + 1];
1752 /* how many input lines have been irretractibly output */
1753 static LINENUM last_frozen_line = 0;
1755 static int Argc; /* guess */
1757 static int Argc_last; /* for restarting plan_b */
1758 static char **Argv_last;
1760 static FILE *ofp = NULL; /* output file pointer */
1761 static FILE *rejfp = NULL; /* reject file pointer */
1763 static int filec = 0; /* how many file arguments? */
1764 static LINENUM last_offset = 0;
1765 static LINENUM maxfuzz = 2;
1767 /* patch using ifdef, ifndef, etc. */
1768 static bool do_defines = false;
1770 static char if_defined[128];
1772 static char not_defined[128];
1774 static const char else_defined[] = "#else\n";
1776 static char end_defined[128];
1779 /* Apply a set of diffs as appropriate. */
1782 main(int argc, char *argv[])
1784 int error = 0, hunk, failed, i, fd;
1785 bool patch_seen, reverse_seen;
1786 LINENUM where = 0, newwhere, fuzz, mymaxfuzz;
1790 setvbuf(stdout, NULL, _IOLBF, 0);
1791 setvbuf(stderr, NULL, _IOLBF, 0);
1792 for (i = 0; i < MAXFILEC; i++)
1795 buf_size = INITLINELEN;
1796 buf = malloc((unsigned)(buf_size));
1798 fatal("out of memory\n");
1800 /* Cons up the names of the temporary files. */
1801 if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
1803 for (i = strlen(tmpdir) - 1; i > 0 && tmpdir[i] == '/'; i--)
1806 if (asprintf(&TMPOUTNAME, "%.*s/patchoXXXXXXXXXX", i, tmpdir) == -1)
1807 fatal("cannot allocate memory");
1808 if ((fd = mkstemp(TMPOUTNAME)) < 0)
1809 pfatal("can't create %s", TMPOUTNAME);
1812 if (asprintf(&TMPINNAME, "%.*s/patchiXXXXXXXXXX", i, tmpdir) == -1)
1813 fatal("cannot allocate memory");
1814 if ((fd = mkstemp(TMPINNAME)) < 0)
1815 pfatal("can't create %s", TMPINNAME);
1818 if (asprintf(&TMPREJNAME, "%.*s/patchrXXXXXXXXXX", i, tmpdir) == -1)
1819 fatal("cannot allocate memory");
1820 if ((fd = mkstemp(TMPREJNAME)) < 0)
1821 pfatal("can't create %s", TMPREJNAME);
1824 if (asprintf(&TMPPATNAME, "%.*s/patchpXXXXXXXXXX", i, tmpdir) == -1)
1825 fatal("cannot allocate memory");
1826 if ((fd = mkstemp(TMPPATNAME)) < 0)
1827 pfatal("can't create %s", TMPPATNAME);
1830 v = getenv("SIMPLE_BACKUP_SUFFIX");
1832 simple_backup_suffix = v;
1834 simple_backup_suffix = ORIGEXT;
1836 /* parse switches */
1839 get_some_switches();
1842 if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL)
1843 v = getenv("VERSION_CONTROL");
1844 if (v != NULL || !posix)
1845 backup_type = get_version(v); /* OK to pass NULL. */
1848 /* make sure we clean up /tmp in case of disaster */
1852 for (open_patch_file(filearg[1]); there_is_another_patch();
1853 reinitialize_almost_everything()) {
1854 /* for each patch in patch file */
1858 warn_on_invalid_line = true;
1860 if (outname == NULL)
1861 outname = xstrdup(filearg[0]);
1863 /* for ed script just up and do it and exit */
1864 if (diff_type == ED_DIFF) {
1868 /* initialize the patched file */
1869 if (!skip_rest_of_patch)
1870 init_output(TMPOUTNAME);
1872 /* initialize reject file */
1873 init_reject(TMPREJNAME);
1875 /* find out where all the lines are */
1876 if (!skip_rest_of_patch)
1877 scan_input(filearg[0]);
1880 * from here on, open no standard i/o files, because
1881 * malloc might misfire and we can't catch it easily
1884 /* apply each hunk of patch */
1887 reverse_seen = false;
1889 while (another_hunk()) {
1892 mymaxfuzz = pch_context();
1893 if (maxfuzz < mymaxfuzz)
1894 mymaxfuzz = maxfuzz;
1895 if (!skip_rest_of_patch) {
1897 where = locate_hunk(fuzz);
1898 if (hunk == 1 && where == 0 && !force && !reverse_seen) {
1899 /* dwim for reversed patch? */
1902 say("Not enough memory to try swapped hunk! Assuming unswapped.\n");
1907 where = locate_hunk(fuzz);
1909 /* didn't find it swapped */
1911 /* put it back to normal */
1912 fatal("lost hunk on alloc error!\n");
1914 } else if (noreverse) {
1916 /* put it back to normal */
1917 fatal("lost hunk on alloc error!\n");
1919 say("Ignoring previously applied (or reversed) patch.\n");
1920 skip_rest_of_patch = true;
1922 if (verbosity != SILENT)
1923 say("%seversed (or previously applied) patch detected! %s -R.",
1924 reverse ? "R" : "Unr",
1925 reverse ? "Assuming" : "Ignoring");
1927 ask("%seversed (or previously applied) patch detected! %s -R? [y] ",
1928 reverse ? "R" : "Unr",
1929 reverse ? "Assume" : "Ignore");
1931 ask("Apply anyway? [n] ");
1933 skip_rest_of_patch = true;
1935 reverse_seen = true;
1939 /* put it back to normal */
1940 fatal("lost hunk on alloc error!\n");
1944 } while (!skip_rest_of_patch && where == 0 &&
1945 ++fuzz <= mymaxfuzz);
1947 if (skip_rest_of_patch) { /* just got decided */
1948 if (ferror(ofp) || fclose(ofp)) {
1949 say("Error writing %s\n",
1956 newwhere = pch_newfirst() + last_offset;
1957 if (skip_rest_of_patch) {
1960 if (verbosity != SILENT)
1961 say("Hunk #%d ignored at %ld.\n",
1963 } else if (where == 0) {
1966 if (verbosity != SILENT)
1967 say("Hunk #%d failed at %ld.\n",
1971 if (verbosity == VERBOSE
1972 || (verbosity != SILENT && (fuzz != 0 || last_offset)))
1974 say("Hunk #%d succeeded at %ld",
1977 say(" with fuzz %ld", fuzz);
1979 say(" (offset %ld line%s)",
1981 last_offset == 1L ? "" : "s");
1987 if (out_of_mem && using_plan_a) {
1990 say("\n\nRan out of memory using Plan A--trying again...\n\n");
2000 fatal("Internal error: hunk should not be 0\n");
2002 /* finish spewing out the new file */
2003 if (!skip_rest_of_patch && !spew_output()) {
2004 say("Can't write %s\n", TMPOUTNAME);
2008 /* and put the output where desired */
2010 if (!skip_rest_of_patch) {
2011 struct stat statbuf;
2012 char *realout = outname;
2015 if (move_file(TMPOUTNAME, outname) < 0) {
2017 realout = TMPOUTNAME;
2018 chmod(TMPOUTNAME, filemode);
2020 chmod(outname, filemode);
2022 if (remove_empty_files &&
2023 stat(realout, &statbuf) == 0 &&
2024 statbuf.st_size == 0) {
2025 if (verbosity == VERBOSE)
2026 say("Removing %s (empty after patching).\n",
2032 if (ferror(rejfp) || fclose(rejfp)) {
2033 say("Error writing %s\n", rejname);
2039 if (*rejname == '\0') {
2040 if (strlcpy(rejname, outname,
2041 sizeof(rejname)) >= sizeof(rejname))
2042 fatal("filename %s is too long\n", outname);
2043 if (strlcat(rejname, REJEXT,
2044 sizeof(rejname)) >= sizeof(rejname))
2045 fatal("filename %s is too long\n", outname);
2048 say("%d out of %d hunks %s--saving rejects to %s\n",
2049 failed, hunk, skip_rest_of_patch ? "ignored" : "failed", rejname);
2051 say("%d out of %d hunks %s while patching %s\n",
2052 failed, hunk, skip_rest_of_patch ? "ignored" : "failed", filearg[0]);
2053 if (!check_only && move_file(TMPREJNAME, rejname) < 0)
2066 /* Prepare to find the next patch to do in the patch file. */
2069 reinitialize_almost_everything(void)
2075 last_frozen_line = 0;
2092 reverse = reverse_flag_specified;
2093 skip_rest_of_patch = false;
2095 get_some_switches();
2098 /* Process switches and filenames. */
2101 get_some_switches(void)
2103 const char *options = "b::B:cCd:D:eEfF:i:lnNo:p:r:RstuvV:x:z:";
2104 static struct option longopts[] = {
2105 {"backup", no_argument, 0, 'b'},
2106 {"batch", no_argument, 0, 't'},
2107 {"check", no_argument, 0, 'C'},
2108 {"context", no_argument, 0, 'c'},
2109 {"debug", required_argument, 0, 'x'},
2110 {"directory", required_argument, 0, 'd'},
2111 {"dry-run", no_argument, 0, 'C'},
2112 {"ed", no_argument, 0, 'e'},
2113 {"force", no_argument, 0, 'f'},
2114 {"forward", no_argument, 0, 'N'},
2115 {"fuzz", required_argument, 0, 'F'},
2116 {"ifdef", required_argument, 0, 'D'},
2117 {"input", required_argument, 0, 'i'},
2118 {"ignore-whitespace", no_argument, 0, 'l'},
2119 {"normal", no_argument, 0, 'n'},
2120 {"output", required_argument, 0, 'o'},
2121 {"prefix", required_argument, 0, 'B'},
2122 {"quiet", no_argument, 0, 's'},
2123 {"reject-file", required_argument, 0, 'r'},
2124 {"remove-empty-files", no_argument, 0, 'E'},
2125 {"reverse", no_argument, 0, 'R'},
2126 {"silent", no_argument, 0, 's'},
2127 {"strip", required_argument, 0, 'p'},
2128 {"suffix", required_argument, 0, 'z'},
2129 {"unified", no_argument, 0, 'u'},
2130 {"version", no_argument, 0, 'v'},
2131 {"version-control", required_argument, 0, 'V'},
2132 {"posix", no_argument, &posix, 1},
2133 {"verbose", no_argument, 0, 2},
2144 optreset = optind = 1;
2146 while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
2149 verbosity = VERBOSE;
2152 if (backup_type == none)
2153 backup_type = numbered_existing;
2156 if (verbosity != SILENT)
2157 say("Warning, the ``-b suffix'' option has been"
2158 " obsoleted by the -z option.\n");
2161 /* must directly follow 'b' case for backwards compat */
2162 simple_backup_suffix = xstrdup(optarg);
2165 origprae = xstrdup(optarg);
2168 diff_type = CONTEXT_DIFF;
2174 if (chdir(optarg) < 0)
2175 pfatal("can't cd to %s", optarg);
2179 if (!isalpha((unsigned char)*optarg) && *optarg != '_')
2180 fatal("argument to -D is not an identifier\n");
2181 snprintf(if_defined, sizeof if_defined,
2182 "#ifdef %s\n", optarg);
2183 snprintf(not_defined, sizeof not_defined,
2184 "#ifndef %s\n", optarg);
2185 snprintf(end_defined, sizeof end_defined,
2186 "#endif /* %s */\n", optarg);
2189 diff_type = ED_DIFF;
2192 remove_empty_files = true;
2198 maxfuzz = atoi(optarg);
2201 if (++filec == MAXFILEC)
2202 fatal("too many file arguments\n");
2203 filearg[filec] = xstrdup(optarg);
2206 canonicalize = true;
2209 diff_type = NORMAL_DIFF;
2215 outname = xstrdup(optarg);
2218 strippath = atoi(optarg);
2221 if (strlcpy(rejname, optarg,
2222 sizeof(rejname)) >= sizeof(rejname))
2223 fatal("argument for -r is too long\n");
2227 reverse_flag_specified = true;
2236 diff_type = UNI_DIFF;
2242 backup_type = get_version(optarg);
2247 debug = atoi(optarg);
2260 filearg[0] = xstrdup(*Argv++);
2263 if (++filec == MAXFILEC)
2264 fatal("too many file arguments\n");
2265 filearg[filec] = xstrdup(*Argv++);
2270 if (getenv("POSIXLY_CORRECT") != NULL)
2278 "usage: patch [-bCcEeflNnRstuv] [-B backup-prefix] [-D symbol] [-d directory]\n"
2279 " [-F max-fuzz] [-i patchfile] [-o out-file] [-p strip-count]\n"
2280 " [-r rej-name] [-V t | nil | never | none] [-x number]\n"
2281 " [-z backup-ext] [--posix] [origfile [patchfile]]\n"
2282 " patch <patchfile\n");
2283 my_exit(EXIT_FAILURE);
2287 * Attempt to find the right place to apply this hunk of patch.
2290 locate_hunk(LINENUM fuzz)
2292 LINENUM first_guess = pch_first() + last_offset;
2294 LINENUM pat_lines = pch_ptrn_lines();
2295 LINENUM max_pos_offset = input_lines - first_guess - pat_lines + 1;
2296 LINENUM max_neg_offset = first_guess - last_frozen_line - 1 + pch_context();
2298 if (pat_lines == 0) { /* null range matches always */
2299 if (verbosity == VERBOSE && fuzz == 0 && (diff_type == CONTEXT_DIFF
2300 || diff_type == NEW_CONTEXT_DIFF
2301 || diff_type == UNI_DIFF)) {
2302 say("Empty context always matches.\n");
2304 return (first_guess);
2306 if (max_neg_offset >= first_guess) /* do not try lines < 0 */
2307 max_neg_offset = first_guess - 1;
2308 if (first_guess <= input_lines && patch_match(first_guess, 0, fuzz))
2310 for (offset = 1; ; offset++) {
2311 bool check_after = (offset <= max_pos_offset);
2312 bool check_before = (offset <= max_neg_offset);
2314 if (check_after && patch_match(first_guess, offset, fuzz)) {
2317 say("Offset changing from %ld to %ld\n",
2318 last_offset, offset);
2320 last_offset = offset;
2321 return first_guess + offset;
2322 } else if (check_before && patch_match(first_guess, -offset, fuzz)) {
2325 say("Offset changing from %ld to %ld\n",
2326 last_offset, -offset);
2328 last_offset = -offset;
2329 return first_guess - offset;
2330 } else if (!check_before && !check_after)
2335 /* We did not find the pattern, dump out the hunk so they can handle it. */
2338 abort_context_hunk(void)
2341 const LINENUM pat_end = pch_end();
2343 * add in last_offset to guess the same as the previous successful
2346 const LINENUM oldfirst = pch_first() + last_offset;
2347 const LINENUM newfirst = pch_newfirst() + last_offset;
2348 const LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
2349 const LINENUM newlast = newfirst + pch_repl_lines() - 1;
2350 const char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : "");
2351 const char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----");
2353 fprintf(rejfp, "***************\n");
2354 for (i = 0; i <= pat_end; i++) {
2355 switch (pch_char(i)) {
2357 if (oldlast < oldfirst)
2358 fprintf(rejfp, "*** 0%s\n", stars);
2359 else if (oldlast == oldfirst)
2360 fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
2362 fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst,
2366 if (newlast < newfirst)
2367 fprintf(rejfp, "--- 0%s\n", minuses);
2368 else if (newlast == newfirst)
2369 fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
2371 fprintf(rejfp, "--- %ld,%ld%s\n", newfirst,
2375 fprintf(rejfp, "%s", pfetch(i));
2381 fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
2384 fatal("fatal internal error in abort_context_hunk\n");
2390 rej_line(int ch, LINENUM i)
2393 const char *line = pfetch(i);
2397 fprintf(rejfp, "%c%s", ch, line);
2398 if (len == 0 || line[len - 1] != '\n') {
2399 if (len >= USHRT_MAX)
2400 fprintf(rejfp, "\n\\ Line too long\n");
2402 fprintf(rejfp, "\n\\ No newline at end of line\n");
2409 LINENUM i, j, split;
2411 const LINENUM pat_end = pch_end();
2412 const LINENUM oldfirst = pch_first() + last_offset;
2413 const LINENUM newfirst = pch_newfirst() + last_offset;
2415 if (diff_type != UNI_DIFF) {
2416 abort_context_hunk();
2420 for (i = 0; i <= pat_end; i++) {
2421 if (pch_char(i) == '=') {
2427 fprintf(rejfp, "malformed hunk: no split found\n");
2432 fprintf(rejfp, "@@ -%ld,%ld +%ld,%ld @@\n",
2433 pch_ptrn_lines() ? oldfirst : 0,
2434 pch_ptrn_lines(), newfirst, pch_repl_lines());
2435 while (i < split || j <= pat_end) {
2436 ch1 = i < split ? pch_char(i) : -1;
2437 ch2 = j <= pat_end ? pch_char(j) : -1;
2441 } else if (ch1 == ' ' && ch2 == ' ') {
2445 } else if (ch1 == '!' && ch2 == '!') {
2446 while (i < split && ch1 == '!') {
2449 ch1 = i < split ? pch_char(i) : -1;
2451 while (j <= pat_end && ch2 == '!') {
2454 ch2 = j <= pat_end ? pch_char(j) : -1;
2456 } else if (ch1 == '*') {
2458 } else if (ch2 == '+' || ch2 == ' ') {
2462 fprintf(rejfp, "internal error on (%ld %ld %ld)\n",
2471 /* We found where to apply it (we hope), so do it. */
2474 apply_hunk(LINENUM where)
2477 const LINENUM lastline = pch_ptrn_lines();
2478 LINENUM new = lastline + 1;
2483 int def_state = OUTSIDE;
2484 const LINENUM pat_end = pch_end();
2487 while (pch_char(new) == '=' || pch_char(new) == '\n')
2490 while (old <= lastline) {
2491 if (pch_char(old) == '-') {
2492 copy_till(where + old - 1, false);
2494 if (def_state == OUTSIDE) {
2495 fputs(not_defined, ofp);
2496 def_state = IN_IFNDEF;
2497 } else if (def_state == IN_IFDEF) {
2498 fputs(else_defined, ofp);
2499 def_state = IN_ELSE;
2501 fputs(pfetch(old), ofp);
2505 } else if (new > pat_end) {
2507 } else if (pch_char(new) == '+') {
2508 copy_till(where + old - 1, false);
2510 if (def_state == IN_IFNDEF) {
2511 fputs(else_defined, ofp);
2512 def_state = IN_ELSE;
2513 } else if (def_state == OUTSIDE) {
2514 fputs(if_defined, ofp);
2515 def_state = IN_IFDEF;
2518 fputs(pfetch(new), ofp);
2520 } else if (pch_char(new) != pch_char(old)) {
2521 say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
2522 pch_hunk_beg() + old,
2523 pch_hunk_beg() + new);
2525 say("oldchar = '%c', newchar = '%c'\n",
2526 pch_char(old), pch_char(new));
2529 } else if (pch_char(new) == '!') {
2530 copy_till(where + old - 1, false);
2532 fputs(not_defined, ofp);
2533 def_state = IN_IFNDEF;
2535 while (pch_char(old) == '!') {
2537 fputs(pfetch(old), ofp);
2543 fputs(else_defined, ofp);
2544 def_state = IN_ELSE;
2546 while (pch_char(new) == '!') {
2547 fputs(pfetch(new), ofp);
2551 if (pch_char(new) != ' ')
2552 fatal("Internal error: expected ' '\n");
2555 if (do_defines && def_state != OUTSIDE) {
2556 fputs(end_defined, ofp);
2557 def_state = OUTSIDE;
2561 if (new <= pat_end && pch_char(new) == '+') {
2562 copy_till(where + old - 1, false);
2564 if (def_state == OUTSIDE) {
2565 fputs(if_defined, ofp);
2566 def_state = IN_IFDEF;
2567 } else if (def_state == IN_IFNDEF) {
2568 fputs(else_defined, ofp);
2569 def_state = IN_ELSE;
2572 while (new <= pat_end && pch_char(new) == '+') {
2573 fputs(pfetch(new), ofp);
2577 if (do_defines && def_state != OUTSIDE) {
2578 fputs(end_defined, ofp);
2583 * Open the new file.
2586 init_output(const char *name)
2588 ofp = fopen(name, "w");
2590 pfatal("can't create %s", name);
2594 * Open a file to put hunks we can't locate.
2597 init_reject(const char *name)
2599 rejfp = fopen(name, "w");
2601 pfatal("can't create %s", name);
2605 * Copy input file to output, up to wherever hunk is to be applied.
2606 * If endoffile is true, treat the last line specially since it may
2610 copy_till(LINENUM lastline, bool endoffile)
2612 if (last_frozen_line > lastline)
2613 fatal("misordered hunks! output would be garbled\n");
2614 while (last_frozen_line < lastline) {
2615 if (++last_frozen_line == lastline && endoffile)
2616 dump_line(last_frozen_line, !last_line_missing_eol);
2618 dump_line(last_frozen_line, true);
2623 * Finish copying the input file to the output file.
2632 say("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
2635 copy_till(input_lines, true); /* dump remainder of file */
2636 rv = ferror(ofp) == 0 && fclose(ofp) == 0;
2642 * Copy one line from input to output.
2645 dump_line(LINENUM line, bool write_newline)
2649 s = ifetch(line, 0);
2652 /* Note: string is not NUL terminated. */
2653 for (; *s != '\n'; s++)
2660 * Does the patch pattern match at line base+offset?
2663 patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
2665 LINENUM pline = 1 + fuzz;
2667 LINENUM pat_lines = pch_ptrn_lines() - fuzz;
2668 const char *ilineptr;
2669 const char *plineptr;
2670 unsigned short plinelen;
2672 for (iline = base + offset + fuzz; pline <= pat_lines; pline++, iline++) {
2673 ilineptr = ifetch(iline, offset >= 0);
2674 if (ilineptr == NULL)
2676 plineptr = pfetch(pline);
2677 plinelen = pch_line_len(pline);
2679 if (!similar(ilineptr, plineptr, plinelen))
2681 } else if (strnNE(ilineptr, plineptr, plinelen))
2683 if (iline == input_lines) {
2685 * We are looking at the last line of the file.
2686 * If the file has no eol, the patch line should
2687 * not have one either and vice-versa. Note that
2690 if (last_line_missing_eol) {
2691 if (plineptr[plinelen - 1] == '\n')
2694 if (plineptr[plinelen - 1] != '\n')
2703 * Do two lines match with canonicalized white space?
2706 similar(const char *a, const char *b, int len)
2709 if (isspace((unsigned char)*b)) { /* whitespace (or \n) to match? */
2710 if (!isspace((unsigned char)*a)) /* no corresponding whitespace? */
2712 while (len && isspace((unsigned char)*b) && *b != '\n')
2713 b++, len--; /* skip pattern whitespace */
2714 while (isspace((unsigned char)*a) && *a != '\n')
2715 a++; /* skip target whitespace */
2716 if (*a == '\n' || *b == '\n')
2717 return (*a == *b); /* should end in sync */
2718 } else if (*a++ != *b++) /* match non-whitespace chars */
2721 len--; /* probably not necessary */
2723 return true; /* actually, this is not reached */
2724 /* since there is always a \n */
2728 [FILE:49:files/pathnames.h]
2730 #define _PATH_RED "/bin/red"
2733 [FILE:39374:files/pch.c]
2734 #include <sys/types.h>
2735 #include <sys/stat.h>
2749 #include "pathnames.h"
2751 /* Patch (diff listing) abstract type. */
2753 static off_t p_filesize; /* size of the patch file */
2754 static LINENUM p_first; /* 1st line number */
2755 static LINENUM p_newfirst; /* 1st line number of replacement */
2756 static LINENUM p_ptrn_lines; /* # lines in pattern */
2757 static LINENUM p_repl_lines; /* # lines in replacement text */
2758 static LINENUM p_end = -1; /* last line in hunk */
2759 static LINENUM p_max; /* max allowed value of p_end */
2760 static LINENUM p_context = 3; /* # of context lines */
2761 static LINENUM p_input_line = 0; /* current line # from patch file */
2762 static char **p_line = NULL;/* the text of the hunk */
2763 static unsigned short *p_len = NULL; /* length of each line */
2764 static char *p_char = NULL; /* +, -, and ! */
2765 static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */
2766 static int p_indent; /* indent to patch */
2767 static off_t p_base; /* where to intuit this time */
2768 static LINENUM p_bline; /* line # of p_base */
2769 static off_t p_start; /* where intuit found a patch */
2770 static LINENUM p_sline; /* and the line number for it */
2771 static LINENUM p_hunk_beg; /* line number of current hunk */
2772 static LINENUM p_efake = -1; /* end of faked up lines--don't free */
2773 static LINENUM p_bfake = -1; /* beg of faked up lines */
2774 static FILE *pfp = NULL; /* patch file pointer */
2775 static char *bestguess = NULL; /* guess at correct filename */
2777 static void grow_hunkmax(void);
2778 static int intuit_diff_type(void);
2779 static void next_intuit_at(off_t, LINENUM);
2780 static void skip_to(off_t, LINENUM);
2781 static size_t pgets(bool _do_indent);
2782 static char *best_name(const struct file_name *, bool);
2783 static char *posix_name(const struct file_name *, bool);
2784 static size_t num_components(const char *);
2785 static LINENUM strtolinenum(char *, char **);
2788 * Prepare to look for the next patch in the patch file.
2797 p_end = (LINENUM) - 1;
2803 * Open the patch file at the beginning of time.
2806 open_patch_file(const char *filename)
2808 struct stat filestat;
2811 if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) {
2812 pfp = fopen(TMPPATNAME, "w");
2814 pfatal("can't create %s", TMPPATNAME);
2815 while ((nr = fread(buf, 1, buf_size, stdin)) > 0) {
2816 nw = fwrite(buf, 1, nr, pfp);
2818 pfatal("write error to %s", TMPPATNAME);
2820 if (ferror(pfp) || fclose(pfp))
2821 pfatal("can't write %s", TMPPATNAME);
2822 filename = TMPPATNAME;
2824 pfp = fopen(filename, "r");
2826 pfatal("patch file %s not found", filename);
2827 if (fstat(fileno(pfp), &filestat))
2828 pfatal("can't stat %s", filename);
2829 p_filesize = filestat.st_size;
2830 next_intuit_at(0, 1L); /* start at the beginning */
2835 * Make sure our dynamically realloced tables are malloced to begin with.
2841 p_line = malloc(hunkmax * sizeof(char *));
2843 p_len = malloc(hunkmax * sizeof(unsigned short));
2845 p_char = malloc(hunkmax * sizeof(char));
2849 * Enlarge the arrays containing the current hunk of patch.
2854 int new_hunkmax = hunkmax * 2;
2856 if (p_line == NULL || p_len == NULL || p_char == NULL)
2857 fatal("Internal memory allocation error\n");
2859 p_line = reallocf(p_line, new_hunkmax * sizeof(char *));
2860 p_len = reallocf(p_len, new_hunkmax * sizeof(unsigned short));
2861 p_char = reallocf(p_char, new_hunkmax * sizeof(char));
2863 if (p_line != NULL && p_len != NULL && p_char != NULL) {
2864 hunkmax = new_hunkmax;
2869 fatal("out of memory\n");
2870 out_of_mem = true; /* whatever is null will be allocated again */
2871 /* from within plan_a(), of all places */
2874 /* True if the remainder of the patch file contains a diff of some sort. */
2877 there_is_another_patch(void)
2879 bool exists = false;
2881 if (p_base != 0 && p_base >= p_filesize) {
2882 if (verbosity == VERBOSE)
2886 if (verbosity == VERBOSE)
2888 diff_type = intuit_diff_type();
2891 if (verbosity == VERBOSE)
2892 say(" Ignoring the trailing garbage.\ndone\n");
2894 say(" I can't seem to find a patch in there anywhere.\n");
2897 if (verbosity == VERBOSE)
2898 say(" %sooks like %s to me...\n",
2899 (p_base == 0 ? "L" : "The next patch l"),
2900 diff_type == UNI_DIFF ? "a unified diff" :
2901 diff_type == CONTEXT_DIFF ? "a context diff" :
2902 diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
2903 diff_type == NORMAL_DIFF ? "a normal diff" :
2905 if (p_indent && (verbosity == VERBOSE))
2906 say("(Patch is indented %d space%s.)\n", p_indent,
2907 p_indent == 1 ? "" : "s");
2908 skip_to(p_start, p_sline);
2909 while (filearg[0] == NULL) {
2910 if (force || batch) {
2911 say("No file to patch. Skipping...\n");
2912 filearg[0] = xstrdup(bestguess);
2913 skip_rest_of_patch = true;
2916 ask("File to patch: ");
2919 bestguess = xstrdup(buf);
2920 filearg[0] = fetchname(buf, &exists, 0);
2923 int def_skip = *bestguess == '\0';
2924 ask("No file found--skip this patch? [%c] ",
2925 def_skip ? 'y' : 'n');
2926 if (*buf == 'n' || (!def_skip && *buf != 'y'))
2928 if (verbosity != SILENT)
2929 say("Skipping patch...\n");
2931 filearg[0] = fetchname(bestguess, &exists, 0);
2932 skip_rest_of_patch = true;
2940 p4_fetchname(struct file_name *name, char *str)
2944 /* Skip leading whitespace. */
2945 while (isspace((unsigned char)*str))
2948 /* Remove the file revision number. */
2949 for (t = str, h = NULL; *t != '\0' && !isspace((unsigned char)*t); t++)
2955 name->path = fetchname(str, &name->exists, strippath);
2958 /* Determine what kind of diff is in the remaining part of the patch file. */
2961 intuit_diff_type(void)
2963 off_t this_line = 0, previous_line;
2964 off_t first_command_line = -1;
2965 LINENUM fcl_line = -1;
2966 bool last_line_was_command = false, this_is_a_command = false;
2967 bool stars_last_line = false, stars_this_line = false;
2970 struct file_name names[MAX_FILE];
2971 int piece_of_git = 0;
2973 memset(names, 0, sizeof(names));
2974 ok_to_create_file = false;
2975 fseeko(pfp, p_base, SEEK_SET);
2976 p_input_line = p_bline - 1;
2978 previous_line = this_line;
2979 last_line_was_command = this_is_a_command;
2980 stars_last_line = stars_this_line;
2981 this_line = ftello(pfp);
2984 if (pgets(false) == 0) {
2985 if (first_command_line >= 0) {
2986 /* nothing but deletes!? */
2987 p_start = first_command_line;
2992 p_start = this_line;
2993 p_sline = p_input_line;
2998 for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
3000 indent += 8 - (indent % 8);
3004 for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)
3006 this_is_a_command = (isdigit((unsigned char)*s) &&
3007 (*t == 'd' || *t == 'c' || *t == 'a'));
3008 if (first_command_line < 0 && this_is_a_command) {
3009 first_command_line = this_line;
3010 fcl_line = p_input_line;
3011 p_indent = indent; /* assume this for now */
3013 if (!stars_last_line && strnEQ(s, "*** ", 4))
3014 names[OLD_FILE].path = fetchname(s + 4,
3015 &names[OLD_FILE].exists, strippath);
3016 else if (strnEQ(s, "--- ", 4)) {
3018 if (piece_of_git && strippath == 957)
3020 names[NEW_FILE].path = fetchname(s + off,
3021 &names[NEW_FILE].exists, strippath);
3022 } else if (strnEQ(s, "+++ ", 4)) {
3023 /* pretend it is the old name */
3025 if (piece_of_git && strippath == 957)
3027 names[OLD_FILE].path = fetchname(s + off,
3028 &names[OLD_FILE].exists, strippath);
3029 } else if (strnEQ(s, "Index:", 6))
3030 names[INDEX_FILE].path = fetchname(s + 6,
3031 &names[INDEX_FILE].exists, strippath);
3032 else if (strnEQ(s, "Prereq:", 7)) {
3033 for (t = s + 7; isspace((unsigned char)*t); t++)
3035 revision = xstrdup(t);
3037 *t && !isspace((unsigned char)*t); t++)
3040 if (*revision == '\0') {
3044 } else if (strnEQ(s, "diff --git a/", 13)) {
3045 /* Git-style diffs. */
3047 } else if (strnEQ(s, "==== ", 5)) {
3048 /* Perforce-style diffs. */
3049 if ((t = strstr(s + 5, " - ")) != NULL)
3050 p4_fetchname(&names[NEW_FILE], t + 3);
3051 p4_fetchname(&names[OLD_FILE], s + 5);
3053 if ((!diff_type || diff_type == ED_DIFF) &&
3054 first_command_line >= 0 &&
3057 p_start = first_command_line;
3062 if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
3063 if (strnEQ(s + 4, "0,0", 3))
3064 ok_to_create_file = true;
3066 p_start = this_line;
3067 p_sline = p_input_line;
3071 stars_this_line = strnEQ(s, "********", 8);
3072 if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
3073 strnEQ(s, "*** ", 4)) {
3074 if (strtolinenum(s + 4, &s) == 0)
3075 ok_to_create_file = true;
3077 * If this is a new context diff the character just
3078 * at the end of the line is a '*'.
3080 while (*s && *s != '\n')
3083 p_start = previous_line;
3084 p_sline = p_input_line - 1;
3085 retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
3088 if ((!diff_type || diff_type == NORMAL_DIFF) &&
3089 last_line_was_command &&
3090 (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) {
3091 p_start = previous_line;
3092 p_sline = p_input_line - 1;
3094 retval = NORMAL_DIFF;
3099 if (retval == UNI_DIFF) {
3100 /* unswap old and new */
3101 struct file_name tmp = names[OLD_FILE];
3102 names[OLD_FILE] = names[NEW_FILE];
3103 names[NEW_FILE] = tmp;
3105 if (filearg[0] == NULL) {
3107 filearg[0] = posix_name(names, ok_to_create_file);
3109 /* Ignore the Index: name for context diffs, like GNU */
3110 if (names[OLD_FILE].path != NULL ||
3111 names[NEW_FILE].path != NULL) {
3112 free(names[INDEX_FILE].path);
3113 names[INDEX_FILE].path = NULL;
3115 filearg[0] = best_name(names, ok_to_create_file);
3121 if (filearg[0] != NULL)
3122 bestguess = xstrdup(filearg[0]);
3123 else if (!ok_to_create_file) {
3125 * We don't want to create a new file but we need a
3126 * filename to set bestguess. Avoid setting filearg[0]
3127 * so the file is not created automatically.
3130 bestguess = posix_name(names, true);
3132 bestguess = best_name(names, true);
3134 free(names[OLD_FILE].path);
3135 free(names[NEW_FILE].path);
3136 free(names[INDEX_FILE].path);
3141 * Remember where this patch ends so we know where to start up again.
3144 next_intuit_at(off_t file_pos, LINENUM file_line)
3147 p_bline = file_line;
3151 * Basically a verbose fseeko() to the actual diff listing.
3154 skip_to(off_t file_pos, LINENUM file_line)
3158 if (p_base > file_pos)
3159 fatal("Internal error: seek %lld>%lld\n",
3160 (long long)p_base, (long long)file_pos);
3161 if (verbosity == VERBOSE && p_base < file_pos) {
3162 fseeko(pfp, p_base, SEEK_SET);
3163 say("The text leading up to this was:\n--------------------------\n");
3164 while (ftello(pfp) < file_pos) {
3167 fatal("Unexpected end of file\n");
3170 say("--------------------------\n");
3172 fseeko(pfp, file_pos, SEEK_SET);
3173 p_input_line = file_line - 1;
3176 /* Make this a function for better debugging. */
3180 fatal("malformed patch at line %ld: %s", p_input_line, buf);
3181 /* about as informative as "Syntax error" in C */
3185 * True if the line has been discarded (i.e. it is a line saying
3186 * "\ No newline at end of file".)
3189 remove_special_line(void)
3197 } while (c != EOF && c != '\n');
3202 fseeko(pfp, -1, SEEK_CUR);
3208 * True if there is more of the current diff listing to process.
3213 off_t line_beginning; /* file pos of the current line */
3214 LINENUM repl_beginning; /* index of --- line */
3215 LINENUM fillcnt; /* #lines of missing ptrn or repl */
3216 LINENUM fillsrc; /* index of first line to copy */
3217 LINENUM filldst; /* index of first missing line */
3218 bool ptrn_spaces_eaten; /* ptrn was slightly malformed */
3219 bool repl_could_be_missing; /* no + or ! lines in this hunk */
3220 bool repl_missing; /* we are now backtracking */
3221 off_t repl_backtrack_position; /* file pos of first repl line */
3222 LINENUM repl_patch_line; /* input line number for same */
3223 LINENUM ptrn_copiable; /* # of copiable lines in ptrn */
3228 while (p_end >= 0) {
3229 if (p_end == p_efake)
3230 p_end = p_bfake; /* don't free twice */
3232 free(p_line[p_end]);
3237 p_max = hunkmax; /* gets reduced when --- found */
3238 if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
3239 line_beginning = ftello(pfp);
3244 ptrn_spaces_eaten = false;
3245 repl_could_be_missing = true;
3246 repl_missing = false;
3247 repl_backtrack_position = 0;
3248 repl_patch_line = 0;
3253 if (len == 0 || strnNE(buf, "********", 8)) {
3254 next_intuit_at(line_beginning, p_input_line);
3258 p_hunk_beg = p_input_line + 1;
3259 while (p_end < p_max) {
3260 line_beginning = ftello(pfp);
3264 if (p_max - p_end < 4) {
3265 /* assume blank lines got chopped */
3266 strlcpy(buf, " \n", buf_size);
3268 if (repl_beginning && repl_could_be_missing) {
3269 repl_missing = true;
3272 fatal("unexpected end of file in patch\n");
3276 if (p_end >= hunkmax)
3277 fatal("Internal error: hunk larger than hunk "
3279 p_char[p_end] = *buf;
3280 p_line[p_end] = NULL;
3283 if (strnEQ(buf, "********", 8)) {
3284 if (repl_beginning && repl_could_be_missing) {
3285 repl_missing = true;
3288 fatal("unexpected end of hunk "
3293 if (repl_beginning && repl_could_be_missing) {
3294 repl_missing = true;
3297 fatal("unexpected *** at line %ld: %s",
3301 p_line[p_end] = savestr(buf);
3307 *s && !isdigit((unsigned char)*s); s++)
3311 if (strnEQ(s, "0,0", 3))
3312 memmove(s, s + 2, strlen(s + 2) + 1);
3313 p_first = strtolinenum(s, &s);
3316 *s && !isdigit((unsigned char)*s); s++)
3320 p_ptrn_lines = strtolinenum(s, &s) - p_first + 1;
3321 if (p_ptrn_lines < 0)
3329 if (p_first >= LINENUM_MAX - p_ptrn_lines ||
3330 p_ptrn_lines >= LINENUM_MAX - 6)
3333 /* we need this much at least */
3334 p_max = p_ptrn_lines + 6;
3335 while (p_max >= hunkmax)
3340 if (buf[1] == '-') {
3341 if (repl_beginning ||
3342 (p_end != p_ptrn_lines + 1 +
3343 (p_char[p_end - 1] == '\n'))) {
3346 * `old' lines were omitted;
3347 * set up to fill them in
3348 * from 'new' context lines.
3350 p_end = p_ptrn_lines + 1;
3351 fillsrc = p_end + 1;
3353 fillcnt = p_ptrn_lines;
3355 if (repl_beginning) {
3356 if (repl_could_be_missing) {
3357 repl_missing = true;
3360 fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n",
3361 p_input_line, p_hunk_beg + repl_beginning);
3363 fatal("%s \"---\" at line %ld--check line numbers at line %ld\n",
3364 (p_end <= p_ptrn_lines
3367 p_input_line, p_hunk_beg);
3371 repl_beginning = p_end;
3372 repl_backtrack_position = ftello(pfp);
3373 repl_patch_line = p_input_line;
3374 p_line[p_end] = savestr(buf);
3379 p_char[p_end] = '=';
3380 for (s = buf; *s && !isdigit((unsigned char)*s); s++)
3384 p_newfirst = strtolinenum(s, &s);
3386 for (; *s && !isdigit((unsigned char)*s); s++)
3390 p_repl_lines = strtolinenum(s, &s) -
3392 if (p_repl_lines < 0)
3394 } else if (p_newfirst)
3400 if (p_newfirst >= LINENUM_MAX - p_repl_lines ||
3401 p_repl_lines >= LINENUM_MAX - p_end)
3403 p_max = p_repl_lines + p_end;
3404 if (p_max > MAXHUNKSIZE)
3405 fatal("hunk too large (%ld lines) at line %ld: %s",
3406 p_max, p_input_line, buf);
3407 while (p_max >= hunkmax)
3409 if (p_repl_lines != ptrn_copiable &&
3410 (p_context != 0 || p_repl_lines != 1))
3411 repl_could_be_missing = false;
3417 repl_could_be_missing = false;
3419 if (buf[1] == '\n' && canonicalize)
3420 strlcpy(buf + 1, " \n", buf_size - 1);
3421 if (!isspace((unsigned char)buf[1]) &&
3422 buf[1] != '>' && buf[1] != '<' &&
3423 repl_beginning && repl_could_be_missing) {
3424 repl_missing = true;
3428 if (context < p_context)
3429 p_context = context;
3432 p_line[p_end] = savestr(buf + 2);
3437 if (p_end == p_ptrn_lines) {
3438 if (remove_special_line()) {
3441 l = strlen(p_line[p_end]) - 1;
3442 (p_line[p_end])[l] = 0;
3447 case '\n': /* assume the 2 spaces got eaten */
3448 if (repl_beginning && repl_could_be_missing &&
3449 (!ptrn_spaces_eaten ||
3450 diff_type == NEW_CONTEXT_DIFF)) {
3451 repl_missing = true;
3454 p_line[p_end] = savestr(buf);
3459 if (p_end != p_ptrn_lines + 1) {
3460 ptrn_spaces_eaten |= (repl_beginning != 0);
3462 if (!repl_beginning)
3464 p_char[p_end] = ' ';
3468 if (!isspace((unsigned char)buf[1]) &&
3469 repl_beginning && repl_could_be_missing) {
3470 repl_missing = true;
3474 if (!repl_beginning)
3476 p_line[p_end] = savestr(buf + 2);
3483 if (repl_beginning && repl_could_be_missing) {
3484 repl_missing = true;
3489 /* set up p_len for strncmp() so we don't have to */
3490 /* assume null termination */
3492 p_len[p_end] = strlen(p_line[p_end]);
3498 if (p_end >= 0 && !repl_beginning)
3499 fatal("no --- found in patch at line %ld\n", pch_hunk_beg());
3503 /* reset state back to just after --- */
3504 p_input_line = repl_patch_line;
3505 for (p_end--; p_end > repl_beginning; p_end--)
3506 free(p_line[p_end]);
3507 fseeko(pfp, repl_backtrack_position, SEEK_SET);
3509 /* redundant 'new' context lines were omitted - set */
3510 /* up to fill them in from the old file context */
3511 if (!p_context && p_repl_lines == 1) {
3516 filldst = repl_beginning + 1;
3517 fillcnt = p_repl_lines;
3519 } else if (!p_context && fillcnt == 1) {
3520 /* the first hunk was a null hunk with no context */
3521 /* and we were expecting one line -- fix it up. */
3522 while (filldst < p_end) {
3523 p_line[filldst] = p_line[filldst + 1];
3524 p_char[filldst] = p_char[filldst + 1];
3525 p_len[filldst] = p_len[filldst + 1];
3529 repl_beginning--; /* this doesn't need to be fixed */
3532 p_first++; /* do append rather than insert */
3536 if (diff_type == CONTEXT_DIFF &&
3537 (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) {
3538 if (verbosity == VERBOSE)
3540 "(Fascinating--this is really a new-style context diff but without",
3541 "the telltale extra asterisks on the *** line that usually indicate",
3542 "the new style...)");
3543 diff_type = NEW_CONTEXT_DIFF;
3545 /* if there were omitted context lines, fill them in now */
3547 p_bfake = filldst; /* remember where not to free() */
3548 p_efake = filldst + fillcnt - 1;
3549 while (fillcnt-- > 0) {
3550 while (fillsrc <= p_end && p_char[fillsrc] != ' ')
3552 if (fillsrc > p_end)
3553 fatal("replacement text or line numbers mangled in hunk at line %ld\n",
3555 p_line[filldst] = p_line[fillsrc];
3556 p_char[filldst] = p_char[fillsrc];
3557 p_len[filldst] = p_len[fillsrc];
3561 while (fillsrc <= p_end && fillsrc != repl_beginning &&
3562 p_char[fillsrc] != ' ')
3566 printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
3567 fillsrc, filldst, repl_beginning, p_end + 1);
3569 if (fillsrc != p_end + 1 && fillsrc != repl_beginning)
3571 if (filldst != p_end + 1 && filldst != repl_beginning)
3574 if (p_line[p_end] != NULL) {
3575 if (remove_special_line()) {
3577 (p_line[p_end])[p_len[p_end]] = 0;
3580 } else if (diff_type == UNI_DIFF) {
3581 LINENUM fillold; /* index of old lines */
3582 LINENUM fillnew; /* index of new lines */
3585 line_beginning = ftello(pfp); /* file pos of the current line */
3588 if (len == 0 || strnNE(buf, "@@ -", 4)) {
3589 next_intuit_at(line_beginning, p_input_line);
3595 p_first = strtolinenum(s, &s);
3597 p_ptrn_lines = strtolinenum(s + 1, &s);
3602 if (*s != '+' || !*++s)
3604 p_newfirst = strtolinenum(s, &s);
3606 p_repl_lines = strtolinenum(s + 1, &s);
3613 if (p_first >= LINENUM_MAX - p_ptrn_lines ||
3614 p_newfirst > LINENUM_MAX - p_repl_lines ||
3615 p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3618 p_first++; /* do append rather than insert */
3619 p_max = p_ptrn_lines + p_repl_lines + 1;
3620 while (p_max >= hunkmax)
3623 fillnew = fillold + p_ptrn_lines;
3624 p_end = fillnew + p_repl_lines;
3625 snprintf(buf, buf_size, "*** %ld,%ld ****\n", p_first,
3626 p_first + p_ptrn_lines - 1);
3627 p_line[0] = savestr(buf);
3633 snprintf(buf, buf_size, "--- %ld,%ld ----\n", p_newfirst,
3634 p_newfirst + p_repl_lines - 1);
3635 p_line[fillnew] = savestr(buf);
3640 p_char[fillnew++] = '=';
3643 p_hunk_beg = p_input_line + 1;
3644 while (fillold <= p_ptrn_lines || fillnew <= p_end) {
3645 line_beginning = ftello(pfp);
3649 if (p_max - fillnew < 3) {
3650 /* assume blank lines got chopped */
3651 strlcpy(buf, " \n", buf_size);
3653 fatal("unexpected end of file in patch\n");
3656 if (*buf == '\t' || *buf == '\n') {
3657 ch = ' '; /* assume the space got eaten */
3661 s = savestr(buf + 1);
3664 while (--fillnew > p_ptrn_lines)
3665 free(p_line[fillnew]);
3666 p_end = fillold - 1;
3671 if (fillold > p_ptrn_lines) {
3673 p_end = fillnew - 1;
3676 p_char[fillold] = ch;
3677 p_line[fillold] = s;
3678 p_len[fillold++] = strlen(s);
3679 if (fillold > p_ptrn_lines) {
3680 if (remove_special_line()) {
3681 p_len[fillold - 1] -= 1;
3682 s[p_len[fillold - 1]] = 0;
3690 if (fillold > p_ptrn_lines) {
3692 while (--fillnew > p_ptrn_lines)
3693 free(p_line[fillnew]);
3694 p_end = fillold - 1;
3698 p_char[fillold] = ch;
3699 p_line[fillold] = s;
3700 p_len[fillold++] = strlen(s);
3703 while (--fillnew > p_ptrn_lines)
3704 free(p_line[fillnew]);
3705 p_end = fillold - 1;
3708 if (fillold > p_ptrn_lines) {
3709 if (remove_special_line()) {
3710 p_len[fillold - 1] -= 1;
3711 s[p_len[fillold - 1]] = 0;
3716 if (fillnew > p_end) {
3718 while (--fillnew > p_ptrn_lines)
3719 free(p_line[fillnew]);
3720 p_end = fillold - 1;
3723 p_char[fillnew] = ch;
3724 p_line[fillnew] = s;
3725 p_len[fillnew++] = strlen(s);
3726 if (fillold > p_ptrn_lines) {
3727 if (remove_special_line()) {
3728 p_len[fillnew - 1] -= 1;
3729 s[p_len[fillnew - 1]] = 0;
3737 if (ch != ' ' && context > 0) {
3738 if (context < p_context)
3739 p_context = context;
3743 } else { /* normal diff--fake it up */
3748 line_beginning = ftello(pfp);
3752 if (len == 0 || !isdigit((unsigned char)*buf)) {
3753 next_intuit_at(line_beginning, p_input_line);
3756 p_first = strtolinenum(buf, &s);
3758 p_ptrn_lines = strtolinenum(s + 1, &s) - p_first + 1;
3759 if (p_ptrn_lines < 0)
3762 p_ptrn_lines = (*s != 'a');
3764 if (hunk_type == 'a')
3765 p_first++; /* do append rather than insert */
3766 min = strtolinenum(s + 1, &s);
3768 max = strtolinenum(s + 1, &s);
3771 if (min < 0 || min > max || max - min == LINENUM_MAX)
3773 if (hunk_type == 'd')
3776 p_repl_lines = max - min + 1;
3777 if (p_newfirst > LINENUM_MAX - p_repl_lines ||
3778 p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3780 p_end = p_ptrn_lines + p_repl_lines + 1;
3781 if (p_end > MAXHUNKSIZE)
3782 fatal("hunk too large (%ld lines) at line %ld: %s",
3783 p_end, p_input_line, buf);
3784 while (p_end >= hunkmax)
3786 snprintf(buf, buf_size, "*** %ld,%ld\n", p_first,
3787 p_first + p_ptrn_lines - 1);
3788 p_line[0] = savestr(buf);
3794 for (i = 1; i <= p_ptrn_lines; i++) {
3798 fatal("unexpected end of file in patch at line %ld\n",
3801 fatal("< expected at line %ld of patch\n",
3803 p_line[i] = savestr(buf + 2);
3808 p_len[i] = strlen(p_line[i]);
3812 if (remove_special_line()) {
3814 (p_line[i - 1])[p_len[i - 1]] = 0;
3816 if (hunk_type == 'c') {
3820 fatal("unexpected end of file in patch at line %ld\n",
3823 fatal("--- expected at line %ld of patch\n",
3826 snprintf(buf, buf_size, "--- %ld,%ld\n", min, max);
3827 p_line[i] = savestr(buf);
3833 for (i++; i <= p_end; i++) {
3837 fatal("unexpected end of file in patch at line %ld\n",
3840 fatal("> expected at line %ld of patch\n",
3842 p_line[i] = savestr(buf + 2);
3847 p_len[i] = strlen(p_line[i]);
3851 if (remove_special_line()) {
3853 (p_line[i - 1])[p_len[i - 1]] = 0;
3856 if (reverse) /* backwards patch? */
3858 say("Not enough memory to swap next hunk!\n");
3864 for (i = 0; i <= p_end; i++) {
3865 if (i == p_ptrn_lines)
3869 fprintf(stderr, "%3ld %c %c %s", i, p_char[i],
3870 special, p_line[i]);
3875 if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */
3876 p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */
3881 * Input a line from the patch file.
3882 * Worry about indentation if do_indent is true.
3883 * The line is read directly into the buf global variable which
3884 * is resized if necessary in order to hold the complete line.
3885 * Returns the number of characters read including the terminating
3889 pgets(bool do_indent)
3893 int indent = 0, skipped = 0;
3895 line = fgetln(pfp, &len);
3897 if (len + 1 > buf_size) {
3898 while (len + 1 > buf_size)
3901 buf = malloc(buf_size);
3903 fatal("out of memory\n");
3905 if (do_indent == 1 && p_indent) {
3907 indent < p_indent && (*line == ' ' || *line == '\t' || *line == 'X');
3908 line++, skipped++) {
3910 indent += 8 - (indent %7);
3915 memcpy(buf, line, len - skipped);
3916 buf[len - skipped] = '\0';
3923 * Reverse the old and new portions of the current hunk.
3928 char **tp_line; /* the text of the hunk */
3929 unsigned short *tp_len;/* length of each line */
3930 char *tp_char; /* +, -, and ! */
3933 bool blankline = false;
3937 p_first = p_newfirst;
3940 /* make a scratch copy */
3945 p_line = NULL; /* force set_hunkmax to allocate again */
3949 if (p_line == NULL || p_len == NULL || p_char == NULL) {
3957 return false; /* not enough memory to swap hunk! */
3959 /* now turn the new into the old */
3961 i = p_ptrn_lines + 1;
3962 if (tp_char[i] == '\n') { /* account for possible blank line */
3966 if (p_efake >= 0) { /* fix non-freeable ptr range */
3974 for (n = 0; i <= p_end; i++, n++) {
3975 p_line[n] = tp_line[i];
3976 p_char[n] = tp_char[i];
3977 if (p_char[n] == '+')
3979 p_len[n] = tp_len[i];
3982 i = p_ptrn_lines + 1;
3983 p_line[n] = tp_line[i];
3984 p_char[n] = tp_char[i];
3985 p_len[n] = tp_len[i];
3988 if (p_char[0] != '=')
3989 fatal("Malformed patch at line %ld: expected '=' found '%c'\n",
3990 p_input_line, p_char[0]);
3992 for (s = p_line[0]; *s; s++)
3996 /* now turn the old into the new */
3998 if (p_char[0] != '*')
3999 fatal("Malformed patch at line %ld: expected '*' found '%c'\n",
4000 p_input_line, p_char[0]);
4002 for (s = tp_line[0]; *s; s++)
4005 for (i = 0; n <= p_end; i++, n++) {
4006 p_line[n] = tp_line[i];
4007 p_char[n] = tp_char[i];
4008 if (p_char[n] == '-')
4010 p_len[n] = tp_len[i];
4013 if (i != p_ptrn_lines + 1)
4014 fatal("Malformed patch at line %ld: expected %ld lines, "
4016 p_input_line, p_ptrn_lines + 1, i);
4019 p_ptrn_lines = p_repl_lines;
4030 * Return the specified line position in the old file of the old context.
4039 * Return the number of lines of old context.
4042 pch_ptrn_lines(void)
4044 return p_ptrn_lines;
4048 * Return the probable line position in the new file of the first line.
4057 * Return the number of lines in the replacement text including context.
4060 pch_repl_lines(void)
4062 return p_repl_lines;
4066 * Return the number of lines in the whole hunk.
4075 * Return the number of context lines before the first changed line.
4084 * Return the length of a particular patch line.
4087 pch_line_len(LINENUM line)
4093 * Return the control character (+, -, *, !, etc) for a patch line.
4096 pch_char(LINENUM line)
4098 return p_char[line];
4102 * Return a pointer to a particular patch line.
4105 pfetch(LINENUM line)
4107 return p_line[line];
4111 * Return where in the patch file this hunk began, for error messages.
4120 * Apply an ed script by feeding ed itself.
4126 off_t beginning_of_this_line;
4127 FILE *pipefp = NULL;
4130 if (!skip_rest_of_patch) {
4131 if (copy_file(filearg[0], TMPOUTNAME) < 0) {
4133 fatal("can't create temp file %s", TMPOUTNAME);
4135 snprintf(buf, buf_size, "%s%s%s", _PATH_RED,
4136 verbosity == VERBOSE ? " " : " -s ", TMPOUTNAME);
4137 pipefp = popen(buf, "w");
4140 beginning_of_this_line = ftello(pfp);
4141 if (pgets(true) == 0) {
4142 next_intuit_at(beginning_of_this_line, p_input_line);
4146 for (t = buf; isdigit((unsigned char)*t) || *t == ','; t++)
4148 /* POSIX defines allowed commands as {a,c,d,i,s} */
4149 if (isdigit((unsigned char)*buf) &&
4150 (*t == 'a' || *t == 'c' || *t == 'd' || *t == 'i' || *t == 's')) {
4156 t = strchr(buf, '\0') - 1;
4157 while (--t >= buf && *t == '\\')
4158 continuation = !continuation;
4159 if (!continuation ||
4165 } else if (*t != 'd') {
4166 while (pgets(true)) {
4170 if (strEQ(buf, ".\n"))
4175 next_intuit_at(beginning_of_this_line, p_input_line);
4181 fprintf(pipefp, "w\n");
4182 fprintf(pipefp, "q\n");
4187 if (move_file(TMPOUTNAME, outname) < 0) {
4189 chmod(TMPOUTNAME, filemode);
4191 chmod(outname, filemode);
4197 * Choose the name of the file to be patched based on POSIX rules.
4198 * NOTE: the POSIX rules are amazingly stupid and we only follow them
4199 * if the user specified --posix or set POSIXLY_CORRECT.
4202 posix_name(const struct file_name *names, bool assume_exists)
4208 * POSIX states that the filename will be chosen from one
4209 * of the old, new and index names (in that order) if
4210 * the file exists relative to CWD after -p stripping.
4212 for (i = 0; i < MAX_FILE; i++) {
4213 if (names[i].path != NULL && names[i].exists) {
4214 path = names[i].path;
4218 if (path == NULL && !assume_exists) {
4220 * No files found, check to see if the diff could be
4221 * creating a new file.
4223 if (path == NULL && ok_to_create_file &&
4224 names[NEW_FILE].path != NULL)
4225 path = names[NEW_FILE].path;
4228 return path ? xstrdup(path) : NULL;
4232 compare_names(const struct file_name *names, bool assume_exists)
4234 size_t min_components, min_baselen, min_len, tmp;
4240 * The "best" name is the one with the fewest number of path
4241 * components, the shortest basename length, and the shortest
4242 * overall length (in that order). We only use the Index: file
4243 * if neither of the old or new files could be intuited from
4246 min_components = min_baselen = min_len = SIZE_MAX;
4247 for (i = INDEX_FILE; i >= OLD_FILE; i--) {
4248 path = names[i].path;
4249 if (path == NULL || (!names[i].exists && !assume_exists))
4251 if ((tmp = num_components(path)) > min_components)
4253 if (tmp < min_components) {
4254 min_components = tmp;
4257 if ((tmp = strlen(basename(path))) > min_baselen)
4259 if (tmp < min_baselen) {
4263 if ((tmp = strlen(path)) > min_len)
4272 * Choose the name of the file to be patched based the "best" one
4276 best_name(const struct file_name *names, bool assume_exists)
4280 best = compare_names(names, assume_exists);
4282 /* No match? Check to see if the diff could be creating a new file. */
4283 if (best == NULL && ok_to_create_file)
4284 best = names[NEW_FILE].path;
4286 return best ? xstrdup(best) : NULL;
4290 num_components(const char *path)
4295 for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) {
4297 cp++; /* skip consecutive slashes */
4303 * Convert number at NPTR into LINENUM and save address of first
4304 * character that is not a digit in ENDPTR. If conversion is not
4305 * possible, call fatal.
4308 strtolinenum(char *nptr, char **endptr)
4315 for (p = nptr; isdigit((unsigned char)*p); p++)
4324 rv = strtonum(nptr, 0, LINENUM_MAX, &errstr);
4326 fatal("invalid line number at line %ld: `%s' is %s\n",
4327 p_input_line, nptr, errstr);
4336 [FILE:608:files/pch.h]
4339 #define INDEX_FILE 2
4347 void re_patch(void);
4348 void open_patch_file(const char *);
4349 void set_hunkmax(void);
4350 bool there_is_another_patch(void);
4351 bool another_hunk(void);
4352 bool pch_swap(void);
4353 char *pfetch(LINENUM);
4354 unsigned short pch_line_len(LINENUM);
4355 LINENUM pch_first(void);
4356 LINENUM pch_ptrn_lines(void);
4357 LINENUM pch_newfirst(void);
4358 LINENUM pch_repl_lines(void);
4359 LINENUM pch_end(void);
4360 LINENUM pch_context(void);
4361 LINENUM pch_hunk_beg(void);
4362 char pch_char(LINENUM);
4363 void do_ed_script(void);
4366 [FILE:7988:files/util.c]
4367 #include <sys/stat.h>
4384 #include "backupfile.h"
4385 #include "pathnames.h"
4387 /* Rename a file, copying it if necessary. */
4390 move_file(const char *from, const char *to)
4397 if (strEQ(to, "-")) {
4400 say("Moving %s to stdout.\n", from);
4402 fromfd = open(from, O_RDONLY);
4404 pfatal("internal error, can't reopen %s", from);
4405 while ((i = read(fromfd, buf, buf_size)) > 0)
4406 if (write(STDOUT_FILENO, buf, i) != i)
4407 pfatal("write failed");
4411 if (backup_file(to) < 0) {
4412 say("Can't backup %s, output is in %s: %s\n", to, from,
4418 say("Moving %s to %s.\n", from, to);
4420 if (rename(from, to) < 0) {
4421 if (errno != EXDEV || copy_file(from, to) < 0) {
4422 say("Can't create %s, output is in %s: %s\n",
4423 to, from, strerror(errno));
4430 /* Backup the original file. */
4433 backup_file(const char *orig)
4435 struct stat filestat;
4436 char bakname[PATH_MAX], *s, *simplename;
4440 if (backup_type == none || stat(orig, &filestat) != 0)
4441 return 0; /* nothing to do */
4443 * If the user used zero prefixes or suffixes, then
4444 * he doesn't want backups. Yet we have to remove
4445 * orig to break possible hardlinks.
4447 if ((origprae && *origprae == 0) || *simple_backup_suffix == 0) {
4451 orig_device = filestat.st_dev;
4452 orig_inode = filestat.st_ino;
4455 if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
4456 strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
4457 fatal("filename %s too long for buffer\n", origprae);
4459 if ((s = find_backup_file_name(orig)) == NULL)
4460 fatal("out of memory\n");
4461 if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
4462 fatal("filename %s too long for buffer\n", s);
4466 if ((simplename = strrchr(bakname, '/')) != NULL)
4467 simplename = simplename + 1;
4469 simplename = bakname;
4472 * Find a backup name that is not the same file. Change the
4473 * first lowercase char into uppercase; if that isn't
4474 * sufficient, chop off the first char and try again.
4476 while (stat(bakname, &filestat) == 0 &&
4477 orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
4478 /* Skip initial non-lowercase chars. */
4479 for (s = simplename; *s && !islower((unsigned char)*s); s++)
4482 *s = toupper((unsigned char)*s);
4484 memmove(simplename, simplename + 1,
4485 strlen(simplename + 1) + 1);
4489 say("Moving %s to %s.\n", orig, bakname);
4491 if (rename(orig, bakname) < 0) {
4492 if (errno != EXDEV || copy_file(orig, bakname) < 0)
4502 copy_file(const char *from, const char *to)
4507 tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
4510 fromfd = open(from, O_RDONLY, 0);
4512 pfatal("internal error, can't reopen %s", from);
4513 while ((i = read(fromfd, buf, buf_size)) > 0)
4514 if (write(tofd, buf, i) != i)
4515 pfatal("write to %s failed", to);
4522 * Allocate a unique area for a string.
4525 savestr(const char *s)
4536 fatal("out of memory\n");
4542 * Allocate a unique area for a string. Call fatal if out of memory.
4545 xstrdup(const char *s)
4553 fatal("out of memory\n");
4558 * Vanilla terminal output (buffered).
4561 say(const char *fmt, ...)
4566 vfprintf(stdout, fmt, ap);
4572 * Terminal output, pun intended.
4575 fatal(const char *fmt, ...)
4580 fprintf(stderr, "patch: **** ");
4581 vfprintf(stderr, fmt, ap);
4587 * Say something from patch, something from the system, then silence . . .
4590 pfatal(const char *fmt, ...)
4595 fprintf(stderr, "patch: **** ");
4597 vfprintf(stderr, fmt, ap);
4599 fprintf(stderr, ": %s\n", strerror(errnum));
4604 * Get a response from the user via /dev/tty
4607 ask(const char *fmt, ...)
4611 static int ttyfd = -1;
4614 vfprintf(stdout, fmt, ap);
4618 ttyfd = open(_PATH_TTY, O_RDONLY);
4620 if ((nr = read(ttyfd, buf, buf_size)) > 0 &&
4621 buf[nr - 1] == '\n')
4624 if (ttyfd < 0 || nr <= 0) {
4625 /* no tty or error reading, pretend user entered 'return' */
4632 * How to handle certain events when not in a critical region.
4635 set_signals(int reset)
4637 static int hup_exit = 0;
4638 static int int_exit = 0;
4641 signal (SIGHUP, hup_exit ? my_exit : SIG_IGN);
4642 signal (SIGINT, int_exit ? my_exit : SIG_IGN);
4644 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
4646 signal (SIGHUP, my_exit);
4648 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
4650 signal (SIGINT, my_exit);
4656 * How to handle certain events when in a critical region.
4659 ignore_signals(void)
4661 signal(SIGHUP, SIG_IGN);
4662 signal(SIGINT, SIG_IGN);
4666 * Make sure we'll have the directories to create a file. If `striplast' is
4667 * true, ignore the last element of `filename'.
4671 makedirs(const char *filename, bool striplast)
4675 if ((tmpbuf = strdup(filename)) == NULL)
4676 fatal("out of memory\n");
4679 char *s = strrchr(tmpbuf, '/');
4682 return; /* nothing to be done */
4686 if (mkpath(tmpbuf) != 0)
4687 pfatal("creation of %s failed", tmpbuf);
4692 * Make filenames more reasonable.
4695 fetchname(const char *at, bool *exists, int strip_leading)
4697 char *fullname, *name, *t;
4699 struct stat filestat;
4701 if (at == NULL || *at == '\0')
4703 while (isspace((unsigned char)*at))
4707 say("fetchname %s %d\n", at, strip_leading);
4709 /* So files can be created by diffing against /dev/null. */
4710 if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1))
4712 name = fullname = t = savestr(at);
4714 tab = strchr(t, '\t') != NULL;
4715 /* Strip off up to `strip_leading' path components and NUL terminate. */
4716 for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') ||
4717 !isspace((unsigned char)*t)); t++) {
4718 if (t[0] == '/' && t[1] != '/' && t[1] != '\0')
4719 if (--sleading >= 0)
4725 * If no -p option was given (957 is the default value!), we were
4726 * given a relative pathname, and the leading directories that we
4727 * just stripped off all exist, put them back on.
4729 if (strip_leading == 957 && name != fullname && *fullname != '/') {
4731 if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
4736 name = savestr(name);
4739 *exists = stat(name, &filestat) == 0;
4746 printf("patch 2.0-12u11 Ravenports\n");
4747 my_exit(EXIT_SUCCESS);
4751 * Exit with cleanup.
4766 [FILE:759:files/util.h]
4767 char *fetchname(const char *, bool *, int);
4768 int backup_file(const char *);
4769 int move_file(const char *, const char *);
4770 int copy_file(const char *, const char *);
4771 void say(const char *, ...)
4772 __attribute__((__format__(__printf__, 1, 2)));
4773 void fatal(const char *, ...)
4774 __attribute__((__format__(__printf__, 1, 2)));
4775 void pfatal(const char *, ...)
4776 __attribute__((__format__(__printf__, 1, 2)));
4777 void ask(const char *, ...)
4778 __attribute__((__format__(__printf__, 1, 2)));
4779 char *savestr(const char *);
4780 char *xstrdup(const char *);
4781 void set_signals(int);
4782 void ignore_signals(void);
4783 void makedirs(const char *, bool);
4785 void my_exit(int) __attribute__((noreturn));
4788 extern int mkpath(char *);