- 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:
parent
1e88e37ddc
commit
d3f9c5a1b7
@ -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++) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user