- Revert strlcpy() changes to memcpy() because it's more efficient and
former may be safer but in this case it doesn't add extra safety [1] - Fix -w option [2] - Fix handling of GREP_OPTIONS [3] - Fix --line-buffered - Make stdin input imply --line-buffered so that tail -f can be piped to grep [4] - Imply -h if single file is grepped, this is the GNU behaviour - Reduce locking overhead to gain some more performance [5] - Inline some functions to help the compiler better optimize the code - Use shortcut for empty files [6] PR: bin/149425 [6] Prodded by: jilles [1] Reported by: Alex Kozlov <spam@rm-rf.kiev.ua> [2] [3], swell.k@gmail.com [2], poyopoyo@puripuri.plala.or.jp [4] Submitted by: scf [5], Shuichi KITAGUCHI <ki@hh.iij4u.or.jp> [6] Approved by: delphij (mentor)
This commit is contained in:
parent
0f7e249192
commit
59218eb770
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=211364
@ -46,8 +46,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "grep.h"
|
||||
|
||||
static int grep_cmp(const unsigned char *, const unsigned char *, size_t);
|
||||
static void grep_revstr(unsigned char *, int);
|
||||
static inline int grep_cmp(const unsigned char *, const unsigned char *, size_t);
|
||||
static inline void grep_revstr(unsigned char *, int);
|
||||
|
||||
void
|
||||
fgrepcomp(fastgrep_t *fg, const char *pat)
|
||||
@ -273,7 +273,7 @@ grep_search(fastgrep_t *fg, unsigned char *data, size_t len, regmatch_t *pmatch)
|
||||
* Returns: i >= 0 on failure (position that it failed)
|
||||
* -1 on success
|
||||
*/
|
||||
static int
|
||||
static inline int
|
||||
grep_cmp(const unsigned char *pat, const unsigned char *data, size_t len)
|
||||
{
|
||||
size_t size;
|
||||
@ -318,7 +318,7 @@ grep_cmp(const unsigned char *pat, const unsigned char *data, size_t len)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
grep_revstr(unsigned char *str, int len)
|
||||
{
|
||||
int i;
|
||||
|
@ -67,14 +67,14 @@ static int bzerr;
|
||||
* Returns a single character according to the file type.
|
||||
* Returns -1 on failure.
|
||||
*/
|
||||
int
|
||||
static inline int
|
||||
grep_fgetc(struct file *f)
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
switch (filebehave) {
|
||||
case FILE_STDIO:
|
||||
return (fgetc(f->f));
|
||||
return (getc_unlocked(f->f));
|
||||
case FILE_GZIP:
|
||||
return (gzgetc(f->gzf));
|
||||
case FILE_BZIP:
|
||||
@ -92,13 +92,13 @@ grep_fgetc(struct file *f)
|
||||
* Returns true if the file position is a EOF, returns false
|
||||
* otherwise.
|
||||
*/
|
||||
int
|
||||
static inline int
|
||||
grep_feof(struct file *f)
|
||||
{
|
||||
|
||||
switch (filebehave) {
|
||||
case FILE_STDIO:
|
||||
return (feof(f->f));
|
||||
return (feof_unlocked(f->f));
|
||||
case FILE_GZIP:
|
||||
return (gzeof(f->gzf));
|
||||
case FILE_BZIP:
|
||||
@ -131,6 +131,9 @@ grep_fgetln(struct file *f, size_t *len)
|
||||
st.st_size = MAXBUFSIZ;
|
||||
else if (stat(fname, &st) != 0)
|
||||
err(2, NULL);
|
||||
/* no need to allocate buffer. */
|
||||
if (st.st_size == 0)
|
||||
return (NULL);
|
||||
|
||||
bufsiz = (MAXBUFSIZ > (st.st_size * PREREAD_M)) ?
|
||||
(st.st_size / 2) : MAXBUFSIZ;
|
||||
@ -142,6 +145,8 @@ grep_fgetln(struct file *f, size_t *len)
|
||||
if (ch == EOF)
|
||||
break;
|
||||
binbuf[i++] = ch;
|
||||
if ((ch == '\n') && lbflag)
|
||||
break;
|
||||
}
|
||||
|
||||
f->binary = memchr(binbuf, (filebehave != FILE_GZIP) ?
|
||||
@ -184,11 +189,16 @@ grep_stdin_open(void)
|
||||
{
|
||||
struct file *f;
|
||||
|
||||
/* Processing stdin implies --line-buffered for tail -f to work. */
|
||||
lbflag = true;
|
||||
|
||||
snprintf(fname, sizeof fname, "%s", getstr(1));
|
||||
|
||||
f = grep_malloc(sizeof *f);
|
||||
|
||||
binbuf = NULL;
|
||||
if ((f->f = fdopen(STDIN_FILENO, "r")) != NULL) {
|
||||
flockfile(f->f);
|
||||
f->stdin = true;
|
||||
return (f);
|
||||
}
|
||||
@ -209,11 +219,14 @@ grep_open(const char *path)
|
||||
|
||||
f = grep_malloc(sizeof *f);
|
||||
|
||||
binbuf = NULL;
|
||||
f->stdin = false;
|
||||
switch (filebehave) {
|
||||
case FILE_STDIO:
|
||||
if ((f->f = fopen(path, "r")) != NULL)
|
||||
if ((f->f = fopen(path, "r")) != NULL) {
|
||||
flockfile(f->f);
|
||||
return (f);
|
||||
}
|
||||
break;
|
||||
case FILE_GZIP:
|
||||
if ((f->gzf = gzopen(fname, "r")) != NULL)
|
||||
@ -238,6 +251,7 @@ grep_close(struct file *f)
|
||||
|
||||
switch (filebehave) {
|
||||
case FILE_STDIO:
|
||||
funlockfile(f->f);
|
||||
fclose(f->f);
|
||||
break;
|
||||
case FILE_GZIP:
|
||||
@ -251,5 +265,4 @@ grep_close(struct file *f)
|
||||
/* Reset read buffer for the file we are closing */
|
||||
binbufptr = NULL;
|
||||
free(binbuf);
|
||||
|
||||
}
|
||||
|
@ -121,8 +121,8 @@ 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 */
|
||||
bool dexclude, dinclude; /* --exclude-dir and --include-dir */
|
||||
bool fexclude, finclude; /* --exclude and --include */
|
||||
|
||||
enum {
|
||||
BIN_OPT = CHAR_MAX + 1,
|
||||
@ -236,7 +236,8 @@ add_pattern(char *pat, size_t len)
|
||||
--len;
|
||||
/* pat may not be NUL-terminated */
|
||||
pattern[patterns] = grep_malloc(len + 1);
|
||||
strlcpy(pattern[patterns], pat, len + 1);
|
||||
memcpy(pattern[patterns], pat, len);
|
||||
pattern[patterns][len] = '\0';
|
||||
++patterns;
|
||||
}
|
||||
|
||||
@ -355,38 +356,33 @@ main(int argc, char *argv[])
|
||||
|
||||
eopts = getenv("GREP_OPTIONS");
|
||||
|
||||
eargc = 1;
|
||||
/* support for extra arguments in GREP_OPTIONS */
|
||||
eargc = 0;
|
||||
if (eopts != NULL) {
|
||||
char *str;
|
||||
|
||||
for(i = 0; i < strlen(eopts); i++)
|
||||
if (eopts[i] == ' ')
|
||||
/* make an estimation of how many extra arguments we have */
|
||||
for (unsigned int j = 0; j < strlen(eopts); j++)
|
||||
if (eopts[j] == ' ')
|
||||
eargc++;
|
||||
|
||||
eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1));
|
||||
|
||||
str = strtok(eopts, " ");
|
||||
eargc = 0;
|
||||
|
||||
while(str != NULL) {
|
||||
eargv[++eargc] = (char *)grep_malloc(sizeof(char) *
|
||||
(strlen(str) + 1));
|
||||
strlcpy(eargv[eargc], str, strlen(str) + 1);
|
||||
str = strtok(NULL, " ");
|
||||
}
|
||||
eargv[++eargc] = NULL;
|
||||
/* parse extra arguments */
|
||||
while ((str = strsep(&eopts, " ")) != NULL)
|
||||
eargv[eargc++] = grep_strdup(str);
|
||||
|
||||
aargv = (char **)grep_calloc(eargc + argc + 1,
|
||||
sizeof(char *));
|
||||
|
||||
aargv[0] = argv[0];
|
||||
for (i = 0; i < eargc; i++)
|
||||
aargv[i + 1] = eargv[i];
|
||||
for (int j = 1; j < argc; j++, i++)
|
||||
aargv[i + 1] = argv[j];
|
||||
|
||||
for(i = 1; i < eargc; i++)
|
||||
aargv[i] = eargv[i];
|
||||
for(int j = 1; j < argc; j++)
|
||||
aargv[i++] = argv[j];
|
||||
|
||||
aargc = eargc + argc - 1;
|
||||
|
||||
aargc = eargc + argc;
|
||||
} else {
|
||||
aargv = argv;
|
||||
aargc = argc;
|
||||
@ -609,11 +605,11 @@ main(int argc, char *argv[])
|
||||
add_fpattern(optarg, EXCL_PAT);
|
||||
break;
|
||||
case R_DINCLUDE_OPT:
|
||||
dexclude = true;
|
||||
dinclude = true;
|
||||
add_dpattern(optarg, INCL_PAT);
|
||||
break;
|
||||
case R_DEXCLUDE_OPT:
|
||||
dinclude = true;
|
||||
dexclude = true;
|
||||
add_dpattern(optarg, EXCL_PAT);
|
||||
break;
|
||||
case HELP_OPT:
|
||||
@ -685,12 +681,15 @@ main(int argc, char *argv[])
|
||||
|
||||
if (dirbehave == DIR_RECURSE)
|
||||
c = grep_tree(aargv);
|
||||
else
|
||||
else {
|
||||
if (aargc == 1)
|
||||
hflag = true;
|
||||
for (c = 0; aargc--; ++aargv) {
|
||||
if ((finclude || fexclude) && !file_matching(*aargv))
|
||||
continue;
|
||||
c+= procfile(*aargv);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WITHOUT_NLS
|
||||
catclose(catalog);
|
||||
|
@ -115,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 dexclude, dinclude, fexclude, finclude, nullflag;
|
||||
extern bool dexclude, dinclude, fexclude, finclude, lbflag, nullflag;
|
||||
extern unsigned long long Aflag, Bflag, mcount;
|
||||
extern char *label;
|
||||
extern const char *color;
|
||||
@ -134,7 +134,6 @@ 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);
|
||||
@ -153,8 +152,6 @@ void clearqueue(void);
|
||||
void grep_close(struct file *f);
|
||||
struct file *grep_stdin_open(void);
|
||||
struct file *grep_open(const char *path);
|
||||
int grep_feof(struct file *f);
|
||||
int grep_fgetc(struct file *f);
|
||||
char *grep_fgetln(struct file *f, size_t *len);
|
||||
|
||||
/* fastgrep.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;
|
||||
strcpy(item->data.dat, x->dat);
|
||||
memcpy(item->data.dat, x->dat, x->len);
|
||||
item->data.file = x->file;
|
||||
|
||||
STAILQ_INSERT_TAIL(&queue, item, list);
|
||||
|
@ -72,7 +72,7 @@ file_matching(const char *fname)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
bool
|
||||
static inline bool
|
||||
dir_matching(const char *dname)
|
||||
{
|
||||
bool ret;
|
||||
@ -144,9 +144,10 @@ grep_tree(char **argv)
|
||||
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));
|
||||
memcpy(dir, p->fts_path,
|
||||
d - p->fts_path);
|
||||
dir[d - p->fts_path] = '\0';
|
||||
}
|
||||
ok = dir_matching(dir);
|
||||
free(dir);
|
||||
@ -276,7 +277,7 @@ procfile(const char *fn)
|
||||
* matches. The matching lines are passed to printline() to display the
|
||||
* appropriate output.
|
||||
*/
|
||||
static int
|
||||
static inline int
|
||||
procline(struct str *l, int nottext)
|
||||
{
|
||||
regmatch_t matches[MAX_LINE_MATCHES];
|
||||
@ -317,30 +318,20 @@ procline(struct str *l, int nottext)
|
||||
(size_t)pmatch.rm_eo != l->len)
|
||||
r = REG_NOMATCH;
|
||||
/* Check for whole word match */
|
||||
if (r == 0 && wflag && pmatch.rm_so != 0 &&
|
||||
(size_t)pmatch.rm_eo != l->len) {
|
||||
wchar_t *wbegin;
|
||||
wint_t wend;
|
||||
size_t size;
|
||||
if (r == 0 && wflag && pmatch.rm_so != 0) {
|
||||
wint_t wbegin, wend;
|
||||
|
||||
size = mbstowcs(NULL, l->dat,
|
||||
pmatch.rm_so);
|
||||
|
||||
if (size == ((size_t) - 1))
|
||||
wbegin = wend = L' ';
|
||||
if (pmatch.rm_so != 0 &&
|
||||
sscanf(&l->dat[pmatch.rm_so - 1],
|
||||
"%lc", &wbegin) != 1)
|
||||
r = REG_NOMATCH;
|
||||
else if ((size_t)pmatch.rm_eo != l->len &&
|
||||
sscanf(&l->dat[pmatch.rm_eo],
|
||||
"%lc", &wend) != 1)
|
||||
r = REG_NOMATCH;
|
||||
else if (iswword(wbegin) || iswword(wend))
|
||||
r = REG_NOMATCH;
|
||||
else {
|
||||
wbegin = grep_malloc(size);
|
||||
if (mbstowcs(wbegin, l->dat,
|
||||
pmatch.rm_so) == ((size_t) - 1))
|
||||
r = REG_NOMATCH;
|
||||
else if (sscanf(&l->dat[pmatch.rm_eo],
|
||||
"%lc", &wend) != 1)
|
||||
r = REG_NOMATCH;
|
||||
else if (iswword(wbegin[wcslen(wbegin)]) ||
|
||||
iswword(wend))
|
||||
r = REG_NOMATCH;
|
||||
free(wbegin);
|
||||
}
|
||||
}
|
||||
if (r == 0) {
|
||||
if (m == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user