diff options
author | gabor <gabor@FreeBSD.org> | 2010-07-29 00:11:14 +0000 |
---|---|---|
committer | gabor <gabor@FreeBSD.org> | 2010-07-29 00:11:14 +0000 |
commit | d3f9c5a1b7e9d966652b4c688f2558356eb149d3 (patch) | |
tree | 1e1d5961f5ee38199f4b4fbd83cfffc86339e1c5 /usr.bin/grep | |
parent | 1e88e37ddc5c0145f7fc505a213d255161668879 (diff) | |
download | FreeBSD-src-d3f9c5a1b7e9d966652b4c688f2558356eb149d3.zip FreeBSD-src-d3f9c5a1b7e9d966652b4c688f2558356eb149d3.tar.gz |
- 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]
Diffstat (limited to 'usr.bin/grep')
-rw-r--r-- | usr.bin/grep/fastgrep.c | 3 | ||||
-rw-r--r-- | usr.bin/grep/grep.1 | 50 | ||||
-rw-r--r-- | usr.bin/grep/grep.c | 76 | ||||
-rw-r--r-- | usr.bin/grep/grep.h | 12 | ||||
-rw-r--r-- | usr.bin/grep/queue.c | 2 | ||||
-rw-r--r-- | usr.bin/grep/util.c | 73 |
6 files changed, 148 insertions, 68 deletions
diff --git a/usr.bin/grep/fastgrep.c b/usr.bin/grep/fastgrep.c index 265e457..5239a0e1 100644 --- a/usr.bin/grep/fastgrep.c +++ b/usr.bin/grep/fastgrep.c @@ -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++) { diff --git a/usr.bin/grep/grep.1 b/usr.bin/grep/grep.1 index 1f96a3e..38f9639 100644 --- a/usr.bin/grep/grep.1 +++ b/usr.bin/grep/grep.1 @@ -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 patterns, 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 diff --git a/usr.bin/grep/grep.c b/usr.bin/grep/grep.c index d8fc5c6..1de68d0 100644 --- a/usr.bin/grep/grep.c +++ b/usr.bin/grep/grep.c @@ -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 and end on word boundaries */ 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: handling of devices */ 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); diff --git a/usr.bin/grep/grep.h b/usr.bin/grep/grep.h index 4a2d43f..bb5e5f9 100644 --- a/usr.bin/grep/grep.h +++ b/usr.bin/grep/grep.h @@ -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, dirbehave, filebehave, grepbehave, linkbehave; 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 */ diff --git a/usr.bin/grep/queue.c b/usr.bin/grep/queue.c index dcef7f8..29a6c2f 100644 --- a/usr.bin/grep/queue.c +++ b/usr.bin/grep/queue.c @@ -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); diff --git a/usr.bin/grep/util.c b/usr.bin/grep/util.c index 4de36a7..95a68b3 100644 --- a/usr.bin/grep/util.c +++ b/usr.bin/grep/util.c @@ -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 |