diff: fix -N and nonexistent files. Closes 7454
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 5 May 2017 16:39:22 +0000 (18:39 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 5 May 2017 16:39:22 +0000 (18:39 +0200)
function                                             old     new   delta
diffreg                                             1253    1310     +57
diff_main                                           1329    1355     +26
create_J                                            1819    1821      +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 85/0)               Total: 85 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
editors/diff.c

index 3304edb26f9a4c7703ceb1e3a262526b5c685de9..7687518f3be072b7434fda06e3dcba3daaa3ee6c 100644 (file)
@@ -715,9 +715,19 @@ static int diffreg(char *file[2])
        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.
                 */
@@ -978,17 +988,23 @@ int diff_main(int argc UNUSED_PARAM, char **argv)
        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");