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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to