*/
//config:config PATCH
-//config: bool "patch"
+//config: bool "patch (9.1 kb)"
//config: default y
//config: help
-//config: Apply a unified diff formatted patch.
+//config: Apply a unified diff formatted patch.
//applet:IF_PATCH(APPLET(patch, BB_DIR_USR_BIN, BB_SUID_DROP))
// Figure out which line of hunk to compare with next. (Skip lines
// of the hunk we'd be adding.)
while (plist && *plist->data == "+-"[reverse]) {
- if (data && !strcmp(data, plist->data+1)) {
+ if (data && strcmp(data, plist->data+1) == 0) {
if (!backwarn) {
backwarn = TT.linenum;
if (option_mask32 & FLAG_IGNORE) {
// out of buffer.
for (;;) {
+ while (plist && *plist->data == "+-"[reverse]) {
+ if (strcmp(check->data, plist->data+1) == 0
+ && !backwarn
+ ) {
+ backwarn = TT.linenum;
+ if (option_mask32 & FLAG_IGNORE) {
+ dummy_revert = 1;
+ reverse ^= 1;
+ }
+ }
+ plist = plist->next;
+ }
if (!plist || strcmp(check->data, plist->data+1)) {
// Match failed. Write out first line of buffered data and
// recheck remaining buffered data for a new match.
if (PATCH_DEBUG)
- fdprintf(2, "NOT: %s\n", plist->data);
+ fdprintf(2, "NOT: %s\n", plist ? plist->data : "EOF");
TT.state = 3;
check = buf;
// state 1: Found +++ file indicator, look for @@
// state 2: In hunk: counting initial context lines
// state 3: In hunk: getting body
+// Like GNU patch, we don't require a --- line before the +++, and
+// also allow the --- after the +++ line.
int patch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int patch_main(int argc UNUSED_PARAM, char **argv)
xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO);
}
}
- if (argv[0]) {
- oldname = xstrdup(argv[0]);
- newname = xstrdup(argv[0]);
- }
// Loop through the lines in the patch
for(;;) {
}
// Open a new file?
- if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) {
+ if (is_prefixed_with(patchline, "--- ") || is_prefixed_with(patchline, "+++ ")) {
char *s, **name = reverse ? &newname : &oldname;
int i;
// Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@
// but a missing ,value means the value is 1.
- } else if (state == 1 && !strncmp("@@ -", patchline, 4)) {
+ } else if (state == 1 && is_prefixed_with(patchline, "@@ -")) {
int i;
char *s = patchline+4;
TT.context = 0;
state = 2;
+ // If the --- line is missing or malformed, either oldname
+ // or (for -R) newname could be NULL -- but not both. Like
+ // GNU patch, proceed based on the +++ line, and avoid SEGVs.
+ if (!oldname)
+ oldname = xstrdup("MISSING_FILENAME");
+ if (!newname)
+ newname = xstrdup("MISSING_FILENAME");
+
// If this is the first hunk, open the file.
if (TT.filein == -1) {
int oldsum, newsum, empty = 0;
// We're deleting oldname if new file is /dev/null (before -p)
// or if new hunk is empty (zero context) after patching
- if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) {
+ if (strcmp(name, "/dev/null") == 0 || !(reverse ? oldsum : newsum)) {
name = reverse ? newname : oldname;
- empty++;
+ empty = 1;
}
- // handle -p path truncation.
+ // Handle -p path truncation.
for (i = 0, s = name; *s;) {
if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i)
break;
i++;
name = s;
}
+ // If "patch FILE_TO_PATCH", completely ignore name from patch
+ if (argv[0])
+ name = argv[0];
if (empty) {
// File is empty after the patches have been applied
struct stat statbuf;
// If the old file was null, we're creating a new one.
- if (!strcmp(oldname, "/dev/null") || !oldsum) {
+ if (strcmp(oldname, "/dev/null") == 0 || !oldsum) {
printf("creating %s\n", name);
s = strrchr(name, '/');
if (s) {