From: Eric Biggers Date: Mon, 30 Dec 2013 07:21:24 +0000 (-0600) Subject: wildcard.c: Don't use broken PathMatchSpec() X-Git-Tag: v1.6.0~47 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=0065a73c25d704b139d5880d6e3af73a0b056a54 wildcard.c: Don't use broken PathMatchSpec() --- diff --git a/include/wimlib_tchar.h b/include/wimlib_tchar.h index 33ad0cc5..ecaae5d5 100644 --- a/include/wimlib_tchar.h +++ b/include/wimlib_tchar.h @@ -54,6 +54,7 @@ typedef wchar_t tchar; # define tstrdup wcsdup # define ttempnam _wtempnam # define tgetenv _wgetenv +# define totlower(c) towlower((wchar_t)(c)) /* The following "tchar" functions do not have exact wide-character equivalents * on Windows so require parameter rearrangement or redirection to a replacement * function defined ourselves. */ @@ -116,6 +117,7 @@ typedef char tchar; # define tstrdup strdup # define ttempnam tempnam # define tgetenv getenv +# define totlower(c) tolower((unsigned char)(c)) # define TSTRDUP STRDUP # define tstrerror_r strerror_r # define trename rename diff --git a/src/wildcard.c b/src/wildcard.c index 0965b26c..c0f0adbd 100644 --- a/src/wildcard.c +++ b/src/wildcard.c @@ -27,6 +27,7 @@ # include "config.h" #endif +#include #include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/error.h" @@ -43,10 +44,20 @@ struct match_dentry_ctx { bool case_insensitive; }; +#define PLATFORM_SUPPORTS_FNMATCH + #ifdef __WIN32__ +/* PathMatchSpec() could provide a fnmatch() alternative, but it isn't + * documented properly, nor does it work properly. For example, it returns that + * any name matches *.* even if that name doesn't actually contain a period. */ +# undef PLATFORM_SUPPORTS_FNMATCH +#endif + +#ifndef PLATFORM_SUPPORTS_FNMATCH static bool -match_wildcard_case_sensitive(const tchar *string, size_t string_len, - const tchar *wildcard, size_t wildcard_len) +do_match_wildcard(const tchar *string, size_t string_len, + const tchar *wildcard, size_t wildcard_len, + bool ignore_case) { for (;;) { if (string_len == 0) { @@ -57,58 +68,49 @@ match_wildcard_case_sensitive(const tchar *string, size_t string_len, return (wildcard_len == 0); } else if (wildcard_len == 0) { return false; - } else if (*string == *wildcard || *wildcard == T('?')) { + } else if (*string == *wildcard || *wildcard == T('?') || + (ignore_case && totlower(*string) == totlower(*wildcard))) + { string++; string_len--; wildcard_len--; wildcard++; continue; } else if (*wildcard == T('*')) { - return match_wildcard_case_sensitive( - string, string_len, - wildcard + 1, wildcard_len - 1) || - match_wildcard_case_sensitive( - string + 1, string_len - 1, - wildcard, wildcard_len); + return do_match_wildcard(string, string_len, + wildcard + 1, wildcard_len - 1, + ignore_case) || + do_match_wildcard(string + 1, string_len - 1, + wildcard, wildcard_len, + ignore_case); } else { return false; } } } -#endif /* __WIN32__ */ +#endif /* ! PLATFORM_SUPPORTS_FNMATCH */ static bool match_wildcard(const tchar *string, tchar *wildcard, - size_t wildcard_len, bool case_insensitive) + size_t wildcard_len, bool ignore_case) { - /* Note: in Windows builds fnmatch() calls a replacement function. It - * does not support case-sensitive globbing. */ -#ifdef __WIN32__ - if (case_insensitive) -#endif - { - char orig; - int ret; - int flags = FNM_NOESCAPE; - if (case_insensitive) - flags |= FNM_CASEFOLD; +#ifdef PLATFORM_SUPPORTS_FNMATCH + char orig; + int ret; + int flags = FNM_NOESCAPE; + if (ignore_case) + flags |= FNM_CASEFOLD; - orig = wildcard[wildcard_len]; - wildcard[wildcard_len] = T('\0'); + orig = wildcard[wildcard_len]; + wildcard[wildcard_len] = T('\0'); - ret = fnmatch(wildcard, string, flags); + ret = fnmatch(wildcard, string, flags); - wildcard[wildcard_len] = orig; - return (ret == 0); - } -#ifdef __WIN32__ - else - { - return match_wildcard_case_sensitive(string, - tstrlen(string), - wildcard, - wildcard_len); - } + wildcard[wildcard_len] = orig; + return (ret == 0); +#else + return do_match_wildcard(string, tstrlen(string), + wildcard, wildcard_len, ignore_case); #endif }