Strip leading "./" or ".//" from patterns and filenames

so that "./foo" matches "foo" (and vice versa).

This is related to PR bin/119141.

PR:		bin/119141
MFC after:	4 days
This commit is contained in:
Tim Kientzle 2008-08-18 04:58:54 +00:00
parent 8671b38b6c
commit 0f4b98311a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=181821

View File

@ -59,6 +59,7 @@ static int bsdtar_fnmatch(const char *p, const char *s);
static void initialize_matching(struct bsdtar *);
static int match_exclusion(struct match *, const char *pathname);
static int match_inclusion(struct match *, const char *pathname);
static int pathmatch(const char *p, const char *s);
/*
* The matching logic here needs to be re-thought. I started out to
@ -193,12 +194,12 @@ match_exclusion(struct match *match, const char *pathname)
const char *p;
if (*match->pattern == '*' || *match->pattern == '/')
return (bsdtar_fnmatch(match->pattern, pathname) == 0);
return (pathmatch(match->pattern, pathname) == 0);
for (p = pathname; p != NULL; p = strchr(p, '/')) {
if (*p == '/')
p++;
if (bsdtar_fnmatch(match->pattern, p) == 0)
if (pathmatch(match->pattern, p) == 0)
return (1);
}
return (0);
@ -211,7 +212,7 @@ match_exclusion(struct match *match, const char *pathname)
int
match_inclusion(struct match *match, const char *pathname)
{
return (bsdtar_fnmatch(match->pattern, pathname) == 0);
return (pathmatch(match->pattern, pathname) == 0);
}
void
@ -279,6 +280,41 @@ unmatched_inclusions_warn(struct bsdtar *bsdtar, const char *msg)
return (matching->inclusions_unmatched_count);
}
/*
* TODO: Extend this so that the following matches work:
* "foo//bar" == "foo/bar"
* "foo/./bar" == "foo/bar"
* "./foo" == "foo"
*
* The POSIX fnmatch() function doesn't handle any of these, but
* all are common situations that arise when paths are generated within
* large scripts. E.g., the following is quite common:
* MYPATH=foo/ TARGET=$MYPATH/bar
* It may be worthwhile to edit such paths at write time as well,
* especially when such editing may avoid the need for long pathname
* extensions.
*/
static int
pathmatch(const char *pattern, const char *string)
{
/*
* Strip leading "./" or ".//" so that, e.g.,
* "foo" matches "./foo". In particular, this
* opens up an optimization for the writer to
* elide leading "./".
*/
if (pattern[0] == '.' && pattern[1] == '/') {
pattern += 2;
while (pattern[0] == '/')
++pattern;
}
if (string[0] == '.' && string[1] == '/') {
string += 2;
while (string[0] == '/')
++string;
}
return (bsdtar_fnmatch(pattern, string, FNM_LEADING_DIR));
}
#if defined(HAVE_FNMATCH) && defined(HAVE_FNM_LEADING_DIR)