- 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]
This commit is contained in:
gabor 2010-07-29 00:11:14 +00:00
parent 1e88e37ddc
commit d3f9c5a1b7
6 changed files with 148 additions and 68 deletions

View File

@ -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++) {

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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);
@ -408,6 +436,19 @@ grep_realloc(void *ptr, size_t size)
return (ptr);
}
/*
* 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.
*/