xref: /illumos-gate/usr/src/common/smbsrv/smb_match.c (revision 1d7f3fadeebf3754e3f042d91e7a4439755dc598)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #ifndef _KERNEL
29 #include <stdlib.h>
30 #include <string.h>
31 #else
32 #include <sys/types.h>
33 #include <sys/sunddi.h>
34 #endif
35 #include <smbsrv/ctype.h>
36 
37 
38 /*
39  *	c	Any non-special character matches itslef
40  *	?	Match any character
41  *	ab	character 'a' followed by character 'b'
42  *	S	Any string of non-special characters
43  *	AB	String 'A' followed by string 'B'
44  *	*	Any String, including the empty string
45  */
46 int
47 smb_match(char *patn, char *str)
48 {
49 	for (;;) {
50 		switch (*patn) {
51 		case 0:
52 			return (*str == 0);
53 
54 		case '?':
55 			if (*str != 0) {
56 				str++;
57 				patn++;
58 				continue;
59 			} else {
60 				return (0);
61 			}
62 			/*NOTREACHED*/
63 
64 #if 0
65 		case '[':
66 			int	invert = 0, clower, cupper;
67 
68 			patn++;
69 			if (*patn == '!') {
70 				invert = 1;
71 				patn++;
72 			}
73 			for (;;) {
74 				clower = *patn;
75 				if (clower == 0)
76 					break;
77 				if (clower == ']') {
78 					patn++;
79 					break;
80 				}
81 				patn++;
82 				if (*patn == '-') {
83 					/* range */
84 					patn++;
85 					cupper = *patn;
86 					if (cupper == 0)
87 						break;
88 					patn++;
89 				} else {
90 					cupper = clower;
91 				}
92 				if (*str < clower || cupper < *str)
93 					continue;
94 
95 				/* match */
96 				if (invert)
97 					return (0);
98 
99 				while (*patn && *patn++ != ']')
100 					;
101 				str++;
102 				continue; /* THIS WON`T WORK */
103 			}
104 			if (invert) {
105 				str++;
106 				continue;
107 			}
108 			return (0);
109 
110 #endif
111 
112 		case '*':
113 			patn++;
114 			if (*patn == 0)
115 				return (1);
116 
117 #if 0
118 			if (*patn != '?' && *patn != '*' && *patn != '[') {
119 				/* accelerate */
120 				while (*str) {
121 					if (*str == *patn &&
122 					    match(patn+1, str+1))
123 						return (1);
124 					str++;
125 				}
126 				return (0);
127 			}
128 #endif
129 
130 			while (*str) {
131 				if (smb_match(patn, str))
132 					return (1);
133 				str++;
134 			}
135 			return (0);
136 
137 		default:
138 			if (*str != *patn)
139 				return (0);
140 			str++;
141 			patn++;
142 			continue;
143 		}
144 	}
145 }
146 
147 int
148 smb_match83(char *patn, char *str83)
149 {
150 	int	avail;
151 	char	*ptr;
152 	char	name83[14];
153 
154 	ptr = name83;
155 	for (avail = 8; (avail > 0) && (*patn != '.') && (*patn != 0);
156 	    avail--) {
157 		*(ptr++) = *(patn++);
158 	}
159 	while (avail--)
160 		*(ptr++) = ' ';
161 	*(ptr++) = '.';
162 
163 	if (*patn == '.')
164 		patn++;
165 	else if (*patn != 0)
166 		return (0);
167 
168 	for (avail = 3; (avail > 0) && (*patn != 0); avail--) {
169 		*(ptr++) = *(patn++);
170 	}
171 	if (*patn != 0)
172 		return (0);
173 
174 	while (avail--)
175 		*(ptr++) = ' ';
176 	*ptr = 0;
177 
178 	return (smb_match_ci(name83, str83));
179 }
180 
181 
182 
183 int
184 smb_match_ci(char *patn, char *str)
185 {
186 	/*
187 	 * "<" is a special pattern that matches only those names that do
188 	 * NOT have an extension. "." and ".." are ok.
189 	 */
190 	if (strcmp(patn, "<") == 0) {
191 		if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
192 			return (1);
193 		if (strchr(str, '.') == 0)
194 			return (1);
195 		return (0);
196 	}
197 	for (;;) {
198 		switch (*patn) {
199 		case 0:
200 			return (*str == 0);
201 
202 		case '?':
203 			if (*str != 0) {
204 				str++;
205 				patn++;
206 				continue;
207 			} else {
208 				return (0);
209 			}
210 			/*NOTREACHED*/
211 
212 
213 		case '*':
214 			patn++;
215 			if (*patn == 0)
216 				return (1);
217 
218 			while (*str) {
219 				if (smb_match_ci(patn, str))
220 					return (1);
221 				str++;
222 			}
223 			return (0);
224 
225 		default:
226 			if (*str != *patn) {
227 				int	c1 = *str;
228 				int	c2 = *patn;
229 
230 				c1 = mts_tolower(c1);
231 				c2 = mts_tolower(c2);
232 				if (c1 != c2)
233 					return (0);
234 			}
235 			str++;
236 			patn++;
237 			continue;
238 		}
239 	}
240 	/* NOT REACHED */
241 }
242