summaryrefslogtreecommitdiff
path: root/contrib/patch/pch.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/patch/pch.c')
-rw-r--r--contrib/patch/pch.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/contrib/patch/pch.c b/contrib/patch/pch.c
index 64a627a7f0fb..f5c0ce0dd71d 100644
--- a/contrib/patch/pch.c
+++ b/contrib/patch/pch.c
@@ -1,6 +1,6 @@
/* reading patches */
-/* $Id: pch.c,v 1.23 1997/06/17 06:52:12 eggert Exp $ */
+/* $Id: pch.c,v 1.26 1997/07/21 17:59:46 eggert Exp $ */
/*
Copyright 1986, 1987, 1988 Larry Wall
@@ -38,6 +38,7 @@ If not, write to the Free Software Foundation,
static FILE *pfp; /* patch file pointer */
static int p_says_nonexistent[2]; /* [0] for old file, [1] for new;
value is 0 for nonempty, 1 for empty, 2 for nonexistent */
+static int p_rfc934_nesting; /* RFC 934 nesting level */
static time_t p_timestamp[2]; /* timestamps in patch headers */
static off_t p_filesize; /* size of the patch file */
static LINENUM p_first; /* 1st line number */
@@ -67,11 +68,11 @@ enum nametype { OLD, NEW, INDEX, NONE };
static enum diff intuit_diff_type PARAMS ((void));
static enum nametype best_name PARAMS ((char * const *, int const *));
static int prefix_components PARAMS ((char *, int));
-static size_t pget_line PARAMS ((int));
+static size_t pget_line PARAMS ((int, int));
static size_t get_line PARAMS ((void));
static bool incomplete_line PARAMS ((void));
static bool grow_hunkmax PARAMS ((void));
-static void malformed PARAMS ((void));
+static void malformed PARAMS ((void)) __attribute__ ((noreturn));
static void next_intuit_at PARAMS ((file_offset, LINENUM));
static void skip_to PARAMS ((file_offset, LINENUM));
@@ -142,6 +143,8 @@ open_patch_file(filename)
pfatal ("fstat");
}
p_filesize = st.st_size;
+ if (p_filesize != (file_offset) p_filesize)
+ fatal ("patch file is too long");
next_intuit_at (file_pos, (LINENUM) 1);
set_hunkmax();
}
@@ -197,6 +200,8 @@ there_is_another_patch()
say (p_base
? " Ignoring the trailing garbage.\ndone\n"
: " I can't seem to find a patch in there anywhere.\n");
+ if (! p_base && p_filesize)
+ fatal ("Only garbage was found in the patch input.");
return FALSE;
}
if (skip_rest_of_patch)
@@ -219,8 +224,13 @@ there_is_another_patch()
if (p_indent)
say ("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
if (! inname)
- say ("can't find file to patch at input line %ld\n",
- p_sline);
+ {
+ say ("can't find file to patch at input line %ld\n",
+ p_sline);
+ say (strippath == INT_MAX
+ ? "Perhaps you should have used the -p or --strip option?\n"
+ : "Perhaps you used the wrong -p or --strip option?\n");
+ }
}
skip_to(p_start,p_sline);
@@ -286,6 +296,7 @@ intuit_diff_type()
version_controlled[OLD] = -1;
version_controlled[NEW] = -1;
version_controlled[INDEX] = -1;
+ p_rfc934_nesting = 0;
p_timestamp[OLD] = p_timestamp[NEW] = (time_t) -1;
p_says_nonexistent[OLD] = p_says_nonexistent[NEW] = 0;
Fseek (pfp, p_base, SEEK_SET);
@@ -296,7 +307,7 @@ intuit_diff_type()
stars_last_line = stars_this_line;
this_line = file_tell (pfp);
indent = 0;
- if (! pget_line (0)) {
+ if (! pget_line (0, 0)) {
if (first_command_line >= 0) {
/* nothing but deletes!? */
p_start = first_command_line;
@@ -307,8 +318,7 @@ intuit_diff_type()
else {
p_start = this_line;
p_sline = p_input_line;
- retval = NO_DIFF;
- goto scan_exit;
+ return NO_DIFF;
}
}
for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
@@ -328,8 +338,6 @@ intuit_diff_type()
}
if (!stars_last_line && strnEQ(s, "*** ", 4))
name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
- else if (strnEQ(s, "--- ", 4))
- name[NEW] = fetchname (s+4, strippath, &p_timestamp[NEW]);
else if (strnEQ(s, "+++ ", 4))
/* Swap with NEW below. */
name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
@@ -349,7 +357,21 @@ intuit_diff_type()
revision = savestr (revision);
*t = oldc;
}
- }
+ } else
+ {
+ for (t = s; t[0] == '-' && t[1] == ' '; t += 2)
+ continue;
+ if (strnEQ(t, "--- ", 4))
+ {
+ time_t timestamp = (time_t) -1;
+ name[NEW] = fetchname (t+4, strippath, &timestamp);
+ if (timestamp != (time_t) -1)
+ {
+ p_timestamp[NEW] = timestamp;
+ p_rfc934_nesting = (t - s) >> 1;
+ }
+ }
+ }
if ((diff_type == NO_DIFF || diff_type == ED_DIFF) &&
first_command_line >= 0 &&
strEQ(s, ".\n") ) {
@@ -1424,19 +1446,21 @@ another_hunk (difftype, rev)
static size_t
get_line ()
{
- return pget_line (p_indent);
+ return pget_line (p_indent, p_rfc934_nesting);
}
/* Input a line from the patch file, worrying about indentation.
Strip up to INDENT characters' worth of leading indentation.
+ Then remove up to RFC934_NESTING instances of leading "- ".
Ignore any partial lines at end of input, but warn about them.
Succeed if a line was read; it is terminated by "\n\0" for convenience.
Return the number of characters read, including '\n' but not '\0'.
Return -1 if we ran out of memory. */
static size_t
-pget_line (indent)
+pget_line (indent, rfc934_nesting)
int indent;
+ int rfc934_nesting;
{
register FILE *fp = pfp;
register int c;
@@ -1465,6 +1489,23 @@ pget_line (indent)
i = 0;
b = buf;
+
+ while (c == '-' && 0 <= --rfc934_nesting)
+ {
+ c = getc (fp);
+ if (c == EOF)
+ goto patch_ends_in_middle_of_line;
+ if (c != ' ')
+ {
+ i = 1;
+ b[0] = '-';
+ break;
+ }
+ c = getc (fp);
+ if (c == EOF)
+ goto patch_ends_in_middle_of_line;
+ }
+
s = bufsize;
for (;;)
@@ -1487,17 +1528,18 @@ pget_line (indent)
break;
c = getc (fp);
if (c == EOF)
- {
- if (ferror (fp))
- read_fatal ();
- say ("patch unexpectedly ends in middle of line\n");
- return 0;
- }
+ goto patch_ends_in_middle_of_line;
}
b[i] = '\0';
p_input_line++;
return i;
+
+ patch_ends_in_middle_of_line:
+ if (ferror (fp))
+ read_fatal ();
+ say ("patch unexpectedly ends in middle of line\n");
+ return 0;
}
static bool