From owner-svn-src-head@FreeBSD.ORG Thu Jul 29 00:11:15 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 175BD106566B; Thu, 29 Jul 2010 00:11:15 +0000 (UTC) (envelope-from gabor@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 047F88FC12; Thu, 29 Jul 2010 00:11:15 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o6T0BEev072523; Thu, 29 Jul 2010 00:11:14 GMT (envelope-from gabor@svn.freebsd.org) Received: (from gabor@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o6T0BE0l072516; Thu, 29 Jul 2010 00:11:14 GMT (envelope-from gabor@svn.freebsd.org) Message-Id: <201007290011.o6T0BE0l072516@svn.freebsd.org> From: Gabor Kovesdan Date: Thu, 29 Jul 2010 00:11:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r210578 - head/usr.bin/grep X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Jul 2010 00:11:15 -0000 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 #include #include +#include #include #include #include @@ -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