diff: fix a bug in diffing against stdin. Closes 7784
[oweals/busybox.git] / editors / diff.c
index 8b1e92783c82f8a3cd98220b46aa2ec6fc9f5714..c3ad31bf30cc8fd7b85a542ab6f8cb127638ba1b 100644 (file)
  * 6n words for files of length n.
  */
 
+//config:config DIFF
+//config:      bool "diff"
+//config:      default y
+//config:      help
+//config:        diff compares two files or directories and outputs the
+//config:        differences between them in a form that can be given to
+//config:        the patch command.
+//config:
+//config:config FEATURE_DIFF_LONG_OPTIONS
+//config:      bool "Enable long options"
+//config:      default y
+//config:      depends on DIFF && LONG_OPTS
+//config:      help
+//config:        Enable use of long options.
+//config:
+//config:config FEATURE_DIFF_DIR
+//config:      bool "Enable directory support"
+//config:      default y
+//config:      depends on DIFF
+//config:      help
+//config:        This option enables support for directory and subdirectory
+//config:        comparison.
+
+//kbuild:lib-$(CONFIG_DIFF) += diff.o
+
+//applet:IF_DIFF(APPLET(diff, BB_DIR_USR_BIN, BB_SUID_DROP))
+
 //usage:#define diff_trivial_usage
 //usage:       "[-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2"
 //usage:#define diff_full_usage "\n\n"
 //usage:       "Compare files line by line and output the differences between them.\n"
 //usage:       "This implementation supports unified diffs only.\n"
-//usage:     "\nOptions:"
 //usage:     "\n       -a      Treat all files as text"
 //usage:     "\n       -b      Ignore changes in the amount of whitespace"
 //usage:     "\n       -B      Ignore changes whose lines are all blank"
@@ -694,10 +720,12 @@ static bool diff(FILE* fp[2], char *file[2])
 
 static int diffreg(char *file[2])
 {
-       FILE *fp[2] = { stdin, stdin };
+       FILE *fp[2];
        bool binary = false, differ = false;
        int status = STATUS_SAME, i;
 
+       fp[0] = stdin;
+       fp[1] = stdin;
        for (i = 0; i < 2; i++) {
                int fd = open_or_warn_stdin(file[i]);
                if (fd == -1)
@@ -712,9 +740,10 @@ static int diffreg(char *file[2])
                        unlink(name);
                        if (bb_copyfd_eof(fd, fd_tmp) < 0)
                                xfunc_die();
-                       if (fd) /* Prevents closing of stdin */
+                       if (fd != STDIN_FILENO)
                                close(fd);
                        fd = fd_tmp;
+                       xlseek(fd, 0, SEEK_SET);
                }
                fp[i] = fdopen(fd, "r");
        }
@@ -842,7 +871,7 @@ static void diffdir(char *p[2], const char *s_start)
                 * add_to_dirlist will remove it. */
                list[i].len = strlen(p[i]);
                recursive_action(p[i], ACTION_RECURSE | ACTION_FOLLOWLINKS,
-                                add_to_dirlist, skip_dir, &list[i], 0);
+                               add_to_dirlist, skip_dir, &list[i], 0);
                /* Sort dl alphabetically.
                 * GNU diff does this ignoring any number of trailing dots.
                 * We don't, so for us dotted files almost always are