da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdlib.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <string.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/types.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/systm.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/sunddi.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown#include <smbsrv/string.h>
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown#include <smbsrv/smb.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright/*
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * Maximum recursion depth for the wildcard match functions.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * These functions may recurse when processing a '*'.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright */
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright#define SMB_MATCH_DEPTH_MAX 32
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Rossstruct match_priv {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross int depth;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross boolean_t ci;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross};
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Rossstatic int smb_match_private(const char *, const char *, struct match_priv *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Rossstatic const char smb_wildcards[] = "*?<>\"";
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Return B_TRUE if pattern contains wildcards
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wrightboolean_t
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Rosssmb_contains_wildcards(const char *pattern)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (strpbrk(pattern, smb_wildcards) != NULL);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright}
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright/*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * NT-compatible file name match function. [MS-FSA 3.1.4.4]
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Returns TRUE if there is a match.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Rossboolean_t
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Rosssmb_match(const char *p, const char *s, boolean_t ci)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright{
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross struct match_priv priv;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright int rc;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Optimize common patterns that match everything:
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * ("*", "<\"*") That second one is the converted
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * form of "*.*" after smb_convert_wildcards() does
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * its work on it for an old LM client. Note that a
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * plain "*.*" never gets this far.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (p[0] == '*' && p[1] == '\0')
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (B_TRUE);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (p[0] == '<' && p[1] == '\"' && p[2] == '*' && p[3] == '\0')
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (B_TRUE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Match string ".." as if "." This is Windows behavior
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * (not mentioned in MS-FSA) that was determined using
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * the Samba masktest program.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (s[0] == '.' && s[1] == '.' && s[2] == '\0')
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross s++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Optimize simple patterns (no wildcards)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (NULL == strpbrk(p, smb_wildcards)) {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (ci)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross rc = smb_strcasecmp(p, s, 0);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross else
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross rc = strcmp(p, s);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (rc == 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Do real wildcard match.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross priv.depth = 0;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross priv.ci = ci;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross rc = smb_match_private(p, s, &priv);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (rc == 1);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright}
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright/*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Internal file name match function. [MS-FSA 3.1.4.4]
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * This does the full expression evaluation.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright *
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * '*' matches zero of more of any characters.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * '?' matches exactly one of any character.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * '<' matches any string up through the last dot or EOS.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * '>' matches any one char not a dot, dot at EOS, or EOS.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * '"' matches a dot, or EOS.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright *
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright * Returns:
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * 1 match
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * 0 no-match
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * -1 no-match, error (illseq, too many wildcards in pattern, ...)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross *
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Note that both the pattern and the string are in multi-byte form.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross *
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * The implementation of this is quite tricky. First note that it
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * can call itself recursively, though it limits the recursion depth.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Each switch case in the while loop can basically do one of three
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * things: (a) return "Yes, match", (b) return "not a match", or
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * continue processing the match pattern. The cases for wildcards
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * that may match a variable number of characters ('*' and '<') do
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * recursive calls, looking for a match of the remaining pattern,
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * starting at the current and later positions in the string.
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright */
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wrightstatic int
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Rosssmb_match_private(const char *pat, const char *str, struct match_priv *priv)
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright{
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross const char *limit;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross char pc; /* current pattern char */
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown int rc;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross smb_wchar_t wcpat, wcstr; /* current wchar in pat, str */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross int nbpat, nbstr; /* multi-byte length of it */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (priv->depth >= SMB_MATCH_DEPTH_MAX)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (-1);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * Advance over one multi-byte char, used in cases like
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * '?' or '>' where "match one character" needs to be
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * interpreted as "match one multi-byte sequence".
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross *
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * This macro needs to consume the semicolon following
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * each place it appears, so this is carefully written
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * as an if/else with a missing semicolon at the end.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross#define ADVANCE(str) \
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if ((nbstr = smb_mbtowc(NULL, str, MTS_MB_CHAR_MAX)) < 1) \
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (-1); \
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross else \
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross str += nbstr /* no ; */
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /*
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * We move pat forward in each switch case so that the
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross * default case can move it by a whole multi-byte seq.
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross while ((pc = *pat) != '\0') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross switch (pc) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross case '?': /* exactly one of any character */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross pat++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (*str != '\0') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross ADVANCE(str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /* EOS: no-match */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (0);
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross case '*': /* zero or more of any characters */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross pat++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /* Optimize '*' at end of pattern. */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (*pat == '\0')
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (1); /* match */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross while (*str != '\0') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross priv->depth++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross rc = smb_match_private(pat, str, priv);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross priv->depth--;
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright if (rc != 0)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (rc); /* match */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross ADVANCE(str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross case '<': /* any string up through the last dot or EOS */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross pat++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if ((limit = strrchr(str, '.')) != NULL)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross limit++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross while (*str != '\0' && str != limit) {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross priv->depth++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross rc = smb_match_private(pat, str, priv);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross priv->depth--;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (rc != 0)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (rc); /* match */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross ADVANCE(str);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross case '>': /* anything not a dot, dot at EOS, or EOS */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross pat++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (*str == '.') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (str[1] == '\0') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /* dot at EOS */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross str++; /* ADVANCE over '.' */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /* dot NOT at EOS: no-match */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (0);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (*str != '\0') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /* something not a dot */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross ADVANCE(str);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross case '\"': /* dot, or EOS */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross pat++;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (*str == '.') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross str++; /* ADVANCE over '.' */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (*str == '\0') {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /* something else: no-match */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (0);
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross default: /* not a wildcard */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross nbpat = smb_mbtowc(&wcpat, pat, MTS_MB_CHAR_MAX);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross nbstr = smb_mbtowc(&wcstr, str, MTS_MB_CHAR_MAX);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross /* make sure we advance */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (nbpat < 1 || nbstr < 1)
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (-1);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (wcpat == wcstr) {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross pat += nbpat;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross str += nbstr;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (priv->ci) {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross wcpat = smb_tolower(wcpat);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross wcstr = smb_tolower(wcstr);
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross if (wcpat == wcstr) {
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross pat += nbpat;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross str += nbstr;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross continue;
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (0); /* no-match */
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross }
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright }
c13be35a2c14be5433f5d23a6c4f84e66439b7b6Gordon Ross return (*str == '\0');
94fff7907278e4540aa7abee2b1b0ea71d36f7faAlan Wright}