few edits
[Samba.git] / source / lib / ms_fnmatch.c
blob87e40049e05ff74a31d60f4f43a5859db335f9ce
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 filename matching routine
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 This module was originally based on fnmatch.c copyright by the Free
23 Software Foundation. It bears little resemblence to that code now
24 */
27 #include "includes.h"
29 /*
30 bugger. we need a separate wildcard routine for older versions
31 of the protocol. This is not yet perfect, but its a lot
32 better thaan what we had */
33 static int ms_fnmatch_lanman_core(const char *pattern, const char *string)
35 const char *p = pattern, *n = string;
36 char c;
38 if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match;
40 while ((c = *p++)) {
41 switch (c) {
42 case '.':
43 if (! *n) goto next;
44 /* if (! *n && ! *p) goto match; */
45 if (*n != '.') goto nomatch;
46 n++;
47 break;
49 case '?':
50 if (! *n) goto next;
51 if ((*n == '.' && n[1] != '.') || ! *n) goto next;
52 n++;
53 break;
55 case '>':
56 if (! *n) goto next;
57 if (n[0] == '.') {
58 if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match;
59 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
60 goto nomatch;
62 n++;
63 break;
65 case '*':
66 if (! *n) goto next;
67 if (! *p) goto match;
68 for (; *n; n++) {
69 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
71 break;
73 case '<':
74 for (; *n; n++) {
75 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
76 if (*n == '.' && !strchr(n+1,'.')) {
77 n++;
78 break;
81 break;
83 case '"':
84 if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match;
85 if (*n != '.') goto nomatch;
86 n++;
87 break;
89 default:
90 if (c != *n) goto nomatch;
91 n++;
95 if (! *n) goto match;
97 nomatch:
99 if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string);
101 return -1;
103 next:
104 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
105 goto nomatch;
107 match:
109 if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string);
111 return 0;
114 static int ms_fnmatch_lanman1(const char *pattern, const char *string)
116 if (!strpbrk(pattern, "?*<>\"")) {
117 if (strcmp(string,"..") == 0) string = ".";
118 return strcasecmp(pattern, string);
121 if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) {
122 return ms_fnmatch_lanman_core(pattern, "..") &&
123 ms_fnmatch_lanman_core(pattern, ".");
126 return ms_fnmatch_lanman_core(pattern, string);
130 /* the following function was derived using the masktest utility -
131 after years of effort we finally have a perfect MS wildcard
132 matching routine!
134 NOTE: this matches only filenames with no directory component
136 Returns 0 on match, -1 on fail.
138 int ms_fnmatch(const char *pattern, const char *string)
140 const char *p = pattern, *n = string;
141 char c;
142 extern int Protocol;
144 if (Protocol <= PROTOCOL_LANMAN2) {
145 return ms_fnmatch_lanman1(pattern, string);
148 while ((c = *p++)) {
149 switch (c) {
150 case '?':
151 if (! *n) return -1;
152 n++;
153 break;
155 case '>':
156 if (n[0] == '.') {
157 if (! n[1] && ms_fnmatch(p, n+1) == 0) return 0;
158 if (ms_fnmatch(p, n) == 0) return 0;
159 return -1;
161 if (! *n) return ms_fnmatch(p, n);
162 n++;
163 break;
165 case '*':
166 for (; *n; n++) {
167 if (ms_fnmatch(p, n) == 0) return 0;
169 break;
171 case '<':
172 for (; *n; n++) {
173 if (ms_fnmatch(p, n) == 0) return 0;
174 if (*n == '.' && !strchr(n+1,'.')) {
175 n++;
176 break;
179 break;
181 case '"':
182 if (*n == 0 && ms_fnmatch(p, n) == 0) return 0;
183 if (*n != '.') return -1;
184 n++;
185 break;
187 default:
188 if (c != *n) return -1;
189 n++;
193 if (! *n) return 0;
195 return -1;