changes to handling of "." and ".." when dotglob is enabled; other minor changes

This commit is contained in:
Chet Ramey
2021-06-15 15:07:40 -04:00
parent 6e11792d93
commit da43077c47
20 changed files with 2413 additions and 2170 deletions
+2 -44
View File
@@ -1,6 +1,6 @@
/* glob.c -- file-name wildcard pattern matching for Bash.
Copyright (C) 1985-2020 Free Software Foundation, Inc.
Copyright (C) 1985-2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -304,35 +304,6 @@ skipname (pat, dname, flags)
pat[0] != '.' && (pat[0] != '\\' || pat[1] != '.'))
return 1;
/* Special checks for `.'. The only things that can match `.' are ".",
"\.", ".*", and "\.*". We don't try to match everything here, just
make sure that we don't let something obviously disqualifying by.
We only do this if we're not negating the pattern. */
else if ((flags & GX_NEGATE) == 0 && dname[0] == '.' && dname[1] == '\0')
{
if (pat[0] != '.' && (pat[0] != '\\' || pat[1] != '.'))
return 1;
i = (pat[0] == '.') ? 1 : 2;
if (pat[i] && pat[i] != '*')
return 1;
}
#if 0
/* These are additional special checks for `..'. We let through "..",
"\..", ".\.", "\.\.", ".*", ".?", "\.*", and "\.?".
Disabled because it doesn't deal with things like `@(.).' at all. */
else if (dname[0] == '.' && dname[1] == '.' && dname[2] == '\0')
{
if (pat[0] != '.' && (pat[0] != '\\' || pat[1] != '.')) /* [\]. */
return 1;
i = (pat[0] == '.') ? 1 : 2;
if (pat[i] && (pat[i] == '*' || pat[i] == '?') && pat[i+1] == '\0')
return 0; /* [\].[*?] */
if (pat[i] != '.' && (pat[i] != '\\' || pat[i+1] != '.')) /* [\].[\]. */
return 1;
}
#endif
return 0;
}
@@ -371,19 +342,6 @@ wskipname (pat, dname, flags)
pat[0] != L'.' && (pat[0] != L'\\' || pat[1] != L'.'))
return 1;
/* Special checks for `.'. The only things that can match `.' are ".",
"\.", ".*", and "\.*". We don't try to match everything here, just
make sure that we don't let something obviously disqualifying by.
We only do this if we're not negating the pattern. */
else if ((flags & GX_NEGATE) == 0 && dname[0] == L'.' && dname[1] == L'\0')
{
if (pat[0] != L'.' && (pat[0] != L'\\' || pat[1] != L'.'))
return 1;
i = (pat[0] == L'.') ? 1 : 2;
if (pat[i] != L'\0' && pat[i] != L'*')
return 1;
}
return 0;
}
@@ -848,7 +806,7 @@ glob_vector (pat, dir, flags)
/* Compute the flags that will be passed to strmatch(). We don't
need to do this every time through the loop. */
mflags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
mflags = (noglob_dot_filenames ? FNM_PERIOD : FNM_DOTDOT) | FNM_PATHNAME;
#ifdef FNM_CASEFOLD
if (glob_ignore_case)
+43 -8
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -83,6 +83,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
#ifdef EXTENDED_GLOB
/* EXTMATCH () will handle recursively calling GMATCH, so we can
just return what EXTMATCH() returns. */
if ((flags & FNM_EXTMATCH) && *p == L('(') &&
(c == L('+') || c == L('*') || c == L('?') || c == L('@') || c == L('!'))) /* ) */
@@ -90,7 +91,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
int lflags;
/* If we're not matching the start of the string, we're not
concerned about the special cases for matching `.' */
lflags = (n == string) ? flags : (flags & ~FNM_PERIOD);
lflags = (n == string) ? flags : (flags & ~(FNM_PERIOD|FNM_DOTDOT));
return (EXTMATCH (c, n, se, p, pe, lflags));
}
#endif /* EXTENDED_GLOB */
@@ -109,6 +110,15 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
string or if it is the first character following a slash and
we are matching a pathname. */
return FNM_NOMATCH;
/* `?' cannot match `.' or `..' if it is the first character of the
string or if it is the first character following a slash and
we are matching a pathname. */
if ((flags & FNM_DOTDOT) &&
((n == string && SDOT_OR_DOTDOT(n)) ||
((flags & FNM_PATHNAME) && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
return FNM_NOMATCH;
break;
case L('\\'): /* backslash escape removes special meaning */
@@ -147,6 +157,14 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
we are matching a pathname. */
return FNM_NOMATCH;
/* `*' cannot match `.' or `..' if it is the first character of the
string or if it is the first character following a slash and
we are matching a pathname. */
if ((flags & FNM_DOTDOT) &&
((n == string && SDOT_OR_DOTDOT(n)) ||
((flags & FNM_PATHNAME) && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
return FNM_NOMATCH;
if (p == pe)
return 0;
@@ -288,7 +306,7 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
continue;
/* Otherwise, we just recurse. */
if (GMATCH (n, se, p, pe, &end, flags & ~FNM_PERIOD) == 0)
if (GMATCH (n, se, p, pe, &end, flags & ~(FNM_PERIOD|FNM_DOTDOT)) == 0)
{
if (end.pattern == NULL)
return (0);
@@ -321,6 +339,14 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
(n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
return (FNM_NOMATCH);
/* `?' cannot match `.' or `..' if it is the first character of the
string or if it is the first character following a slash and
we are matching a pathname. */
if ((flags & FNM_DOTDOT) &&
((n == string && SDOT_OR_DOTDOT(n)) ||
((flags & FNM_PATHNAME) && n[-1] == L('/') && PDOT_OR_DOTDOT(n))))
return FNM_NOMATCH;
p = BRACKMATCH (p, sc, flags);
if (p == 0)
return FNM_NOMATCH;
@@ -843,7 +869,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
if (m1)
{
/* if srest > s, we are not at start of string */
xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
xflags = (srest > s) ? (flags & ~(FNM_PERIOD|FNM_DOTDOT)) : flags;
m2 = (GMATCH (srest, se, prest, pe, NULL, xflags) == 0) ||
(s != srest && GMATCH (srest, se, p - 1, pe, NULL, xflags) == 0);
}
@@ -873,7 +899,7 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
for ( ; srest <= se; srest++)
{
/* if srest > s, we are not at start of string */
xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
xflags = (srest > s) ? (flags & ~(FNM_PERIOD|FNM_DOTDOT)) : flags;
if (GMATCH (s, srest, psub, pnext - 1, NULL, flags) == 0 &&
GMATCH (srest, se, prest, pe, NULL, xflags) == 0)
return (0);
@@ -899,12 +925,17 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
/* If nothing matched, but the string starts with a period and we
need to match periods explicitly, don't return this as a match,
even for negation. Might need to do this only if srest == s. */
if (m1 == 0 && *s == '.' && (flags & FNM_PERIOD))
even for negation. */
if (m1 == 0 && (flags & FNM_PERIOD) && *s == '.')
return (FNM_NOMATCH);
if (m1 == 0 && (flags & FNM_DOTDOT) &&
(SDOT_OR_DOTDOT (s) ||
((flags & FNM_PATHNAME) && s[-1] == L('/') && PDOT_OR_DOTDOT(s))))
return (FNM_NOMATCH);
/* if srest > s, we are not at start of string */
xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
xflags = (srest > s) ? (flags & ~(FNM_PERIOD|FNM_DOTDOT)) : flags;
if (m1 == 0 && GMATCH (srest, se, prest, pe, NULL, xflags) == 0)
return (0);
}
@@ -939,4 +970,8 @@ fprintf(stderr, "extmatch: flags = %d\n", flags);
#undef MEMCHR
#undef COLLEQUIV
#undef RANGECMP
#undef ISDIRSEP
#undef PATHSEP
#undef PDOT_OR_DOTDOT
#undef SDOT_OR_DOTDOT
#undef L
+22 -1
View File
@@ -1,7 +1,7 @@
/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
globbing. */
/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -308,6 +308,16 @@ is_cclass (c, name)
? TOLOWER ((unsigned char)c) \
: ((unsigned char)c))
#if !defined (__CYGWIN__)
# define ISDIRSEP(c) ((c) == '/')
#else
# define ISDIRSEP(c) ((c) == '/' || (c) == '\\')
#endif /* __CYGWIN__ */
#define PATHSEP(c) (ISDIRSEP(c) || (c) == 0)
# define PDOT_OR_DOTDOT(s) (s[0] == '.' && (PATHSEP (s[1]) || (s[1] == '.' && PATHSEP (s[2]))))
# define SDOT_OR_DOTDOT(s) (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
#define FCT internal_strmatch
#define GMATCH gmatch
#define COLLSYM collsym
@@ -553,6 +563,17 @@ posix_cclass_only (pattern)
/* Now include `sm_loop.c' for multibyte characters. */
#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c))
# if !defined (__CYGWIN__)
# define ISDIRSEP(c) ((c) == L'/')
# else
# define ISDIRSEP(c) ((c) == L'/' || (c) == L'\\')
# endif /* __CYGWIN__ */
# define PATHSEP(c) (ISDIRSEP(c) || (c) == L'\0')
# define PDOT_OR_DOTDOT(w) (w[0] == L'.' && (PATHSEP(w[1]) || (w[1] == L'.' && PATHSEP(w[2]))))
# define SDOT_OR_DOTDOT(w) (w[0] == L'.' && (w[1] == L'\0' || (w[1] == L'.' && w[2] == L'\0')))
#define FCT internal_wstrmatch
#define GMATCH gmatch_wc
#define COLLSYM collwcsym
+2 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne-Again SHell.
@@ -47,6 +47,7 @@
#define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
#define FNM_FIRSTCHAR (1 << 6) /* Match only the first character */
#define FNM_DOTDOT (1 << 7) /* force `.' and `..' to match explicitly even if FNM_PERIOD not supplied. */
/* Value returned by `strmatch' if STRING does not match PATTERN. */
#undef FNM_NOMATCH
+1 -1
View File
@@ -1598,7 +1598,7 @@ puts_face (const char *str, const char *face, int n)
char cur_face;
for (cur_face = FACE_NORMAL, i = 0; i < n; i++)
putc_face (str[i], face[i], &cur_face);
putc_face ((unsigned char) str[i], face[i], &cur_face);
putc_face (EOF, FACE_NORMAL, &cur_face);
}