lib/util: Move unix_wild_match() from source3/lib/util to lib/util/
[kai/samba-autobuild/.git] / lib / util / unix_match.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Jeremy Allison       2001
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include <talloc.h>
22 #include "lib/util/talloc_stack.h"
23 #include "lib/util/charset/charset.h"
24 #include "lib/util/unix_match.h"
25
26 /*********************************************************
27  Recursive routine that is called by unix_wild_match.
28 *********************************************************/
29
30 static bool unix_do_match(const char *regexp, const char *str)
31 {
32         const char *p;
33
34         for( p = regexp; *p && *str; ) {
35
36                 switch(*p) {
37                         case '?':
38                                 str++;
39                                 p++;
40                                 break;
41
42                         case '*':
43
44                                 /*
45                                  * Look for a character matching
46                                  * the one after the '*'.
47                                  */
48                                 p++;
49                                 if(!*p) {
50                                         return true; /* Automatic match */
51                                 }
52                                 while(*str) {
53
54                                         while(*str && (*p != *str)) {
55                                                 str++;
56                                         }
57
58                                         /*
59                                          * Patch from weidel@multichart.de.
60                                          * In the case of the regexp
61                                          * '*XX*' we want to ensure there are
62                                          * at least 2 'X' characters in the
63                                          * string after the '*' for a match to
64                                          * be made.
65                                          */
66
67                                         {
68                                                 int matchcount=0;
69
70                                                 /*
71                                                  * Eat all the characters that
72                                                  * match, but count how many
73                                                  * there were.
74                                                  */
75
76                                                 while(*str && (*p == *str)) {
77                                                         str++;
78                                                         matchcount++;
79                                                 }
80
81                                                 /*
82                                                  * Now check that if the regexp
83                                                  * had n identical characters
84                                                  * that matchcount had at least
85                                                  * that many matches.
86                                                  */
87
88                                                 while (*(p+1) && (*(p+1)==*p)) {
89                                                         p++;
90                                                         matchcount--;
91                                                 }
92
93                                                 if ( matchcount <= 0 ) {
94                                                         return false;
95                                                 }
96                                         }
97
98                                         /*
99                                          * We've eaten the match char
100                                          * after the '*'
101                                          */
102                                         str--;
103
104                                         if(unix_do_match(p, str)) {
105                                                 return true;
106                                         }
107
108                                         if(!*str) {
109                                                 return false;
110                                         } else {
111                                                 str++;
112                                         }
113                                 }
114                                 return false;
115
116                         default:
117                                 if(*str != *p) {
118                                         return false;
119                                 }
120                                 str++;
121                                 p++;
122                                 break;
123                 }
124         }
125
126         if(!*p && !*str) {
127                 return true;
128         }
129
130         if (!*p && str[0] == '.' && str[1] == 0) {
131                 return true;
132         }
133
134         if (!*str && *p == '?') {
135                 while (*p == '?') {
136                         p++;
137                 }
138                 return(!*p);
139         }
140
141         if(!*str && (*p == '*' && p[1] == '\0')) {
142                 return true;
143         }
144
145         return false;
146 }
147
148 /*******************************************************************
149  Simple case insensitive interface to a UNIX wildcard matcher.
150  Returns True if match, False if not.
151 *******************************************************************/
152
153 bool unix_wild_match(const char *pattern, const char *string)
154 {
155         TALLOC_CTX *ctx = talloc_stackframe();
156         char *p2;
157         char *s2;
158         char *p;
159         bool ret = false;
160
161         p2 = strlower_talloc(ctx, pattern);
162         s2 = strlower_talloc(ctx, string);
163         if (!p2 || !s2) {
164                 TALLOC_FREE(ctx);
165                 return false;
166         }
167
168         /* Remove any *? and ** from the pattern as they are meaningless */
169         for(p = p2; *p; p++) {
170                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
171                         memmove(&p[1], &p[2], strlen(&p[2])+1);
172                 }
173         }
174
175         if (p2[0] == '*' && p2[1] == '\0') {
176                 TALLOC_FREE(ctx);
177                 return true;
178         }
179
180         ret = unix_do_match(p2, s2);
181         TALLOC_FREE(ctx);
182         return ret;
183 }