diff --git a/ChangeLog b/ChangeLog index e4027a7209..bd10d114d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +1999-04-26 Ulrich Drepper + + * posix/fnmatch.c: Include string.h also for glibc. + (fnmatch, case '?'): Optimize if cascades a bit. + (fnmatch, case '*'): Correct handling if FNM_PATHNAME is set. + + * posix/testfnm.c: Add test cases for * with FNM_PATHNAME errors. + 1999-04-24 Ulrich Drepper * iconv/gconv_builtin.h: Add definitions for UTF16 builtins. diff --git a/posix/fnmatch.c b/posix/fnmatch.c index dc389efa39..e0ff2c34d2 100644 --- a/posix/fnmatch.c +++ b/posix/fnmatch.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 93, 96, 97, 98 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU C Library. This library is free software; you can redistribute it and/or @@ -29,7 +29,7 @@ #include #include -#if HAVE_STRING_H +#if HAVE_STRING_H || defined _LIBC # include #else # include @@ -154,9 +154,9 @@ fnmatch (pattern, string, flags) case '?': if (*n == '\0') return FNM_NOMATCH; - else if ((flags & FNM_FILE_NAME) && *n == '/') + else if (*n == '/' && (flags & FNM_FILE_NAME)) return FNM_NOMATCH; - else if ((flags & FNM_PERIOD) && *n == '.' && + else if (*n == '.' && (flags & FNM_PERIOD) && (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) return FNM_NOMATCH; break; @@ -175,13 +175,13 @@ fnmatch (pattern, string, flags) break; case '*': - if ((flags & FNM_PERIOD) && *n == '.' && + if (*n == '.' && (flags & FNM_PERIOD) && (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) return FNM_NOMATCH; for (c = *p++; c == '?' || c == '*'; c = *p++) { - if ((flags & FNM_FILE_NAME) && *n == '/') + if (*n == '/' && (flags & FNM_FILE_NAME)) /* A slash does not match a wildcard under FNM_FILE_NAME. */ return FNM_NOMATCH; else if (c == '?') @@ -199,17 +199,38 @@ fnmatch (pattern, string, flags) } if (c == '\0') - return 0; + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this does mean it cannot match. */ + return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL + ? FNM_NOMATCH : 0); + else + { + const char *endp; - { - unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; - c1 = FOLD (c1); - for (--p; *n != '\0'; ++n) - if ((c == '[' || FOLD ((unsigned char) *n) == c1) && - fnmatch (p, n, flags & ~FNM_PERIOD) == 0) - return 0; - return FNM_NOMATCH; - } + if (!(flags & FNM_FILE_NAME) || (endp = strchr (n, '/')) == NULL) + endp = strchr (n, '\0'); + + if (c == '[') + { + for (--p; n < endp; ++n) + if (fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + } + else + { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n) + if (FOLD ((unsigned char) *n) == c + && fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; case '[': { diff --git a/posix/testfnm.c b/posix/testfnm.c index 5ab761b8b2..b43f9531fb 100644 --- a/posix/testfnm.c +++ b/posix/testfnm.c @@ -13,6 +13,9 @@ struct { { "a/b", "a[/]b", 0, 0 }, { "a/b", "a[/]b", FNM_PATHNAME, FNM_NOMATCH }, { "a/b", "[a-z]/[a-z]", 0, 0 }, + { "a/b", "*", FNM_FILE_NAME, FNM_NOMATCH }, + { "a/b", "*[/]b", FNM_FILE_NAME, FNM_NOMATCH }, + { "a/b", "*[b]", FNM_FILE_NAME, FNM_NOMATCH } }; int