1
0
Fork 0
mirror of synced 2025-03-06 20:53:29 +01:00

Bash-5.0 patch 3: improvements when globbing directory names containing backslashes

This commit is contained in:
Chet Ramey 2019-03-19 10:05:39 -04:00
parent ddf3f643cb
commit fcf6ae7d06
6 changed files with 52 additions and 17 deletions

View file

@ -3752,7 +3752,7 @@ completion_glob_pattern (string)
continue;
case '\\':
if (*string == 0)
if (*string++ == 0)
return (0);
}

View file

@ -1061,7 +1061,7 @@ glob_filename (pathname, flags)
char *directory_name, *filename, *dname, *fn;
unsigned int directory_len;
int free_dirname; /* flag */
int dflags;
int dflags, hasglob;
result = (char **) malloc (sizeof (char *));
result_size = 1;
@ -1110,9 +1110,12 @@ glob_filename (pathname, flags)
free_dirname = 1;
}
hasglob = 0;
/* If directory_name contains globbing characters, then we
have to expand the previous levels. Just recurse. */
if (directory_len > 0 && glob_pattern_p (directory_name))
have to expand the previous levels. Just recurse.
If glob_pattern_p returns != [0,1] we have a pattern that has backslash
quotes but no unquoted glob pattern characters. We dequote it below. */
if (directory_len > 0 && (hasglob = glob_pattern_p (directory_name)) == 1)
{
char **directories, *d, *p;
register unsigned int i;
@ -1175,7 +1178,7 @@ glob_filename (pathname, flags)
if (d[directory_len - 1] == '/')
d[directory_len - 1] = '\0';
directories = glob_filename (d, dflags);
directories = glob_filename (d, dflags|GX_RECURSE);
if (free_dirname)
{
@ -1332,6 +1335,20 @@ only_filename:
free (directory_name);
return (NULL);
}
/* If we have a directory name with quoted characters, and we are
being called recursively to glob the directory portion of a pathname,
we need to dequote the directory name before returning it so the
caller can read the directory */
if (directory_len > 0 && hasglob == 2 && (flags & GX_RECURSE) != 0)
{
dequote_pathname (directory_name);
directory_len = strlen (directory_name);
}
/* We could check whether or not the dequoted directory_name is a
directory and return it here, returning the original directory_name
if not, but we don't do that yet. I'm not sure it matters. */
/* Handle GX_MARKDIRS here. */
result[0] = (char *) malloc (directory_len + 1);
if (result[0] == NULL)

View file

@ -30,6 +30,7 @@
#define GX_NULLDIR 0x100 /* internal -- no directory preceding pattern */
#define GX_ADDCURDIR 0x200 /* internal -- add passed directory name */
#define GX_GLOBSTAR 0x400 /* turn on special handling of ** */
#define GX_RECURSE 0x800 /* internal -- glob_filename called recursively */
extern int glob_pattern_p __P((const char *));
extern char **glob_vector __P((char *, char *, int));

View file

@ -26,10 +26,10 @@ INTERNAL_GLOB_PATTERN_P (pattern)
{
register const GCHAR *p;
register GCHAR c;
int bopen;
int bopen, bsquote;
p = pattern;
bopen = 0;
bopen = bsquote = 0;
while ((c = *p++) != L('\0'))
switch (c)
@ -55,13 +55,22 @@ INTERNAL_GLOB_PATTERN_P (pattern)
case L('\\'):
/* Don't let the pattern end in a backslash (GMATCH returns no match
if the pattern ends in a backslash anyway), but otherwise return 1,
since the matching engine uses backslash as an escape character
and it can be removed. */
return (*p != L('\0'));
if the pattern ends in a backslash anyway), but otherwise note that
we have seen this, since the matching engine uses backslash as an
escape character and it can be removed. We return 2 later if we
have seen only backslash-escaped characters, so interested callers
know they can shortcut and just dequote the pathname. */
if (*p != L('\0'))
{
p++;
bsquote = 1;
continue;
}
else /* (*p == L('\0')) */
return 0;
}
return 0;
return bsquote ? 2 : 0;
}
#undef INTERNAL_GLOB_PATTERN_P

View file

@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
#define PATCHLEVEL 2
#define PATCHLEVEL 3
#endif /* _PATCHLEVEL_H_ */

View file

@ -65,11 +65,11 @@ unquoted_glob_pattern_p (string)
{
register int c;
char *send;
int open;
int open, bsquote;
DECLARE_MBSTATE;
open = 0;
open = bsquote = 0;
send = string + strlen (string);
while (c = *string++)
@ -100,7 +100,14 @@ unquoted_glob_pattern_p (string)
can be removed by the matching engine, so we have to run it through
globbing. */
case '\\':
return (*string != 0);
if (*string != '\0' && *string != '/')
{
bsquote = 1;
string++;
continue;
}
else if (*string == 0)
return (0);
case CTLESC:
if (*string++ == '\0')
@ -117,7 +124,8 @@ unquoted_glob_pattern_p (string)
ADVANCE_CHAR_P (string, send - string);
#endif
}
return (0);
return (bsquote ? 2 : 0);
}
/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to