aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-08-15 00:39:30 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2020-08-15 00:39:30 +0200
commita77f3ecf68c63081934f5e0800eab80b5098bb24 (patch)
treeb8d9b333378f24b92feb2c38ea1552e465dca96d
parent5c69ad0ecdc18cf51b312c7c82848f4438fe1c8d (diff)
downloadbusybox-w32-a77f3ecf68c63081934f5e0800eab80b5098bb24.tar.gz
busybox-w32-a77f3ecf68c63081934f5e0800eab80b5098bb24.tar.bz2
busybox-w32-a77f3ecf68c63081934f5e0800eab80b5098bb24.zip
grep: for -L, exitcode 0 means files *without* matches were found, closes 13151
This is a recent change in GNU grep as well (after 3.1) function old new delta grep_file 1215 1228 +13 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--findutils/grep.c29
-rwxr-xr-xtestsuite/grep.tests8
2 files changed, 22 insertions, 15 deletions
diff --git a/findutils/grep.c b/findutils/grep.c
index 55e9c0a8f..b456ed467 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -167,13 +167,11 @@ enum {
167 OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, 167 OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0,
168}; 168};
169 169
170#define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l)
171#define PRINT_LINE_NUM (option_mask32 & OPT_n) 170#define PRINT_LINE_NUM (option_mask32 & OPT_n)
172#define BE_QUIET (option_mask32 & OPT_q) 171#define BE_QUIET (option_mask32 & OPT_q)
173#define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s) 172#define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s)
174#define PRINT_MATCH_COUNTS (option_mask32 & OPT_c) 173#define PRINT_MATCH_COUNTS (option_mask32 & OPT_c)
175#define FGREP_FLAG (option_mask32 & OPT_F) 174#define FGREP_FLAG (option_mask32 & OPT_F)
176#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L)
177#define NUL_DELIMITED (option_mask32 & OPT_z) 175#define NUL_DELIMITED (option_mask32 & OPT_z)
178 176
179struct globals { 177struct globals {
@@ -476,13 +474,13 @@ static int grep_file(FILE *file)
476 * even if errors were detected" */ 474 * even if errors were detected" */
477 exit(EXIT_SUCCESS); 475 exit(EXIT_SUCCESS);
478 } 476 }
479 /* if we're just printing filenames, we stop after the first match */ 477 /* -l "print filenames with matches": stop after the first match */
480 if (PRINT_FILES_WITH_MATCHES) { 478 if (option_mask32 & OPT_l) {
481 puts(cur_file); 479 puts(cur_file);
482 /* fall through to "return 1" */ 480 return 1;
483 } 481 }
484 /* OPT_L aka PRINT_FILES_WITHOUT_MATCHES: return early */ 482 /* -L "print filenames without matches": return early too */
485 return 1; /* one match */ 483 return 0; /* 0: we do not print fname, hence it's "not a match" */
486 } 484 }
487 485
488#if ENABLE_FEATURE_GREP_CONTEXT 486#if ENABLE_FEATURE_GREP_CONTEXT
@@ -602,15 +600,16 @@ static int grep_file(FILE *file)
602 printf("%d\n", nmatches); 600 printf("%d\n", nmatches);
603 } 601 }
604 602
605 /* grep -L: print just the filename */ 603 /* grep -L: "print filenames without matches" */
606 if (PRINT_FILES_WITHOUT_MATCHES) { 604 if (option_mask32 & OPT_L) {
607 /* nmatches is zero, no need to check it: 605 /* nmatches is zero, no need to check it:
608 * we return 1 early if we detected a match 606 * we return 0 early if -L and we detect a match
609 * and PRINT_FILES_WITHOUT_MATCHES is set */ 607 */
610 puts(cur_file); 608 puts(cur_file);
609 return 1; /* 1: we printed fname, hence it's "a match" */
611 } 610 }
612 611
613 return nmatches; 612 return nmatches != 0; /* we return not a count, but a boolean */
614} 613}
615 614
616#if ENABLE_FEATURE_CLEAN_UP 615#if ENABLE_FEATURE_CLEAN_UP
@@ -687,7 +686,7 @@ static int FAST_FUNC file_action_grep(const char *filename,
687 return 0; 686 return 0;
688 } 687 }
689 cur_file = filename; 688 cur_file = filename;
690 *(int*)matched += grep_file(file); 689 *(int*)matched |= grep_file(file);
691 fclose(file); 690 fclose(file);
692 return 1; 691 return 1;
693} 692}
@@ -844,7 +843,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
844 if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { 843 if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) {
845 if (!(option_mask32 & OPT_h)) 844 if (!(option_mask32 & OPT_h))
846 print_filename = 1; 845 print_filename = 1;
847 matched += grep_dir(cur_file); 846 matched |= grep_dir(cur_file);
848 goto grep_done; 847 goto grep_done;
849 } 848 }
850 } 849 }
@@ -857,7 +856,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
857 continue; 856 continue;
858 } 857 }
859 } 858 }
860 matched += grep_file(file); 859 matched |= grep_file(file);
861 fclose_if_not_stdin(file); 860 fclose_if_not_stdin(file);
862 grep_done: ; 861 grep_done: ;
863 } while (*argv && *++argv); 862 } while (*argv && *++argv);
diff --git a/testsuite/grep.tests b/testsuite/grep.tests
index e38278810..66498a989 100755
--- a/testsuite/grep.tests
+++ b/testsuite/grep.tests
@@ -96,6 +96,14 @@ testing "grep -x -F (partial match 1)" "grep -x -F foo input ; echo \$?" \
96testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \ 96testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \
97 "1\n" "bar foo\n" "" 97 "1\n" "bar foo\n" ""
98 98
99# -L "show filenames which do not match" has inverted exitcode (if it printed something, it's "success")
100testing "grep -L exitcode 0" "grep -L qwe input; echo \$?" \
101 "input\n0\n" "asd\n" ""
102testing "grep -L exitcode 0 #2" "grep -L qwe input -; echo \$?" \
103 "(standard input)\n0\n" "qwe\n" "asd\n"
104testing "grep -L exitcode 1" "grep -L qwe input; echo \$?" \
105 "1\n" "qwe\n" ""
106
99optional EGREP 107optional EGREP
100testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \ 108testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \
101 "b\ar\nfoo\nbaz" 109 "b\ar\nfoo\nbaz"