# include "config.h"
#endif
+#include <ctype.h>
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/error.h"
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) {
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
}
{
if (*wildcard == T('\0'))
return WILDCARD_STATUS_DONE_FULLY;
- while (is_any_path_separator(*wildcard))
+ while (*wildcard == WIM_PATH_SEPARATOR)
wildcard++;
if (*wildcard == T('\0'))
return WILDCARD_STATUS_DONE_TRAILING_SLASHES;
w = ctx->wildcard_path;
begin = ctx->cur_component_offset + ctx->cur_component_len;
- while (is_any_path_separator(w[begin]))
+ while (w[begin] == WIM_PATH_SEPARATOR)
begin++;
end = begin;
- while (w[end] != T('\0') && !is_any_path_separator(w[end]))
+ while (w[end] != T('\0') && w[end] != WIM_PATH_SEPARATOR)
end++;
len = end - begin;
* wildcard.
* @wildcard_path
* Wildcard path to expand, which may contain the '?' and '*' characters.
- * Path separators may be either forward slashes, and leading path
- * separators are ignored. Trailing path separators indicate that the
- * wildcard can only match directories.
+ * Path separators must be WIM_PATH_SEPARATOR. Leading path separators are
+ * ignored, whereas one or more trailing path separators indicate that the
+ * wildcard path can only match directories (and not reparse points).
* @consume_dentry
* Callback function which will receive each directory entry matched by the
* wildcard.