aboutsummaryrefslogtreecommitdiff
path: root/patch.c
diff options
context:
space:
mode:
authorPedro F. Giffuni <pfg@FreeBSD.org>2013-07-27 19:57:20 +0000
committerPedro F. Giffuni <pfg@FreeBSD.org>2013-07-27 19:57:20 +0000
commitfb6b9b91d11dacb448979bb7770182f1731e9f99 (patch)
tree68fe5e9d8970b82717478c7e904a7456bbaad7f5 /patch.c
parentfea6cc68e36068e834e86474181b1e8edbae89df (diff)
Virgin import of patch-2.5.9, the last official GPLv2 release.vendor/misc-GNU/patch/2.5.9vendor/misc-GNU/patch
As in previous imports we dropped the mkinstall and pc directories as they are of no use to us. Differently from previous imports, patch.1 was not renamed and is maintained with its original name (patch.man). If we ever merge this into the main tree, care must be taken to rename it back.
Notes
Notes: svn path=/vendor/patch/dist/; revision=253717 svn path=/vendor/patch/2.5.9/; revision=253718; tag=vendor/misc-GNU/patch/2.5.9
Diffstat (limited to 'patch.c')
-rw-r--r--patch.c589
1 files changed, 328 insertions, 261 deletions
diff --git a/patch.c b/patch.c
index 7eb83f5da26b..9e04daf6b48e 100644
--- a/patch.c
+++ b/patch.c
@@ -1,26 +1,26 @@
/* patch - a program to apply diffs to original files */
-/* $Id: patch.c,v 1.23 1997/07/05 10:32:23 eggert Exp $ */
+/* $Id: patch.c,v 1.44 2003/05/20 13:55:03 eggert Exp $ */
-/*
-Copyright 1984, 1985, 1986, 1987, 1988 Larry Wall
-Copyright 1989, 1990, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1984, 1985, 1986, 1987, 1988 Larry Wall
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1997, 1998, 1999, 2002,
+ 2003 Free Software Foundation, Inc.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.
-If not, write to the Free Software Foundation,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define XTERN
#include <common.h>
@@ -31,8 +31,10 @@ If not, write to the Free Software Foundation,
#include <getopt.h>
#include <inp.h>
#include <pch.h>
+#include <quotearg.h>
#include <util.h>
#include <version.h>
+#include <xalloc.h>
#if HAVE_UTIME_H
# include <utime.h>
@@ -50,45 +52,47 @@ struct utimbuf
struct outstate
{
FILE *ofp;
- int after_newline;
- int zero_output;
+ bool after_newline;
+ bool zero_output;
};
/* procedures */
-static FILE *create_output_file PARAMS ((char const *));
-static LINENUM locate_hunk PARAMS ((LINENUM));
-static bool apply_hunk PARAMS ((struct outstate *, LINENUM));
-static bool copy_till PARAMS ((struct outstate *, LINENUM));
-static bool patch_match PARAMS ((LINENUM, LINENUM, LINENUM, LINENUM));
-static bool similar PARAMS ((char const *, size_t, char const *, size_t));
-static bool spew_output PARAMS ((struct outstate *));
-static char const *make_temp PARAMS ((int));
-static int numeric_string PARAMS ((char const *, int, char const *));
-static void abort_hunk PARAMS ((void));
-static void cleanup PARAMS ((void));
-static void get_some_switches PARAMS ((void));
-static void init_output PARAMS ((char const *, struct outstate *));
-static void init_reject PARAMS ((char const *));
-static void reinitialize_almost_everything PARAMS ((void));
-static void usage PARAMS ((FILE *, int)) __attribute__((noreturn));
-
-static int make_backups;
-static int backup_if_mismatch;
+static FILE *create_output_file (char const *, int);
+static LINENUM locate_hunk (LINENUM);
+static bool apply_hunk (struct outstate *, LINENUM);
+static bool copy_till (struct outstate *, LINENUM);
+static bool patch_match (LINENUM, LINENUM, LINENUM, LINENUM);
+static bool similar (char const *, size_t, char const *, size_t);
+static bool spew_output (struct outstate *);
+static char const *make_temp (char);
+static int numeric_string (char const *, bool, char const *);
+static void abort_hunk (void);
+static void cleanup (void);
+static void get_some_switches (void);
+static void init_output (char const *, int, struct outstate *);
+static void init_reject (void);
+static void reinitialize_almost_everything (void);
+static void remove_if_needed (char const *, int volatile *);
+static void usage (FILE *, int) __attribute__((noreturn));
+
+static bool make_backups;
+static bool backup_if_mismatch;
static char const *version_control;
-static int remove_empty_files;
+static char const *version_control_context;
+static bool remove_empty_files;
-/* TRUE if -R was specified on command line. */
-static int reverse_flag_specified;
+/* true if -R was specified on command line. */
+static bool reverse_flag_specified;
/* how many input lines have been irretractably output */
static LINENUM last_frozen_line;
static char const *do_defines; /* symbol to patch using ifdef, ifndef, etc. */
static char const if_defined[] = "\n#ifdef %s\n";
-static char const not_defined[] = "#ifndef %s\n";
+static char const not_defined[] = "\n#ifndef %s\n";
static char const else_defined[] = "\n#else\n";
-static char const end_defined[] = "\n#endif /* %s */\n";
+static char const end_defined[] = "\n#endif\n";
static int Argc;
static char * const *Argv;
@@ -98,51 +102,55 @@ static FILE *rejfp; /* reject file pointer */
static char const *patchname;
static char *rejname;
static char const * volatile TMPREJNAME;
+static int volatile TMPREJNAME_needs_removal;
static LINENUM last_offset;
static LINENUM maxfuzz = 2;
static char serrbuf[BUFSIZ];
-char const program_name[] = "patch";
-
/* Apply a set of diffs as appropriate. */
-int main PARAMS ((int, char **));
-
int
-main(argc,argv)
-int argc;
-char **argv;
+main (int argc, char **argv)
{
char const *val;
- bool somefailed = FALSE;
+ bool somefailed = false;
struct outstate outstate;
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
+ xalloc_exit_failure = 2;
+ program_name = argv[0];
init_time ();
setbuf(stderr, serrbuf);
+ xalloc_fail_func = memory_fatal;
bufsize = 8 * 1024;
buf = xmalloc (bufsize);
- strippath = INT_MAX;
+ strippath = -1;
+
+ val = getenv ("QUOTING_STYLE");
+ {
+ int i = val ? argmatch (val, quoting_style_args, 0, 0) : -1;
+ set_quoting_style ((struct quoting_options *) 0,
+ i < 0 ? shell_quoting_style : (enum quoting_style) i);
+ }
posixly_correct = getenv ("POSIXLY_CORRECT") != 0;
backup_if_mismatch = ! posixly_correct;
patch_get = ((val = getenv ("PATCH_GET"))
- ? numeric_string (val, 1, "PATCH_GET value")
+ ? numeric_string (val, true, "PATCH_GET value")
: posixly_correct - 1);
- {
- char const *v = getenv ("SIMPLE_BACKUP_SUFFIX");
- if (v && *v)
- simple_backup_suffix = v;
- }
+ val = getenv ("SIMPLE_BACKUP_SUFFIX");
+ simple_backup_suffix = val && *val ? val : ".orig";
- version_control = getenv ("PATCH_VERSION_CONTROL");
- if (! version_control)
- version_control = getenv ("VERSION_CONTROL");
+ if ((version_control = getenv ("PATCH_VERSION_CONTROL")))
+ version_control_context = "$PATCH_VERSION_CONTROL";
+ else if ((version_control = getenv ("VERSION_CONTROL")))
+ version_control_context = "$VERSION_CONTROL";
/* Cons up the names of the global temporary files.
Do this before `cleanup' can possibly be called (e.g. by `pfatal'). */
@@ -157,12 +165,12 @@ char **argv;
get_some_switches();
if (make_backups | backup_if_mismatch)
- backup_type = get_version (version_control);
+ backup_type = get_version (version_control_context, version_control);
- init_output (outfile, &outstate);
+ init_output (outfile, 0, &outstate);
/* Make sure we clean up in case of disaster. */
- set_signals(0);
+ set_signals (false);
for (
open_patch_file (patchname);
@@ -171,35 +179,37 @@ char **argv;
) { /* for each patch in patch file */
int hunk = 0;
int failed = 0;
- int mismatch = 0;
+ bool mismatch = false;
char *outname = outfile ? outfile : inname;
if (!skip_rest_of_patch)
get_input_file (inname, outname);
if (diff_type == ED_DIFF) {
- outstate.zero_output = 0;
- if (! dry_run)
+ outstate.zero_output = false;
+ somefailed |= skip_rest_of_patch;
+ do_ed_script (outstate.ofp);
+ if (! dry_run && ! outfile && ! skip_rest_of_patch)
{
- do_ed_script (outstate.ofp);
- if (! outfile)
- {
- struct stat statbuf;
- if (stat (TMPOUTNAME, &statbuf) != 0)
- pfatal ("%s", TMPOUTNAME);
- outstate.zero_output = statbuf.st_size == 0;
- }
+ struct stat statbuf;
+ if (stat (TMPOUTNAME, &statbuf) != 0)
+ pfatal ("%s", TMPOUTNAME);
+ outstate.zero_output = statbuf.st_size == 0;
}
} else {
int got_hunk;
- int apply_anyway = 0;
+ bool apply_anyway = false;
/* initialize the patched file */
if (! skip_rest_of_patch && ! outfile)
- init_output (TMPOUTNAME, &outstate);
+ {
+ int exclusive = TMPOUTNAME_needs_removal ? 0 : O_EXCL;
+ TMPOUTNAME_needs_removal = 1;
+ init_output (TMPOUTNAME, exclusive, &outstate);
+ }
/* initialize reject file */
- init_reject(TMPREJNAME);
+ init_reject ();
/* find out where all the lines are */
if (!skip_rest_of_patch)
@@ -223,7 +233,7 @@ char **argv;
do {
where = locate_hunk(fuzz);
if (! where || fuzz || last_offset)
- mismatch = 1;
+ mismatch = true;
if (hunk == 1 && ! where && ! (force | apply_anyway)
&& reverse == reverse_flag_specified) {
/* dwim for reversed patch? */
@@ -240,7 +250,7 @@ char **argv;
(reverse
? "Unreversed"
: "Reversed (or previously applied)"))))
- reverse ^= 1;
+ reverse = ! reverse;
else
{
/* Put it back to normal. */
@@ -248,7 +258,7 @@ char **argv;
fatal ("lost hunk on alloc error!");
if (where)
{
- apply_anyway = 1;
+ apply_anyway = true;
fuzz--; /* Undo `++fuzz' below. */
where = 0;
}
@@ -271,58 +281,67 @@ char **argv;
abort_hunk();
failed++;
if (verbosity == VERBOSE)
- say ("Hunk #%d ignored at %ld.\n", hunk, newwhere);
+ say ("Hunk #%d ignored at %s.\n", hunk,
+ format_linenum (numbuf, newwhere));
}
else if (!where
- || (where == 1 && pch_says_nonexistent (reverse)
+ || (where == 1 && pch_says_nonexistent (reverse) == 2
&& instat.st_size)) {
+
if (where)
- say ("Patch attempted to create file `%s', which already exists.\n", inname);
+ say ("Patch attempted to create file %s, which already exists.\n",
+ quotearg (inname));
+
abort_hunk();
failed++;
if (verbosity != SILENT)
- say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
+ say ("Hunk #%d FAILED at %s.\n", hunk,
+ format_linenum (numbuf, newwhere));
}
else if (! apply_hunk (&outstate, where)) {
abort_hunk ();
failed++;
if (verbosity != SILENT)
- say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
+ say ("Hunk #%d FAILED at %s.\n", hunk,
+ format_linenum (numbuf, newwhere));
} else {
if (verbosity == VERBOSE
|| (verbosity != SILENT && (fuzz || last_offset))) {
- say ("Hunk #%d succeeded at %ld", hunk, newwhere);
+ say ("Hunk #%d succeeded at %s", hunk,
+ format_linenum (numbuf, newwhere));
if (fuzz)
- say (" with fuzz %ld", fuzz);
+ say (" with fuzz %s", format_linenum (numbuf, fuzz));
if (last_offset)
- say (" (offset %ld line%s)",
- last_offset, last_offset==1?"":"s");
+ say (" (offset %s line%s)",
+ format_linenum (numbuf, last_offset),
+ "s" + (last_offset == 1));
say (".\n");
}
}
}
- if (got_hunk < 0 && using_plan_a) {
- if (outfile)
- fatal ("out of memory using Plan A");
- say ("\n\nRan out of memory using Plan A -- trying again...\n\n");
- if (outstate.ofp)
+ if (!skip_rest_of_patch)
+ {
+ if (got_hunk < 0 && using_plan_a)
{
- fclose (outstate.ofp);
- outstate.ofp = 0;
+ if (outfile)
+ fatal ("out of memory using Plan A");
+ say ("\n\nRan out of memory using Plan A -- trying again...\n\n");
+ if (outstate.ofp)
+ {
+ fclose (outstate.ofp);
+ outstate.ofp = 0;
+ }
+ fclose (rejfp);
+ continue;
}
- fclose (rejfp);
- continue;
- }
- /* finish spewing out the new file */
- if (!skip_rest_of_patch)
- {
+ /* Finish spewing out the new file. */
assert (hunk);
if (! spew_output (&outstate))
{
say ("Skipping patch.\n");
- skip_rest_of_patch = TRUE;
+ skip_rest_of_patch = true;
}
}
}
@@ -332,15 +351,15 @@ char **argv;
if (! skip_rest_of_patch && ! outfile) {
if (outstate.zero_output
&& (remove_empty_files
- || (pch_says_nonexistent (reverse ^ 1) == 2
+ || (pch_says_nonexistent (! reverse) == 2
&& ! posixly_correct)))
{
if (verbosity == VERBOSE)
- say ("Removing file `%s'%s.\n", outname,
+ say ("Removing file %s%s\n", quotearg (outname),
dry_run ? " and any empty ancestor directories" : "");
if (! dry_run)
{
- move_file ((char *) 0, outname, (mode_t) 0,
+ move_file ((char *) 0, (int *) 0, outname, (mode_t) 0,
(make_backups
|| (backup_if_mismatch && (mismatch | failed))));
removedirs (outname);
@@ -349,43 +368,46 @@ char **argv;
else
{
if (! outstate.zero_output
- && pch_says_nonexistent (reverse ^ 1))
+ && pch_says_nonexistent (! reverse))
{
- mismatch = 1;
+ mismatch = true;
if (verbosity != SILENT)
- say ("File `%s' is not empty after patch, as expected.\n",
- outname);
+ say ("File %s is not empty after patch, as expected\n",
+ quotearg (outname));
}
if (! dry_run)
{
time_t t;
- move_file (TMPOUTNAME, outname, instat.st_mode,
+ move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal,
+ outname, instat.st_mode,
(make_backups
|| (backup_if_mismatch && (mismatch | failed))));
if ((set_time | set_utc)
- && (t = pch_timestamp (reverse ^ 1)) != (time_t) -1)
+ && (t = pch_timestamp (! reverse)) != (time_t) -1)
{
struct utimbuf utimbuf;
utimbuf.actime = utimbuf.modtime = t;
if (! force && ! inerrno
- && ! pch_says_nonexistent (reverse)
+ && pch_says_nonexistent (reverse) != 2
&& (t = pch_timestamp (reverse)) != (time_t) -1
&& t != instat.st_mtime)
- say ("not setting time of file `%s' (time mismatch)\n",
- outname);
+ say ("Not setting time of file %s (time mismatch)\n",
+ quotearg (outname));
else if (! force && (mismatch | failed))
- say ("not setting time of file `%s' (contents mismatch)\n",
- outname);
+ say ("Not setting time of file %s (contents mismatch)\n",
+ quotearg (outname));
else if (utime (outname, &utimbuf) != 0)
- pfatal ("can't set timestamp on file `%s'", outname);
+ pfatal ("Can't set timestamp on file %s",
+ quotearg (outname));
}
if (! inerrno && chmod (outname, instat.st_mode) != 0)
- pfatal ("can't set permissions on file `%s'", outname);
+ pfatal ("Can't set permissions on file %s",
+ quotearg (outname));
}
}
}
@@ -393,7 +415,7 @@ char **argv;
if (fclose (rejfp) != 0)
write_fatal ();
if (failed) {
- somefailed = TRUE;
+ somefailed = true;
say ("%d out of %d hunk%s %s", failed, hunk, "s" + (hunk == 1),
skip_rest_of_patch ? "ignored" : "FAILED");
if (outname) {
@@ -403,15 +425,17 @@ char **argv;
strcpy (rej, outname);
addext (rej, ".rej", '#');
}
- say (" -- saving rejects to %s", rej);
+ say (" -- saving rejects to file %s", quotearg (rej));
if (! dry_run)
{
- move_file (TMPREJNAME, rej, instat.st_mode, FALSE);
+ move_file (TMPREJNAME, &TMPREJNAME_needs_removal,
+ rej, instat.st_mode, false);
if (! inerrno
&& (chmod (rej, (instat.st_mode
& ~(S_IXUSR|S_IXGRP|S_IXOTH)))
!= 0))
- pfatal ("can't set permissions on file `%s'", rej);
+ pfatal ("can't set permissions on file %s",
+ quotearg (rej));
}
if (!rejname)
free (rej);
@@ -419,7 +443,7 @@ char **argv;
say ("\n");
}
}
- set_signals (1);
+ set_signals (true);
}
if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0))
write_fatal ();
@@ -432,7 +456,7 @@ char **argv;
/* Prepare to find the next patch to do in the patch file. */
static void
-reinitialize_almost_everything()
+reinitialize_almost_everything (void)
{
re_patch();
re_input();
@@ -455,7 +479,7 @@ reinitialize_almost_everything()
}
reverse = reverse_flag_specified;
- skip_rest_of_patch = FALSE;
+ skip_rest_of_patch = false;
}
static char const shortopts[] = "bB:cd:D:eEfF:g:i:lnNo:p:r:RstTuvV:x:Y:z:Z";
@@ -490,12 +514,14 @@ static struct option const longopts[] =
{"basename-prefix", required_argument, NULL, 'Y'},
{"suffix", required_argument, NULL, 'z'},
{"set-utc", no_argument, NULL, 'Z'},
- {"dry-run", no_argument, NULL, 129},
- {"verbose", no_argument, NULL, 130},
- {"binary", no_argument, NULL, 131},
- {"help", no_argument, NULL, 132},
- {"backup-if-mismatch", no_argument, NULL, 133},
- {"no-backup-if-mismatch", no_argument, NULL, 134},
+ {"dry-run", no_argument, NULL, CHAR_MAX + 1},
+ {"verbose", no_argument, NULL, CHAR_MAX + 2},
+ {"binary", no_argument, NULL, CHAR_MAX + 3},
+ {"help", no_argument, NULL, CHAR_MAX + 4},
+ {"backup-if-mismatch", no_argument, NULL, CHAR_MAX + 5},
+ {"no-backup-if-mismatch", no_argument, NULL, CHAR_MAX + 6},
+ {"posix", no_argument, NULL, CHAR_MAX + 7},
+ {"quoting-style", required_argument, NULL, CHAR_MAX + 8},
{NULL, no_argument, NULL, 0}
};
@@ -528,6 +554,10 @@ static char const *const option_help[] =
" -Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).",
" -T --set-time Likewise, assuming local time.",
"",
+" --quoting-style=WORD output file names using quoting style WORD.",
+" Valid WORDs are: literal, shell, shell-always, c, escape.",
+" Default is taken from QUOTING_STYLE env variable, or 'shell' if unset.",
+"",
"Backup and version control options:",
"",
" -b --backup Back up the original contents of each file.",
@@ -540,7 +570,7 @@ static char const *const option_help[] =
" -Y PREFIX --basename-prefix=PREFIX Prepend PREFIX to backup file basenames.",
" -z SUFFIX --suffix=SUFFIX Append SUFFIX to backup file names.",
"",
-" -g NUM --get=NUM Get files from RCS or SCCS if positive; ask if negative.",
+" -g NUM --get=NUM Get files from RCS etc. if positive; ask if negative.",
"",
"Miscellaneous options:",
"",
@@ -549,9 +579,10 @@ static char const *const option_help[] =
" -s --quiet --silent Work silently unless an error occurs.",
" --verbose Output extra information about the work being done.",
" --dry-run Do not actually change any files; just print what would happen.",
+" --posix Conform to the POSIX standard.",
"",
" -d DIR --directory=DIR Change the working directory to DIR first.",
-#if HAVE_SETMODE
+#if HAVE_SETMODE_DOS
" --binary Read and write data in binary mode.",
#else
" --binary Read and write data in binary mode (no effect on this platform).",
@@ -560,14 +591,12 @@ static char const *const option_help[] =
" -v --version Output version info.",
" --help Output this help.",
"",
-"Report bugs to <bug-gnu-utils@prep.ai.mit.edu>.",
+"Report bugs to <" PACKAGE_BUGREPORT ">.",
0
};
static void
-usage (stream, status)
- FILE *stream;
- int status;
+usage (FILE *stream, int status)
{
char const * const *p;
@@ -590,7 +619,7 @@ usage (stream, status)
/* Process switches and filenames. */
static void
-get_some_switches()
+get_some_switches (void)
{
register int optc;
@@ -603,7 +632,7 @@ get_some_switches()
!= -1) {
switch (optc) {
case 'b':
- make_backups = 1;
+ make_backups = true;
/* Special hack for backward compatibility with CVS 1.9.
If the last 4 args are `-b SUFFIX ORIGFILE PATCHFILE',
treat `-b' as if it were `-b -z'. */
@@ -630,7 +659,7 @@ get_some_switches()
break;
case 'd':
if (chdir(optarg) < 0)
- pfatal ("can't change directory to `%s'", optarg);
+ pfatal ("Can't change to directory %s", quotearg (optarg));
break;
case 'D':
do_defines = savestr (optarg);
@@ -639,28 +668,28 @@ get_some_switches()
diff_type = ED_DIFF;
break;
case 'E':
- remove_empty_files = TRUE;
+ remove_empty_files = true;
break;
case 'f':
- force = TRUE;
+ force = true;
break;
case 'F':
- maxfuzz = numeric_string (optarg, 0, "fuzz factor");
+ maxfuzz = numeric_string (optarg, false, "fuzz factor");
break;
case 'g':
- patch_get = numeric_string (optarg, 1, "get option value");
+ patch_get = numeric_string (optarg, true, "get option value");
break;
case 'i':
patchname = savestr (optarg);
break;
case 'l':
- canonicalize = TRUE;
+ canonicalize = true;
break;
case 'n':
diff_type = NORMAL_DIFF;
break;
case 'N':
- noreverse = TRUE;
+ noreverse = true;
break;
case 'o':
if (strcmp (optarg, "-") == 0)
@@ -668,23 +697,23 @@ get_some_switches()
outfile = savestr (optarg);
break;
case 'p':
- strippath = numeric_string (optarg, 0, "strip count");
+ strippath = numeric_string (optarg, false, "strip count");
break;
case 'r':
rejname = savestr (optarg);
break;
case 'R':
- reverse = 1;
- reverse_flag_specified = 1;
+ reverse = true;
+ reverse_flag_specified = true;
break;
case 's':
verbosity = SILENT;
break;
case 't':
- batch = TRUE;
+ batch = true;
break;
case 'T':
- set_time = 1;
+ set_time = true;
break;
case 'u':
diff_type = UNI_DIFF;
@@ -695,10 +724,11 @@ get_some_switches()
break;
case 'V':
version_control = optarg;
+ version_control_context = "--version-control or -V option";
break;
#if DEBUGGING
case 'x':
- debug = numeric_string (optarg, 1, "debugging option");
+ debug = numeric_string (optarg, true, "debugging option");
break;
#endif
case 'Y':
@@ -713,26 +743,41 @@ get_some_switches()
simple_backup_suffix = savestr (optarg);
break;
case 'Z':
- set_utc = 1;
+ set_utc = true;
break;
- case 129:
- dry_run = TRUE;
+ case CHAR_MAX + 1:
+ dry_run = true;
break;
- case 130:
+ case CHAR_MAX + 2:
verbosity = VERBOSE;
break;
- case 131:
-#if HAVE_SETMODE
+ case CHAR_MAX + 3:
+#if HAVE_SETMODE_DOS
binary_transput = O_BINARY;
#endif
break;
- case 132:
+ case CHAR_MAX + 4:
usage (stdout, 0);
- case 133:
- backup_if_mismatch = 1;
+ case CHAR_MAX + 5:
+ backup_if_mismatch = true;
+ break;
+ case CHAR_MAX + 6:
+ backup_if_mismatch = false;
+ break;
+ case CHAR_MAX + 7:
+ posixly_correct = true;
break;
- case 134:
- backup_if_mismatch = 0;
+ case CHAR_MAX + 8:
+ {
+ int i = argmatch (optarg, quoting_style_args, 0, 0);
+ if (i < 0)
+ {
+ invalid_arg ("quoting style", optarg, i);
+ usage (stderr, 2);
+ }
+ set_quoting_style ((struct quoting_options *) 0,
+ (enum quoting_style) i);
+ }
break;
default:
usage (stderr, 2);
@@ -749,8 +794,8 @@ get_some_switches()
patchname = savestr (Argv[optind++]);
if (optind < Argc)
{
- fprintf (stderr, "%s: extra operand `%s'\n",
- program_name, Argv[optind]);
+ fprintf (stderr, "%s: %s: extra operand\n",
+ program_name, quotearg (Argv[optind]));
usage (stderr, 2);
}
}
@@ -761,10 +806,9 @@ get_some_switches()
of type ARGTYPE_MSGID by converting it to an integer,
returning the result. */
static int
-numeric_string (string, negative_allowed, argtype_msgid)
- char const *string;
- int negative_allowed;
- char const *argtype_msgid;
+numeric_string (char const *string,
+ bool negative_allowed,
+ char const *argtype_msgid)
{
int value = 0;
char const *p = string;
@@ -780,17 +824,17 @@ numeric_string (string, negative_allowed, argtype_msgid)
int next_value = v10 + signed_digit;
if (9 < (unsigned) digit)
- fatal ("%s `%s' is not a number", argtype_msgid, string);
+ fatal ("%s %s is not a number", argtype_msgid, quotearg (string));
if (v10 / 10 != value || (next_value < v10) != (signed_digit < 0))
- fatal ("%s `%s' is too large", argtype_msgid, string);
+ fatal ("%s %s is too large", argtype_msgid, quotearg (string));
value = next_value;
}
while (*++p);
if (value < 0 && ! negative_allowed)
- fatal ("%s `%s' is negative", argtype_msgid, string);
+ fatal ("%s %s is negative", argtype_msgid, quotearg (string));
return value;
}
@@ -798,8 +842,7 @@ numeric_string (string, negative_allowed, argtype_msgid)
/* Attempt to find the right place to apply this hunk of patch. */
static LINENUM
-locate_hunk(fuzz)
-LINENUM fuzz;
+locate_hunk (LINENUM fuzz)
{
register LINENUM first_guess = pch_first () + last_offset;
register LINENUM offset;
@@ -838,7 +881,7 @@ LINENUM fuzz;
&& offset <= max_pos_offset
&& patch_match (first_guess, offset, (LINENUM) 0, suffix_fuzz))
{
- last_offset = offset;
+ last_offset += offset;
return first_guess + offset;
}
else
@@ -852,7 +895,7 @@ LINENUM fuzz;
if (offset <= max_neg_offset
&& patch_match (first_guess, -offset, prefix_fuzz, (LINENUM) 0))
{
- last_offset = - offset;
+ last_offset -= offset;
return first_guess - offset;
}
else
@@ -860,18 +903,24 @@ LINENUM fuzz;
}
for (offset = 0; offset <= max_offset; offset++) {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
if (offset <= max_pos_offset
&& patch_match (first_guess, offset, prefix_fuzz, suffix_fuzz)) {
if (debug & 1)
- say ("Offset changing from %ld to %ld\n", last_offset, offset);
- last_offset = offset;
+ say ("Offset changing from %s to %s\n",
+ format_linenum (numbuf0, last_offset),
+ format_linenum (numbuf1, last_offset + offset));
+ last_offset += offset;
return first_guess+offset;
}
if (0 < offset && offset <= max_neg_offset
&& patch_match (first_guess, -offset, prefix_fuzz, suffix_fuzz)) {
if (debug & 1)
- say ("Offset changing from %ld to %ld\n", last_offset, -offset);
- last_offset = -offset;
+ say ("Offset changing from %s to %s\n",
+ format_linenum (numbuf0, last_offset),
+ format_linenum (numbuf1, last_offset - offset));
+ last_offset -= offset;
return first_guess-offset;
}
}
@@ -881,7 +930,7 @@ LINENUM fuzz;
/* We did not find the pattern, dump out the hunk so they can handle it. */
static void
-abort_hunk()
+abort_hunk (void)
{
register LINENUM i;
register LINENUM pat_end = pch_end ();
@@ -897,22 +946,30 @@ abort_hunk()
fprintf(rejfp, "***************\n");
for (i=0; i<=pat_end; i++) {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
switch (pch_char(i)) {
case '*':
if (oldlast < oldfirst)
fprintf(rejfp, "*** 0%s\n", stars);
else if (oldlast == oldfirst)
- fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
+ fprintf (rejfp, "*** %s%s\n",
+ format_linenum (numbuf0, oldfirst), stars);
else
- fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
+ fprintf (rejfp, "*** %s,%s%s\n",
+ format_linenum (numbuf0, oldfirst),
+ format_linenum (numbuf1, oldlast), stars);
break;
case '=':
if (newlast < newfirst)
fprintf(rejfp, "--- 0%s\n", minuses);
else if (newlast == newfirst)
- fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
+ fprintf (rejfp, "--- %s%s\n",
+ format_linenum (numbuf0, newfirst), minuses);
else
- fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
+ fprintf (rejfp, "--- %s,%s%s\n",
+ format_linenum (numbuf0, newfirst),
+ format_linenum (numbuf1, newlast), minuses);
break;
case ' ': case '-': case '+': case '!':
fprintf (rejfp, "%c ", pch_char (i));
@@ -931,9 +988,7 @@ abort_hunk()
/* We found where to apply it (we hope), so do it. */
static bool
-apply_hunk (outstate, where)
- struct outstate *outstate;
- LINENUM where;
+apply_hunk (struct outstate *outstate, LINENUM where)
{
register LINENUM old = 1;
register LINENUM lastline = pch_ptrn_lines ();
@@ -951,10 +1006,10 @@ apply_hunk (outstate, where)
if (pch_char(old) == '-') {
assert (outstate->after_newline);
if (! copy_till (outstate, where + old - 1))
- return FALSE;
+ return false;
if (R_do_defines) {
if (def_state == OUTSIDE) {
- fprintf (fp, outstate->after_newline + if_defined,
+ fprintf (fp, outstate->after_newline + not_defined,
R_do_defines);
def_state = IN_IFNDEF;
}
@@ -965,7 +1020,7 @@ apply_hunk (outstate, where)
if (ferror (fp))
write_fatal ();
outstate->after_newline = pch_write_line (old, fp);
- outstate->zero_output = 0;
+ outstate->zero_output = false;
}
last_frozen_line++;
old++;
@@ -975,7 +1030,7 @@ apply_hunk (outstate, where)
}
else if (pch_char(new) == '+') {
if (! copy_till (outstate, where + old - 1))
- return FALSE;
+ return false;
if (R_do_defines) {
if (def_state == IN_IFNDEF) {
fprintf (fp, outstate->after_newline + else_defined);
@@ -990,24 +1045,26 @@ apply_hunk (outstate, where)
write_fatal ();
}
outstate->after_newline = pch_write_line (new, fp);
- outstate->zero_output = 0;
+ outstate->zero_output = false;
new++;
}
else if (pch_char(new) != pch_char(old)) {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
if (debug & 1)
say ("oldchar = '%c', newchar = '%c'\n",
pch_char (old), pch_char (new));
- fatal ("Out-of-sync patch, lines %ld,%ld -- mangled text or line numbers, maybe?",
- pch_hunk_beg() + old,
- pch_hunk_beg() + new);
+ fatal ("Out-of-sync patch, lines %s,%s -- mangled text or line numbers, maybe?",
+ format_linenum (numbuf0, pch_hunk_beg() + old),
+ format_linenum (numbuf1, pch_hunk_beg() + new));
}
else if (pch_char(new) == '!') {
assert (outstate->after_newline);
if (! copy_till (outstate, where + old - 1))
- return FALSE;
+ return false;
assert (outstate->after_newline);
if (R_do_defines) {
- fprintf (fp, not_defined, R_do_defines);
+ fprintf (fp, 1 + not_defined, R_do_defines);
if (ferror (fp))
write_fatal ();
def_state = IN_IFNDEF;
@@ -1036,25 +1093,24 @@ apply_hunk (outstate, where)
new++;
}
while (pch_char (new) == '!');
- outstate->zero_output = 0;
+ outstate->zero_output = false;
}
else {
assert(pch_char(new) == ' ');
old++;
new++;
if (R_do_defines && def_state != OUTSIDE) {
- fprintf (fp, outstate->after_newline + end_defined,
- R_do_defines);
+ fprintf (fp, outstate->after_newline + end_defined);
if (ferror (fp))
write_fatal ();
- outstate->after_newline = 1;
+ outstate->after_newline = true;
def_state = OUTSIDE;
}
}
}
if (new <= pat_end && pch_char(new) == '+') {
if (! copy_till (outstate, where + old - 1))
- return FALSE;
+ return false;
if (R_do_defines) {
if (def_state == OUTSIDE) {
fprintf (fp, outstate->after_newline + if_defined,
@@ -1067,7 +1123,7 @@ apply_hunk (outstate, where)
}
if (ferror (fp))
write_fatal ();
- outstate->zero_output = 0;
+ outstate->zero_output = false;
}
do
@@ -1075,60 +1131,57 @@ apply_hunk (outstate, where)
if (! outstate->after_newline && putc ('\n', fp) == EOF)
write_fatal ();
outstate->after_newline = pch_write_line (new, fp);
- outstate->zero_output = 0;
+ outstate->zero_output = false;
new++;
}
while (new <= pat_end && pch_char (new) == '+');
}
if (R_do_defines && def_state != OUTSIDE) {
- fprintf (fp, outstate->after_newline + end_defined, R_do_defines);
+ fprintf (fp, outstate->after_newline + end_defined);
if (ferror (fp))
write_fatal ();
- outstate->after_newline = 1;
+ outstate->after_newline = true;
}
- return TRUE;
+ return true;
}
/* Create an output file. */
static FILE *
-create_output_file (name)
- char const *name;
+create_output_file (char const *name, int open_flags)
{
- int fd = create_file (name, O_WRONLY | binary_transput, instat.st_mode);
+ int fd = create_file (name, O_WRONLY | binary_transput | open_flags,
+ instat.st_mode);
FILE *f = fdopen (fd, binary_transput ? "wb" : "w");
if (! f)
- pfatal ("can't create `%s'", name);
+ pfatal ("Can't create file %s", quotearg (name));
return f;
}
/* Open the new file. */
static void
-init_output (name, outstate)
- char const *name;
- struct outstate *outstate;
+init_output (char const *name, int open_flags, struct outstate *outstate)
{
- outstate->ofp = name ? create_output_file (name) : (FILE *) 0;
- outstate->after_newline = 1;
- outstate->zero_output = 1;
+ outstate->ofp = name ? create_output_file (name, open_flags) : (FILE *) 0;
+ outstate->after_newline = true;
+ outstate->zero_output = true;
}
/* Open a file to put hunks we can't locate. */
static void
-init_reject(name)
- char const *name;
+init_reject (void)
{
- rejfp = create_output_file (name);
+ int exclusive = TMPREJNAME_needs_removal ? 0 : O_EXCL;
+ TMPREJNAME_needs_removal = 1;
+ rejfp = create_output_file (TMPREJNAME, exclusive);
}
/* Copy input file to output, up to wherever hunk is to be applied. */
static bool
-copy_till (outstate, lastline)
- register struct outstate *outstate;
- register LINENUM lastline;
+copy_till (register struct outstate *outstate, register LINENUM lastline)
{
register LINENUM R_last_frozen_line = last_frozen_line;
register FILE *fp = outstate->ofp;
@@ -1138,36 +1191,41 @@ copy_till (outstate, lastline)
if (R_last_frozen_line > lastline)
{
say ("misordered hunks! output would be garbled\n");
- return FALSE;
+ return false;
}
while (R_last_frozen_line < lastline)
{
- s = ifetch (++R_last_frozen_line, 0, &size);
+ s = ifetch (++R_last_frozen_line, false, &size);
if (size)
{
if ((! outstate->after_newline && putc ('\n', fp) == EOF)
|| ! fwrite (s, sizeof *s, size, fp))
write_fatal ();
outstate->after_newline = s[size - 1] == '\n';
- outstate->zero_output = 0;
+ outstate->zero_output = false;
}
}
last_frozen_line = R_last_frozen_line;
- return TRUE;
+ return true;
}
/* Finish copying the input file to the output file. */
static bool
-spew_output (outstate)
- struct outstate *outstate;
+spew_output (struct outstate *outstate)
{
if (debug & 256)
- say ("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
+ {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
+ say ("il=%s lfl=%s\n",
+ format_linenum (numbuf0, input_lines),
+ format_linenum (numbuf1, last_frozen_line));
+ }
if (last_frozen_line < input_lines)
if (! copy_till (outstate, input_lines))
- return FALSE;
+ return false;
if (outstate->ofp && ! outfile)
{
@@ -1176,17 +1234,14 @@ spew_output (outstate)
outstate->ofp = 0;
}
- return TRUE;
+ return true;
}
/* Does the patch pattern match at line base+offset? */
static bool
-patch_match (base, offset, prefix_fuzz, suffix_fuzz)
-LINENUM base;
-LINENUM offset;
-LINENUM prefix_fuzz;
-LINENUM suffix_fuzz;
+patch_match (LINENUM base, LINENUM offset,
+ LINENUM prefix_fuzz, LINENUM suffix_fuzz)
{
register LINENUM pline = 1 + prefix_fuzz;
register LINENUM iline;
@@ -1200,23 +1255,20 @@ LINENUM suffix_fuzz;
if (!similar(p, size,
pfetch(pline),
pch_line_len(pline) ))
- return FALSE;
+ return false;
}
else if (size != pch_line_len (pline)
|| memcmp (p, pfetch (pline), size) != 0)
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/* Do two lines match with canonicalized white space? */
static bool
-similar (a, alen, b, blen)
- register char const *a;
- register size_t alen;
- register char const *b;
- register size_t blen;
+similar (register char const *a, register size_t alen,
+ register char const *b, register size_t blen)
{
/* Ignore presence or absence of trailing newlines. */
alen -= alen && a[alen - 1] == '\n';
@@ -1231,7 +1283,7 @@ similar (a, alen, b, blen)
if (alen)
{
if (!(*a == ' ' || *a == '\t'))
- return FALSE;
+ return false;
do a++, alen--;
while (alen && (*a == ' ' || *a == '\t'));
}
@@ -1239,7 +1291,7 @@ similar (a, alen, b, blen)
return alen == blen;
}
else if (!alen || *a++ != *b++)
- return FALSE;
+ return false;
else
alen--, blen--;
}
@@ -1247,8 +1299,8 @@ similar (a, alen, b, blen)
/* Make a temporary file. */
-#if HAVE_MKTEMP
-char *mktemp PARAMS ((char *));
+#if HAVE_MKTEMP && ! HAVE_DECL_MKTEMP && ! defined mktemp
+char *mktemp (char *);
#endif
#ifndef TMPDIR
@@ -1256,8 +1308,7 @@ char *mktemp PARAMS ((char *));
#endif
static char const *
-make_temp (letter)
- int letter;
+make_temp (char letter)
{
char *r;
#if HAVE_MKTEMP
@@ -1267,7 +1318,14 @@ make_temp (letter)
if (!tmpdir) tmpdir = TMPDIR;
r = xmalloc (strlen (tmpdir) + 10);
sprintf (r, "%s/p%cXXXXXX", tmpdir, letter);
+
+ /* It is OK to use mktemp here, since the rest of the code always
+ opens temp files with O_EXCL. It might be better to use mkstemp
+ to avoid some DoS problems, but simply substituting mkstemp for
+ mktemp here will not fix the DoS problems; a more extensive
+ change would be needed. */
mktemp (r);
+
if (!*r)
pfatal ("mktemp");
#else
@@ -1281,8 +1339,7 @@ make_temp (letter)
/* Fatal exit with cleanup. */
void
-fatal_exit (sig)
- int sig;
+fatal_exit (int sig)
{
cleanup ();
@@ -1293,10 +1350,20 @@ fatal_exit (sig)
}
static void
-cleanup ()
+remove_if_needed (char const *name, int volatile *needs_removal)
+{
+ if (*needs_removal)
+ {
+ unlink (name);
+ *needs_removal = 0;
+ }
+}
+
+static void
+cleanup (void)
{
- unlink (TMPINNAME);
- unlink (TMPOUTNAME);
- unlink (TMPPATNAME);
- unlink (TMPREJNAME);
+ remove_if_needed (TMPINNAME, &TMPINNAME_needs_removal);
+ remove_if_needed (TMPOUTNAME, &TMPOUTNAME_needs_removal);
+ remove_if_needed (TMPPATNAME, &TMPPATNAME_needs_removal);
+ remove_if_needed (TMPREJNAME, &TMPREJNAME_needs_removal);
}