*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
/*
* The following code uses an algorithm due to Harold Stone,
* which finds a pair of longest identical subsequences in
* 3*(number of k-candidates installed), typically about
* 6n words for files of length n.
*/
-
//config:config DIFF
-//config: bool "diff"
+//config: bool "diff (13 kb)"
//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: 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
//config: help
-//config: This option enables support for directory and subdirectory
-//config: comparison.
-
-//kbuild:lib-$(CONFIG_DIFF) += diff.o
+//config: This option enables support for directory and subdirectory
+//config: comparison.
//applet:IF_DIFF(APPLET(diff, BB_DIR_USR_BIN, BB_SUID_DROP))
+//kbuild:lib-$(CONFIG_DIFF) += diff.o
+
//usage:#define diff_trivial_usage
//usage: "[-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2"
//usage:#define diff_full_usage "\n\n"
fp[0] = stdin;
fp[1] = stdin;
for (i = 0; i < 2; i++) {
- int fd = open_or_warn_stdin(file[i]);
- if (fd == -1)
- goto out;
+ int fd = STDIN_FILENO;
+ if (!LONE_DASH(file[i])) {
+ if (!(option_mask32 & FLAG(N))) {
+ fd = open_or_warn(file[i], O_RDONLY);
+ if (fd == -1)
+ goto out;
+ } else {
+ /* -N: if some file does not exist compare it like empty */
+ fd = open(file[i], O_RDONLY);
+ if (fd == -1)
+ fd = xopen("/dev/null", O_RDONLY);
+ }
+ }
/* Our diff implementation is using seek.
* When we meet non-seekable file, we must make a temp copy.
*/
"starting-file\0" Required_argument "S"
"minimal\0" No_argument "d"
;
+# define GETOPT32 getopt32long
+# define LONGOPTS ,diff_longopts
+#else
+# define GETOPT32 getopt32
+# define LONGOPTS
#endif
int diff_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
INIT_G();
/* exactly 2 params; collect multiple -L <label>; -U N */
- opt_complementary = "=2";
-#if ENABLE_FEATURE_DIFF_LONG_OPTIONS
- applet_long_options = diff_longopts;
-#endif
- getopt32(argv, "abdiL:*NqrsS:tTU:+wupBE",
+ GETOPT32(argv, "^" "abdiL:*NqrsS:tTU:+wupBE" "\0" "=2"
+ LONGOPTS,
&L_arg, &s_start, &opt_U_context);
argv += optind;
while (L_arg)
label[!!label[0]] = llist_pop(&L_arg);
+
+ /* Compat: "diff file name_which_doesnt_exist" exits with 2 */
xfunc_error_retval = 2;
for (i = 0; i < 2; i++) {
file[i] = argv[i];
- /* Compat: "diff file name_which_doesnt_exist" exits with 2 */
if (LONE_DASH(file[i])) {
fstat(STDIN_FILENO, &stb[i]);
gotstdin++;
- } else
+ } else if (option_mask32 & FLAG(N)) {
+ if (stat(file[i], &stb[i]))
+ xstat("/dev/null", &stb[i]);
+ } else {
xstat(file[i], &stb[i]);
+ }
}
xfunc_error_retval = 1;
+
if (gotstdin && (S_ISDIR(stb[0].st_mode) || S_ISDIR(stb[1].st_mode)))
bb_error_msg_and_die("can't compare stdin to a directory");