[PATCH 6/7] grep: Skip grepping symlinks to directories

James Clarke jrtc27 at jrtc27.com
Sat Oct 7 17:53:24 UTC 2017


When grep is passed -r, recursive_action will treat any symlinks to
directories not in the root as normal files, since it lstat's them and
is therefore told they are not directories. However, file_action_grep
will still try to fopen and read from them to see whether they match,
which varies in behaviour across platforms. Linux will give EISDIR and
thus grep will not find any matching lines, but FreeBSD will give the
raw contents of the directory itself, which may match the given pattern.
Also, if grep is passed -c, it will even print a count for these
symlinks, even on Linux.

Since this recursive_action behaviour is required for the correct
functioning of other applets, such as tar, grep should handle this
special case and skip any such symlinks.

Signed-off-by: James Clarke <jrtc27 at jrtc27.com>
---
 findutils/grep.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/findutils/grep.c b/findutils/grep.c
index f72175afb..0cb0aac64 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -639,11 +639,29 @@ static void load_regexes_from_file(llist_t *fopt)
 }
 
 static int FAST_FUNC file_action_grep(const char *filename,
-			struct stat *statbuf UNUSED_PARAM,
+			struct stat *statbuf,
 			void* matched,
 			int depth UNUSED_PARAM)
 {
-	FILE *file = fopen_for_read(filename);
+	FILE *file;
+	struct stat statbufFollow;
+
+	/* If we are given a link to a directory, we should bail out now, rather
+	 * than trying to open the "file" and hoping getline gives us nothing,
+	 * since that is not portable across operating systems (FreeBSD for example
+	 * will return the raw directory contents). */
+	if (S_ISLNK(statbuf->st_mode)) {
+		if (stat(filename, &statbufFollow) < 0) {
+			if (!SUPPRESS_ERR_MSGS)
+				bb_simple_perror_msg(filename);
+			return 0;
+		}
+
+		if (S_ISDIR(statbufFollow.st_mode))
+			return 1;
+	}
+
+	file = fopen_for_read(filename);
 	if (file == NULL) {
 		if (!SUPPRESS_ERR_MSGS)
 			bb_simple_perror_msg(filename);
-- 
2.14.1



More information about the busybox mailing list