svn commit: r210578 - head/usr.bin/grep

Gabor Kovesdan gabor at FreeBSD.org
Thu Jul 29 00:11:15 UTC 2010


Author: gabor
Date: Thu Jul 29 00:11:14 2010
New Revision: 210578
URL: http://svn.freebsd.org/changeset/base/210578

Log:
  - Use the traditional behaviour for filename and directory name inclusion
    and exclusion patterns [1]
  - Some improvements on the exiting code, like replacing memcpy with
    strlcpy/strcpy
  
  Approved by:	delphij (mentor)
  Pointed out by:	bf [1], des [1]

Modified:
  head/usr.bin/grep/fastgrep.c
  head/usr.bin/grep/grep.1
  head/usr.bin/grep/grep.c
  head/usr.bin/grep/grep.h
  head/usr.bin/grep/queue.c
  head/usr.bin/grep/util.c

Modified: head/usr.bin/grep/fastgrep.c
==============================================================================
--- head/usr.bin/grep/fastgrep.c	Wed Jul 28 21:52:09 2010	(r210577)
+++ head/usr.bin/grep/fastgrep.c	Thu Jul 29 00:11:14 2010	(r210578)
@@ -119,8 +119,7 @@ fastcomp(fastgrep_t *fg, const char *pat
 	 * string respectively.
 	 */
 	fg->pattern = grep_malloc(fg->len + 1);
-	memcpy(fg->pattern, pat + (bol ? 1 : 0) + wflag, fg->len);
-	fg->pattern[fg->len] = '\0';
+	strlcpy(fg->pattern, pat + (bol ? 1 : 0) + wflag, fg->len + 1);
 
 	/* Look for ways to cheat...er...avoid the full regex engine. */
 	for (i = 0; i < fg->len; i++) {

Modified: head/usr.bin/grep/grep.1
==============================================================================
--- head/usr.bin/grep/grep.1	Wed Jul 28 21:52:09 2010	(r210577)
+++ head/usr.bin/grep/grep.1	Thu Jul 29 00:11:14 2010	(r210578)
@@ -29,7 +29,7 @@
 .\"
 .\"	@(#)grep.1	8.3 (Berkeley) 4/18/94
 .\"
-.Dd September 19, 2009
+.Dd July 28, 2010
 .Dt GREP 1
 .Os
 .Sh NAME
@@ -186,15 +186,31 @@ options are used to specify multiple pat
 or when a pattern begins with a dash
 .Pq Sq - .
 .It Fl Fl exclude
-If
-.Fl R
-is specified, it excludes files matching the given
-filename pattern.
+If specified, it excludes files matching the given
+filename pattern from the search.
+Note that
+.Fl Fl exclude
+patterns take priority over
+.Fl Fl include
+patterns, and if no
+.Fl Fl include
+pattern is specified, all files are searched that are
+not excluded.
+Patterns are matched to the full path specified,
+not only to the filename component.
 .It Fl Fl exclude-dir
 If
 .Fl R
 is specified, it excludes directories matching the
-given filename pattern.
+given filename pattern from the search.
+Note that
+.Fl Fl exclude-dir
+patterns take priority over
+.Fl Fl include-dir
+patterns, and if no
+.Fl Fl include-dir
+pattern is specified, all directories are searched that are
+not excluded.
 .It Fl F , Fl Fl fixed-strings
 Interpret
 .Ar pattern
@@ -238,15 +254,25 @@ By default,
 .Nm grep
 is case sensitive.
 .It Fl Fl include
-If
-.Fl R
-is specified, it includes the files matching the
-given filename pattern.
+If specified, only files matching the
+given filename pattern are searched.
+Note that
+.Fl Fl exclude
+patterns take priority over
+.Fl Fl include
+patterns.
+Patterns are matched to the full path specified,
+not only to the filename component.
 .It Fl Fl include-dir
 If
 .Fl R
-is specified, it includes the directories matching the
-given filename pattern.
+is specified, only directories matching the
+given filename pattern are searched.
+Note that
+.Fl Fl exclude-dir
+patterns take priority over
+.Fl Fl include-dir
+patterns.
 .It Fl J, Fl Fl bz2decompress
 Decompress the
 .Xr bzip2 1

Modified: head/usr.bin/grep/grep.c
==============================================================================
--- head/usr.bin/grep/grep.c	Wed Jul 28 21:52:09 2010	(r210577)
+++ head/usr.bin/grep/grep.c	Thu Jul 29 00:11:14 2010	(r210578)
@@ -85,8 +85,9 @@ regex_t		*r_pattern;
 fastgrep_t	*fg_pattern;
 
 /* Filename exclusion/inclusion patterns */
-unsigned int	 epatterns, epattern_sz;
-struct epat	*epattern;
+unsigned int	 fpatterns, fpattern_sz;
+unsigned int	 dpatterns, dpattern_sz;
+struct epat	*dpattern, *fpattern;
 
 /* For regex errors  */
 char	 re_error[RE_ERROR_BUF + 1];
@@ -112,7 +113,6 @@ bool	 wflag;		/* -w: pattern must start 
 bool	 xflag;		/* -x: pattern must match entire line */
 bool	 lbflag;	/* --line-buffered */
 bool	 nullflag;	/* --null */
-bool	 exclflag;	/* --exclude */
 char	*label;		/* --label */
 const char *color;	/* --color */
 int	 grepbehave = GREP_BASIC;	/* -EFGP: type of the regex */
@@ -122,6 +122,9 @@ int	 devbehave = DEV_READ;		/* -D: handl
 int	 dirbehave = DIR_READ;		/* -dRr: handling of directories */
 int	 linkbehave = LINK_READ;	/* -OpS: handling of symlinks */
 
+bool	 dexclude, dinclude;	/* --exclude amd --include */
+bool	 fexclude, finclude;	/* --exclude-dir and --include-dir */
+
 enum {
 	BIN_OPT = CHAR_MAX + 1,
 	COLOR_OPT,
@@ -234,32 +237,44 @@ add_pattern(char *pat, size_t len)
 		--len;
 	/* pat may not be NUL-terminated */
 	pattern[patterns] = grep_malloc(len + 1);
-	memcpy(pattern[patterns], pat, len);
-	pattern[patterns][len] = '\0';
+	strlcpy(pattern[patterns], pat, len + 1);
 	++patterns;
 }
 
 /*
- * Adds an include/exclude pattern to the internal array.
+ * Adds a file include/exclude pattern to the internal array.
  */
 static void
-add_epattern(char *pat, size_t len, int type, int mode)
+add_fpattern(const char *pat, int mode)
 {
 
 	/* Increase size if necessary */
-	if (epatterns == epattern_sz) {
-		epattern_sz *= 2;
-		epattern = grep_realloc(epattern, ++epattern_sz *
+	if (fpatterns == fpattern_sz) {
+		fpattern_sz *= 2;
+		fpattern = grep_realloc(fpattern, ++fpattern_sz *
 		    sizeof(struct epat));
 	}
-	if (len > 0 && pat[len - 1] == '\n')
-		 --len;
-	epattern[epatterns].pat = grep_malloc(len + 1);
-	memcpy(epattern[epatterns].pat, pat, len);
-	epattern[epatterns].pat[len] = '\0';
-	epattern[epatterns].type = type;
-	epattern[epatterns].mode = mode;
-	++epatterns;
+	fpattern[fpatterns].pat = grep_strdup(pat);
+	fpattern[fpatterns].mode = mode;
+	++fpatterns;
+}
+
+/*
+ * Adds a directory include/exclude pattern to the internal array.
+ */
+static void
+add_dpattern(const char *pat, int mode)
+{
+
+	/* Increase size if necessary */
+	if (dpatterns == dpattern_sz) {
+		dpattern_sz *= 2;
+		dpattern = grep_realloc(dpattern, ++dpattern_sz *
+		    sizeof(struct epat));
+	}
+	dpattern[dpatterns].pat = grep_strdup(pat);
+	dpattern[dpatterns].mode = mode;
+	++dpatterns;
 }
 
 /*
@@ -591,24 +606,20 @@ main(int argc, char *argv[])
 			nullflag = true;
 			break;
 		case R_INCLUDE_OPT:
-			exclflag = true;
-			add_epattern(basename(optarg), strlen(basename(optarg)),
-			    FILE_PAT, INCL_PAT);
+			finclude = true;
+			add_fpattern(optarg, INCL_PAT);
 			break;
 		case R_EXCLUDE_OPT:
-			exclflag = true;
-			add_epattern(basename(optarg), strlen(basename(optarg)),
-			    FILE_PAT, EXCL_PAT);
+			fexclude = true;
+			add_fpattern(optarg, EXCL_PAT);
 			break;
 		case R_DINCLUDE_OPT:
-			exclflag = true;
-			add_epattern(basename(optarg), strlen(basename(optarg)),
-			    DIR_PAT, INCL_PAT);
+			dexclude = true;
+			add_dpattern(optarg, INCL_PAT);
 			break;
 		case R_DEXCLUDE_OPT:
-			exclflag = true;
-			add_epattern(basename(optarg), strlen(basename(optarg)),
-			    DIR_PAT, EXCL_PAT);
+			dinclude = true;
+			add_dpattern(optarg, EXCL_PAT);
 			break;
 		case HELP_OPT:
 		default:
@@ -680,8 +691,11 @@ main(int argc, char *argv[])
 	if (dirbehave == DIR_RECURSE)
 		c = grep_tree(aargv);
 	else 
-		for (c = 0; aargc--; ++aargv)
+		for (c = 0; aargc--; ++aargv) {
+			if ((finclude || fexclude) && !file_matching(*aargv))
+				continue;
 			c+= procfile(*aargv);
+		}
 
 #ifndef WITHOUT_NLS
 	catclose(catalog);

Modified: head/usr.bin/grep/grep.h
==============================================================================
--- head/usr.bin/grep/grep.h	Wed Jul 28 21:52:09 2010	(r210577)
+++ head/usr.bin/grep/grep.h	Thu Jul 29 00:11:14 2010	(r210578)
@@ -71,8 +71,6 @@ extern const char		*errstr[];
 #define LINK_EXPLICIT	1
 #define LINK_SKIP	2
 
-#define FILE_PAT	0
-#define DIR_PAT		1
 #define EXCL_PAT	0
 #define INCL_PAT	1
 
@@ -98,7 +96,6 @@ struct str {
 struct epat {
 	char		*pat;
 	int		 mode;
-	int		 type;
 };
 
 typedef struct {
@@ -118,7 +115,7 @@ extern int	 cflags, eflags;
 extern bool	 Eflag, Fflag, Gflag, Hflag, Lflag,
 		 bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag,
 		 qflag, sflag, vflag, wflag, xflag;
-extern bool	 exclflag, nullflag;
+extern bool	 dexclude, dinclude, fexclude, finclude, nullflag;
 extern unsigned long long Aflag, Bflag, mcount;
 extern char	*label;
 extern const char *color;
@@ -126,9 +123,9 @@ extern int	 binbehave, devbehave, dirbeh
 
 extern bool	 first, matchall, notfound, prev;
 extern int	 tail;
-extern unsigned int epatterns, patterns;
+extern unsigned int dpatterns, fpatterns, patterns;
 extern char    **pattern;
-extern struct epat *epattern;
+extern struct epat *dpattern, *fpattern;
 extern regex_t	*er_pattern, *r_pattern;
 extern fastgrep_t *fg_pattern;
 
@@ -137,11 +134,14 @@ extern fastgrep_t *fg_pattern;
 extern char	 re_error[RE_ERROR_BUF + 1];	/* Seems big enough */
 
 /* util.c */
+bool	 dir_matching(const char *dname);
+bool	 file_matching(const char *fname);
 int	 procfile(const char *fn);
 int	 grep_tree(char **argv);
 void	*grep_malloc(size_t size);
 void	*grep_calloc(size_t nmemb, size_t size);
 void	*grep_realloc(void *ptr, size_t size);
+char	*grep_strdup(const char *str);
 void	 printline(struct str *line, int sep, regmatch_t *matches, int m);
 
 /* queue.c */

Modified: head/usr.bin/grep/queue.c
==============================================================================
--- head/usr.bin/grep/queue.c	Wed Jul 28 21:52:09 2010	(r210577)
+++ head/usr.bin/grep/queue.c	Thu Jul 29 00:11:14 2010	(r210578)
@@ -60,7 +60,7 @@ enqueue(struct str *x)
 	item->data.len = x->len;
 	item->data.line_no = x->line_no;
 	item->data.off = x->off;
-	memcpy(item->data.dat, x->dat, x->len);
+	strcpy(item->data.dat, x->dat);
 	item->data.file = x->file;
 
 	STAILQ_INSERT_TAIL(&queue, item, list);

Modified: head/usr.bin/grep/util.c
==============================================================================
--- head/usr.bin/grep/util.c	Wed Jul 28 21:52:09 2010	(r210577)
+++ head/usr.bin/grep/util.c	Thu Jul 29 00:11:14 2010	(r210578)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <fnmatch.h>
 #include <fts.h>
 #include <libgen.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -51,6 +52,45 @@ __FBSDID("$FreeBSD$");
 static int	 linesqueued;
 static int	 procline(struct str *l, int);
 
+bool
+file_matching(const char *fname)
+{
+	bool ret;
+
+	ret = finclude ? false : true;
+
+	for (unsigned int i = 0; i < fpatterns; ++i) {
+		if (fnmatch(fpattern[i].pat,
+		    fname, 0) == 0 || fnmatch(fpattern[i].pat,
+		    basename(fname), 0) == 0) {
+			if (fpattern[i].mode == EXCL_PAT)
+				return (false);
+			else
+				ret = true;
+		}
+	}
+	return (ret);
+}
+
+bool
+dir_matching(const char *dname)
+{
+	bool ret;
+
+	ret = dinclude ? false : true;
+
+	for (unsigned int i = 0; i < dpatterns; ++i) {
+		if (dname != NULL &&
+		    fnmatch(dname, dpattern[i].pat, 0) == 0) {
+			if (dpattern[i].mode == EXCL_PAT)
+				return (false);
+			else
+				ret = true;
+		}
+	}
+	return (ret);
+}
+
 /*
  * Processes a directory when a recursive search is performed with
  * the -R option.  Each appropriate file is passed to procfile().
@@ -61,7 +101,6 @@ grep_tree(char **argv)
 	FTS *fts;
 	FTSENT *p;
 	char *d, *dir = NULL;
-	unsigned int i;
 	int c, fts_flags;
 	bool ok;
 
@@ -102,30 +141,19 @@ grep_tree(char **argv)
 		default:
 			/* Check for file exclusion/inclusion */
 			ok = true;
-			if (exclflag) {
+			if (dexclude || dinclude) {
 				if ((d = strrchr(p->fts_path, '/')) != NULL) {
 					dir = grep_malloc(sizeof(char) *
 					    (d - p->fts_path + 2));
 					strlcpy(dir, p->fts_path,
 					    (d - p->fts_path + 1));
 				}
-				for (i = 0; i < epatterns; ++i) {
-					switch(epattern[i].type) {
-					case FILE_PAT:
-						if (fnmatch(epattern[i].pat,
-						    basename(p->fts_path), 0) == 0)
-							ok = epattern[i].mode != EXCL_PAT;
-						break;
-					case DIR_PAT:
-						if (dir != NULL && strstr(dir,
-						    epattern[i].pat) != NULL)
-							ok = epattern[i].mode != EXCL_PAT;
-						break;
-					}
-				}
+				ok = dir_matching(dir);
 				free(dir);
 				dir = NULL;
 			}
+			if (fexclude || finclude)
+				ok &= file_matching(p->fts_path);
 
 			if (ok)
 				c += procfile(p->fts_path);
@@ -409,6 +437,19 @@ grep_realloc(void *ptr, size_t size)
 }
 
 /*
+ * Safe strdup() for internal use.
+ */
+char *
+grep_strdup(const char *str)
+{
+	char *ret;
+
+	if ((ret = strdup(str)) == NULL)
+		err(2, "strdup");
+	return (ret);
+}
+
+/*
  * Prints a matching line according to the command line options.
  */
 void


More information about the svn-src-all mailing list