summaryrefslogtreecommitdiff
path: root/source3/lib/ms_fnmatch.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-04-30 04:45:16 +0000
committerAndrew Tridgell <tridge@samba.org>2000-04-30 04:45:16 +0000
commit71e7974f3f847759ba6f844ea7f482786cc5db02 (patch)
treedab76d4d1260161ae515907a852a1c00bdb52511 /source3/lib/ms_fnmatch.c
parentc0e1c6505329972835ccbf6886f8aab8eb33e634 (diff)
downloadsamba-71e7974f3f847759ba6f844ea7f482786cc5db02.tar.gz
samba-71e7974f3f847759ba6f844ea7f482786cc5db02.tar.bz2
samba-71e7974f3f847759ba6f844ea7f482786cc5db02.zip
YIPEE!!!!!
We finally have a perfect emulation of Microsoft wildcard matching. The routine ms_fnmatch() does wildcard matching with all MS wildcards (including the unicode wildcards), and masktest against a NT4 workstation with hundreds of thousands of random exmaples has not found a single error. amazingly it is only about 60 lines of code, but it has taken us years to get it right. I didn't sleep much last night :) (This used to be commit cc9e007cdfdd300189f89e2a55e4234e47fa842d)
Diffstat (limited to 'source3/lib/ms_fnmatch.c')
-rw-r--r--source3/lib/ms_fnmatch.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c
new file mode 100644
index 0000000000..d9475cb6ef
--- /dev/null
+++ b/source3/lib/ms_fnmatch.c
@@ -0,0 +1,146 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+
+ Copyright (C) Andrew Tridgell 1992-1998
+
+ This module is derived from fnmatch.c copyright by the Free
+ Software Foundation. It has been extensively modified to implement
+ the wildcard matcing semantics of Microsoft SMB servers.
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* this matches only filenames, with no directory component */
+#if FNMATCH_TEST
+#include <stdio.h>
+#include <stdlib.h>
+#else
+#include "includes.h"
+#endif
+
+/* the following function was derived using the masktest utility -
+ after years of effort we finally have a perfect MS wildcard
+ matching routine! */
+int ms_fnmatch(char *pattern, char *string)
+{
+ char *p = pattern, *n = string;
+ char c;
+
+ while ((c = *p++)) {
+ switch (c) {
+ case '?':
+ if (! *n) return -1;
+ n++;
+ break;
+
+ case '>':
+ if (n[0] == '.') {
+ if (! n[1] && ms_fnmatch(p, n+1) == 0) return 0;
+ if (ms_fnmatch(p, n) == 0) return 0;
+ return -1;
+ }
+ if (! *n) return ms_fnmatch(p, n);
+ n++;
+ break;
+
+ case '*':
+ for (; *n; n++) {
+ if (ms_fnmatch(p, n) == 0) return 0;
+ }
+ break;
+
+ case '<':
+ for (; *n; n++) {
+ if (ms_fnmatch(p, n) == 0) return 0;
+ if (*n == '.' && !strchr(n+1,'.')) {
+ n++;
+ break;
+ }
+ }
+ break;
+
+ case '"':
+ if (*n == 0 && ms_fnmatch(p, n) == 0) return 0;
+ if (*n != '.') return -1;
+ n++;
+ break;
+
+ default:
+ if (c != *n) return -1;
+ n++;
+ }
+ }
+
+ if (! *n) return 0;
+
+ return -1;
+}
+
+
+#if FNMATCH_TEST
+
+static int match_one(char *pattern, char *file)
+{
+ if (strcmp(file,"..") == 0) file = ".";
+ if (strcmp(pattern,".") == 0) return -1;
+
+ return ms_fnmatch(pattern, file);
+}
+
+static char *match_test(char *pattern, char *file, char *short_name)
+{
+ static char ret[4];
+ strncpy(ret, "---", 3);
+
+ if (match_one(pattern, ".") == 0) ret[0] = '+';
+ if (match_one(pattern, "..") == 0) ret[1] = '+';
+ if (match_one(pattern, file) == 0 ||
+ (*short_name && match_one(pattern, short_name)==0)) ret[2] = '+';
+ return ret;
+}
+
+ int main(int argc, char *argv[])
+{
+ int ret;
+ char ans[4], mask[100], file[100], mfile[100];
+ char *ans2;
+ int n, i=0;
+ char line[200];
+
+ if (argc == 3) {
+ ret = ms_fnmatch(argv[1], argv[2]);
+ if (ret == 0)
+ printf("YES\n");
+ else printf("NO\n");
+ return ret;
+ }
+ mfile[0] = 0;
+
+ while (fgets(line, sizeof(line)-1, stdin)) {
+ n = sscanf(line, "%3s %s %s %s\n", ans, mask, file, mfile);
+ if (n < 3) continue;
+ ans2 = match_test(mask, file, mfile);
+ if (strcmp(ans2, ans)) {
+ printf("%s %s %d mask=[%s] file=[%s] mfile=[%s]\n",
+ ans, ans2, i, mask, file, mfile);
+ }
+ i++;
+ mfile[0] = 0;
+ }
+ return 0;
+}
+#endif