From 71e7974f3f847759ba6f844ea7f482786cc5db02 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 04:45:16 +0000 Subject: 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) --- source3/lib/ms_fnmatch.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 source3/lib/ms_fnmatch.c (limited to 'source3/lib/ms_fnmatch.c') 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 +#include +#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 -- cgit From aa6040c7ce96ea974967b4e9ec7d13778d3a43a5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 11:25:09 +0000 Subject: some cleanups (This used to be commit 95f6c0f84ab9f3649ddf53ac2ca5261448af2383) --- source3/lib/ms_fnmatch.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index d9475cb6ef..ee9b1cf985 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -1,14 +1,9 @@ /* Unix SMB/Netbios implementation. Version 3.0 - + filename matching routine 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 @@ -23,8 +18,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + This module was originally based on fnmatch.c copyright by the Free + Software Foundation. It bears little resemblence to that code now +*/ + -/* this matches only filenames, with no directory component */ #if FNMATCH_TEST #include #include @@ -34,7 +33,10 @@ /* the following function was derived using the masktest utility - after years of effort we finally have a perfect MS wildcard - matching routine! */ + matching routine! + + NOTE: this matches only filenames with no directory component +*/ int ms_fnmatch(char *pattern, char *string) { char *p = pattern, *n = string; @@ -85,7 +87,7 @@ int ms_fnmatch(char *pattern, char *string) } } - if (! *n) return 0; + if (! *n) return 0; return -1; } @@ -143,4 +145,5 @@ static char *match_test(char *pattern, char *file, char *short_name) } return 0; } -#endif +#endif /* FNMATCH_TEST */ + -- cgit From 693ffb8466ada58ecc59fde754ba79fc6f51528d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 May 2000 02:23:41 +0000 Subject: Added sys_fork() and sys_getpid() functions to stop the overhead of doing a system call every time we want to just get our pid. Jeremy. (This used to be commit 148628b616b5c29ba6340d65fc3ddbcabba6e67a) --- source3/lib/ms_fnmatch.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index ee9b1cf985..364fd6f347 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -36,6 +36,8 @@ matching routine! NOTE: this matches only filenames with no directory component + + Returns 0 on match, -1 on fail. */ int ms_fnmatch(char *pattern, char *string) { -- cgit From 8a1c2e02984edd17e6ab0d5088a80c4dd5f9b933 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Apr 2001 05:41:07 +0000 Subject: AIX ACLs donated by IBM. Merge Andrew's fnmatch fix for WfW. Jeremy. (This used to be commit 1d4438f07745df3d02ed8ab3ef048e20016816b6) --- source3/lib/ms_fnmatch.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 364fd6f347..c4ebaf6aa2 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -31,6 +31,106 @@ #include "includes.h" #endif + + +/* + bugger. we need a separate wildcard routine for older versions + of the protocol. This is not yet perfect, but its a lot + better thaan what we had */ +static int ms_fnmatch_lanman_core(char *pattern, char *string) +{ + char *p = pattern, *n = string; + char c; + + if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match; + + while ((c = *p++)) { + switch (c) { + case '.': + /* if (! *n && ! *p) goto match; */ + if (*n != '.') goto nomatch; + n++; + break; + + case '?': + if ((*n == '.' && n[1] != '.') || ! *n) goto next; + n++; + break; + + case '>': + if (n[0] == '.') { + if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + goto nomatch; + } + if (! *n) goto next; + n++; + break; + + case '*': + if (! *p) goto match; + for (; *n; n++) { + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + } + break; + + case '<': + for (; *n; n++) { + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n == '.' && !strchr(n+1,'.')) { + n++; + break; + } + } + break; + + case '"': + if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n != '.') goto nomatch; + n++; + break; + + default: + if (c != *n) goto nomatch; + n++; + } + } + + if (! *n) goto match; + + nomatch: + /* + if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string); + */ + return -1; + +next: + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + goto nomatch; + + match: + /* + if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string); + */ + return 0; +} + +static int ms_fnmatch_lanman1(char *pattern, char *string) +{ + if (!strpbrk(pattern, "?*<>\"")) { + if (strcmp(string,"..") == 0) string = "."; + return strcmp(pattern, string); + } + + if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) { + return ms_fnmatch_lanman_core(pattern, "..") && + ms_fnmatch_lanman_core(pattern, "."); + } + + return ms_fnmatch_lanman_core(pattern, string); +} + + /* the following function was derived using the masktest utility - after years of effort we finally have a perfect MS wildcard matching routine! @@ -43,6 +143,11 @@ int ms_fnmatch(char *pattern, char *string) { char *p = pattern, *n = string; char c; + extern int Protocol; + + if (Protocol <= PROTOCOL_LANMAN2) { + return ms_fnmatch_lanman1(pattern, string); + } while ((c = *p++)) { switch (c) { -- cgit From 82afede9fa4729ed91e583b4432508f3c887cfdf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Apr 2001 07:09:42 +0000 Subject: Merged Andrew's wfw fix (2). Jeremy. (This used to be commit a4fb755a48d27f21bd0a5d9e9d1227a08c13bdff) --- source3/lib/ms_fnmatch.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index c4ebaf6aa2..b4591c7dbc 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -47,27 +47,30 @@ static int ms_fnmatch_lanman_core(char *pattern, char *string) while ((c = *p++)) { switch (c) { case '.': + if (! *n) goto next; /* if (! *n && ! *p) goto match; */ if (*n != '.') goto nomatch; n++; break; case '?': + if (! *n) goto next; if ((*n == '.' && n[1] != '.') || ! *n) goto next; n++; break; case '>': + if (! *n) goto next; if (n[0] == '.') { if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; if (ms_fnmatch_lanman_core(p, n) == 0) goto match; goto nomatch; } - if (! *n) goto next; n++; break; case '*': + if (! *n) goto next; if (! *p) goto match; for (; *n; n++) { if (ms_fnmatch_lanman_core(p, n) == 0) goto match; @@ -119,7 +122,7 @@ static int ms_fnmatch_lanman1(char *pattern, char *string) { if (!strpbrk(pattern, "?*<>\"")) { if (strcmp(string,"..") == 0) string = "."; - return strcmp(pattern, string); + return strcasecmp(pattern, string); } if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) { -- cgit From aac630b382fefff2e3ead291d2d838832a180925 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 May 2001 23:32:09 +0000 Subject: Had to add a "pam password change" parameter (defaults to "off") and inlined the pam password change code to ensure that existing and working password chat scripts don't break with 2.2.1. PAM password changing has to be explicitly requested. Allowed wildcards in pam password change matching (matches password chat script matching). Had to add const (sorry Tim :-) to ms_fnmatch() to stop warnings. Don't worry - the const changes are isolated and don't cause any other warnings :-). Jeremy. (This used to be commit 47b4d82536c09bffe3a0d9917fa31d935f1be7d8) --- source3/lib/ms_fnmatch.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index b4591c7dbc..72f61c021c 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -37,9 +37,9 @@ bugger. we need a separate wildcard routine for older versions of the protocol. This is not yet perfect, but its a lot better thaan what we had */ -static int ms_fnmatch_lanman_core(char *pattern, char *string) +static int ms_fnmatch_lanman_core(const char *pattern, const char *string) { - char *p = pattern, *n = string; + const char *p = pattern, *n = string; char c; if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match; @@ -118,7 +118,7 @@ next: return 0; } -static int ms_fnmatch_lanman1(char *pattern, char *string) +static int ms_fnmatch_lanman1(const char *pattern, const char *string) { if (!strpbrk(pattern, "?*<>\"")) { if (strcmp(string,"..") == 0) string = "."; @@ -142,9 +142,9 @@ static int ms_fnmatch_lanman1(char *pattern, char *string) Returns 0 on match, -1 on fail. */ -int ms_fnmatch(char *pattern, char *string) +int ms_fnmatch(const char *pattern, const char *string) { - char *p = pattern, *n = string; + const char *p = pattern, *n = string; char c; extern int Protocol; -- cgit From 87fbb7092b8f8b2f0db0f361c3d625e19de57cd9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:15:53 +0000 Subject: The big character set handling changeover! This commit gets rid of all our old codepage handling and replaces it with iconv. All internal strings in Samba are now in "unix" charset, which may be multi-byte. See internals.doc and my posting to samba-technical for a more complete explanation. (This used to be commit debb471267960e56005a741817ebd227ecfc512a) --- source3/lib/ms_fnmatch.c | 145 +++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 93 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 72f61c021c..39b3e0013c 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -31,37 +31,37 @@ #include "includes.h" #endif - - /* bugger. we need a separate wildcard routine for older versions of the protocol. This is not yet perfect, but its a lot - better thaan what we had */ -static int ms_fnmatch_lanman_core(const char *pattern, const char *string) + better than what we had */ +static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, + const smb_ucs2_t *string) { - const char *p = pattern, *n = string; - char c; + const smb_ucs2_t *p = pattern, *n = string; + smb_ucs2_t c; - if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match; + if (strcmp_wa(p, "?")==0 && strcmp_wa(n, ".")) goto match; while ((c = *p++)) { switch (c) { - case '.': + case UCS2_CHAR('.'): if (! *n) goto next; - /* if (! *n && ! *p) goto match; */ - if (*n != '.') goto nomatch; + if (*n != UCS2_CHAR('.')) goto nomatch; n++; break; - case '?': + case UCS2_CHAR('?'): if (! *n) goto next; - if ((*n == '.' && n[1] != '.') || ! *n) goto next; + if ((*n == UCS2_CHAR('.') && + n[1] != UCS2_CHAR('.')) || ! *n) + goto next; n++; break; - case '>': + case UCS2_CHAR('>'): if (! *n) goto next; - if (n[0] == '.') { + if (n[0] == UCS2_CHAR('.')) { if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; if (ms_fnmatch_lanman_core(p, n) == 0) goto match; goto nomatch; @@ -69,7 +69,7 @@ static int ms_fnmatch_lanman_core(const char *pattern, const char *string) n++; break; - case '*': + case UCS2_CHAR('*'): if (! *n) goto next; if (! *p) goto match; for (; *n; n++) { @@ -77,19 +77,20 @@ static int ms_fnmatch_lanman_core(const char *pattern, const char *string) } break; - case '<': + case UCS2_CHAR('<'): for (; *n; n++) { if (ms_fnmatch_lanman_core(p, n) == 0) goto match; - if (*n == '.' && !strchr(n+1,'.')) { + if (*n == UCS2_CHAR('.') && + !strchr_w(n+1,UCS2_CHAR('.'))) { n++; break; } } break; - case '"': + case UCS2_CHAR('"'): if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; - if (*n != '.') goto nomatch; + if (*n != UCS2_CHAR('.')) goto nomatch; n++; break; @@ -118,16 +119,19 @@ next: return 0; } -static int ms_fnmatch_lanman1(const char *pattern, const char *string) +static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *string) { - if (!strpbrk(pattern, "?*<>\"")) { - if (strcmp(string,"..") == 0) string = "."; - return strcasecmp(pattern, string); + if (!strpbrk_wa(pattern, "?*<>\"")) { + smb_ucs2_t s[] = {UCS2_CHAR('.'), 0}; + if (strcmp_wa(string,"..") == 0) string = s; + return strcasecmp_w(pattern, string); } - if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) { - return ms_fnmatch_lanman_core(pattern, "..") && - ms_fnmatch_lanman_core(pattern, "."); + if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) { + smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0}; + smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0}; + return ms_fnmatch_lanman_core(pattern, dotdot) && + ms_fnmatch_lanman_core(pattern, dot); } return ms_fnmatch_lanman_core(pattern, string); @@ -142,10 +146,10 @@ static int ms_fnmatch_lanman1(const char *pattern, const char *string) Returns 0 on match, -1 on fail. */ -int ms_fnmatch(const char *pattern, const char *string) +static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string) { - const char *p = pattern, *n = string; - char c; + const smb_ucs2_t *p = pattern, *n = string; + smb_ucs2_t c; extern int Protocol; if (Protocol <= PROTOCOL_LANMAN2) { @@ -154,40 +158,40 @@ int ms_fnmatch(const char *pattern, const char *string) while ((c = *p++)) { switch (c) { - case '?': + case UCS2_CHAR('?'): 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; + case UCS2_CHAR('>'): + if (n[0] == UCS2_CHAR('.')) { + if (! n[1] && ms_fnmatch_w(p, n+1) == 0) return 0; + if (ms_fnmatch_w(p, n) == 0) return 0; return -1; } - if (! *n) return ms_fnmatch(p, n); + if (! *n) return ms_fnmatch_w(p, n); n++; break; - case '*': + case UCS2_CHAR('*'): for (; *n; n++) { - if (ms_fnmatch(p, n) == 0) return 0; + if (ms_fnmatch_w(p, n) == 0) return 0; } break; - case '<': + case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch(p, n) == 0) return 0; - if (*n == '.' && !strchr(n+1,'.')) { + if (ms_fnmatch_w(p, n) == 0) return 0; + if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { n++; break; } } break; - case '"': - if (*n == 0 && ms_fnmatch(p, n) == 0) return 0; - if (*n != '.') return -1; + case UCS2_CHAR('"'): + if (*n == 0 && ms_fnmatch_w(p, n) == 0) return 0; + if (*n != UCS2_CHAR('.')) return -1; n++; break; @@ -203,57 +207,12 @@ int ms_fnmatch(const char *pattern, const char *string) } -#if FNMATCH_TEST - -static int match_one(char *pattern, char *file) +int ms_fnmatch(const char *pattern, const char *string) { - if (strcmp(file,"..") == 0) file = "."; - if (strcmp(pattern,".") == 0) return -1; - - return ms_fnmatch(pattern, file); -} + wpstring p, s; -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; -} + pstrcpy_wa(p, pattern); + pstrcpy_wa(s, string); - 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; + return ms_fnmatch_w(p, s); } -#endif /* FNMATCH_TEST */ - -- cgit From 11ce0f4d2d493702386c0bd49c8e2dd2aad84d56 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Aug 2001 05:15:26 +0000 Subject: a bunch of fixes from the sflight to seattle in particular: - fixed NT status code for a bunch of ops - fixed handling of protocol levels in ms_fnmatch (This used to be commit 3eba9606f71f90bfd9820af26f8676277ed22390) --- source3/lib/ms_fnmatch.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 39b3e0013c..cc54ffb68e 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -146,13 +146,12 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin Returns 0 on match, -1 on fail. */ -static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string) +static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int protocol) { const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; - extern int Protocol; - if (Protocol <= PROTOCOL_LANMAN2) { + if (protocol <= PROTOCOL_LANMAN2) { return ms_fnmatch_lanman1(pattern, string); } @@ -165,23 +164,23 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string) case UCS2_CHAR('>'): if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_w(p, n+1) == 0) return 0; - if (ms_fnmatch_w(p, n) == 0) return 0; + if (! n[1] && ms_fnmatch_w(p, n+1, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol) == 0) return 0; return -1; } - if (! *n) return ms_fnmatch_w(p, n); + if (! *n) return ms_fnmatch_w(p, n, protocol); n++; break; case UCS2_CHAR('*'): for (; *n; n++) { - if (ms_fnmatch_w(p, n) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol) == 0) return 0; } break; case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch_w(p, n) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol) == 0) return 0; if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { n++; break; @@ -190,7 +189,7 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string) break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_w(p, n) == 0) return 0; + if (*n == 0 && ms_fnmatch_w(p, n, protocol) == 0) return 0; if (*n != UCS2_CHAR('.')) return -1; n++; break; @@ -207,12 +206,21 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string) } -int ms_fnmatch(const char *pattern, const char *string) +int ms_fnmatch(const char *pattern, const char *string, int protocol) { wpstring p, s; + int ret; pstrcpy_wa(p, pattern); pstrcpy_wa(s, string); - return ms_fnmatch_w(p, s); + ret = ms_fnmatch_w(p, s, protocol); +/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */ + return ret; +} + +/* a generic fnmatch function - uses for non-CIFS pattern matching */ +int gen_fnmatch(const char *pattern, const char *string) +{ + return ms_fnmatch(pattern, string, PROTOCOL_NT1); } -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/lib/ms_fnmatch.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index cc54ffb68e..106efa5bbc 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. filename matching routine Copyright (C) Andrew Tridgell 1992-1998 -- cgit From aed1610ec22bb3eb283f548892fb9e00917df5f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Aug 2003 04:25:26 +0000 Subject: Fix for bugid #205 - work by Andrew Bartlet (modified to use fixed buffer by me). Jeremy. (This used to be commit 6f68b8de4760a2103eae0a51b2aca356990ea526) --- source3/lib/ms_fnmatch.c | 82 +++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 29 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 106efa5bbc..24232c3b52 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -35,7 +35,8 @@ of the protocol. This is not yet perfect, but its a lot better than what we had */ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, - const smb_ucs2_t *string) + const smb_ucs2_t *string, + BOOL case_sensitive) { const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; @@ -61,8 +62,8 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, case UCS2_CHAR('>'): if (! *n) goto next; if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (! n[1] && ms_fnmatch_lanman_core(p, n+1, case_sensitive) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; goto nomatch; } n++; @@ -72,13 +73,13 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, if (! *n) goto next; if (! *p) goto match; for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; } break; case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; if (*n == UCS2_CHAR('.') && !strchr_w(n+1,UCS2_CHAR('.'))) { n++; @@ -88,13 +89,17 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n == 0 && ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; if (*n != UCS2_CHAR('.')) goto nomatch; n++; break; default: - if (c != *n) goto nomatch; + if (case_sensitive) { + if (c != *n) goto nomatch; + } else { + if (tolower_w(c) != tolower_w(*n)) goto nomatch; + } n++; } } @@ -108,7 +113,7 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, return -1; next: - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; goto nomatch; match: @@ -118,7 +123,8 @@ next: return 0; } -static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *string) +static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, + const smb_ucs2_t *string, BOOL case_sensitive) { if (!strpbrk_wa(pattern, "?*<>\"")) { smb_ucs2_t s[] = {UCS2_CHAR('.'), 0}; @@ -129,11 +135,11 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) { smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0}; smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0}; - return ms_fnmatch_lanman_core(pattern, dotdot) && - ms_fnmatch_lanman_core(pattern, dot); + return ms_fnmatch_lanman_core(pattern, dotdot, case_sensitive) && + ms_fnmatch_lanman_core(pattern, dot, case_sensitive); } - return ms_fnmatch_lanman_core(pattern, string); + return ms_fnmatch_lanman_core(pattern, string, case_sensitive); } @@ -145,13 +151,14 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin Returns 0 on match, -1 on fail. */ -static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int protocol) +static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, + int protocol, BOOL case_sensitive) { const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; if (protocol <= PROTOCOL_LANMAN2) { - return ms_fnmatch_lanman1(pattern, string); + return ms_fnmatch_lanman1(pattern, string, case_sensitive); } while ((c = *p++)) { @@ -163,23 +170,23 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int case UCS2_CHAR('>'): if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_w(p, n+1, protocol) == 0) return 0; - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (! n[1] && ms_fnmatch_w(p, n+1, protocol, case_sensitive) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; return -1; } - if (! *n) return ms_fnmatch_w(p, n, protocol); + if (! *n) return ms_fnmatch_w(p, n, protocol, case_sensitive); n++; break; case UCS2_CHAR('*'): for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; } break; case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { n++; break; @@ -188,13 +195,17 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (*n == 0 && ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; if (*n != UCS2_CHAR('.')) return -1; n++; break; default: - if (c != *n) return -1; + if (case_sensitive) { + if (c != *n) return -1; + } else { + if (tolower_w(c) != tolower_w(*n)) return -1; + } n++; } } @@ -204,22 +215,35 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int return -1; } - -int ms_fnmatch(const char *pattern, const char *string, int protocol) +int ms_fnmatch(const char *pattern, const char *string, int protocol, + BOOL case_senstive) { - wpstring p, s; + wpstring buffer_pattern, buffer_string; int ret; + size_t size; + + size = push_ucs2(NULL, buffer_pattern, pattern, sizeof(buffer_pattern), STR_TERMINATE); + if (size == (size_t)-1) { + return -1; + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } + + size = push_ucs2(NULL, buffer_string, string, sizeof(buffer_string), STR_TERMINATE); + if (size == (size_t)-1) { + return -1; + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } - pstrcpy_wa(p, pattern); - pstrcpy_wa(s, string); + ret = ms_fnmatch_w(buffer_pattern, buffer_string, protocol, case_senstive); + DEBUG(10,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); - ret = ms_fnmatch_w(p, s, protocol); -/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */ return ret; } /* a generic fnmatch function - uses for non-CIFS pattern matching */ int gen_fnmatch(const char *pattern, const char *string) { - return ms_fnmatch(pattern, string, PROTOCOL_NT1); + return ms_fnmatch(pattern, string, PROTOCOL_NT1, True); } -- cgit From 5480cfc26b798dd7a5a46af9c69e0921c679b3c9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Sep 2004 17:44:27 +0000 Subject: r2213: Optimisation. Passes masktest against W2K3. Jeremy. (This used to be commit 5dc3324c4f1ae10c96b6d385531369e0eeee4c40) --- source3/lib/ms_fnmatch.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 24232c3b52..42c91bd18d 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -179,6 +179,9 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, break; case UCS2_CHAR('*'): + while (*p == UCS2_CHAR('*')) { + p++; + } for (; *n; n++) { if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; } -- cgit From 640f124ca24032446ec717c06f46fc82559653fb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Oct 2004 09:14:43 +0000 Subject: r2778: merged the new samba4 ms_fnmatch code to Samba3. Thanks to Rusty Russel for some help in designing the new algorithm. (This used to be commit 38144f8d2cda32edacf90725f28e763689128d0d) --- source3/lib/ms_fnmatch.c | 307 ++++++++++++++++++++--------------------------- 1 file changed, 131 insertions(+), 176 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 42c91bd18d..bdfb26d0ca 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. filename matching routine - Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Tridgell 1992-2004 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 @@ -15,238 +15,193 @@ 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. */ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ /* This module was originally based on fnmatch.c copyright by the Free - Software Foundation. It bears little resemblence to that code now + Software Foundation. It bears little (if any) resemblence to that + code now */ -#if FNMATCH_TEST -#include -#include -#else #include "includes.h" -#endif -/* - bugger. we need a separate wildcard routine for older versions - of the protocol. This is not yet perfect, but its a lot - better than what we had */ -static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, - const smb_ucs2_t *string, - BOOL case_sensitive) +static int null_match(const smb_ucs2_t *p) { - const smb_ucs2_t *p = pattern, *n = string; - smb_ucs2_t c; + for (;*p;p++) { + if (*p != UCS2_CHAR('*') && + *p != UCS2_CHAR('<') && + *p != UCS2_CHAR('"') && + *p != UCS2_CHAR('>')) return -1; + } + return 0; +} + +/* + the max_n structure is purely for efficiency, it doesn't contribute + to the matching algorithm except by ensuring that the algorithm does + not grow exponentially +*/ +struct max_n { + const smb_ucs2_t *predot; + const smb_ucs2_t *postdot; +}; - if (strcmp_wa(p, "?")==0 && strcmp_wa(n, ".")) goto match; + +/* + p and n are the pattern and string being matched. The max_n array is + an optimisation only. The ldot pointer is NULL if the string does + not contain a '.', otherwise it points at the last dot in 'n'. +*/ +static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, + struct max_n *max_n, const smb_ucs2_t *ldot) +{ + smb_ucs2_t c; + int i; while ((c = *p++)) { switch (c) { - case UCS2_CHAR('.'): - if (! *n) goto next; - if (*n != UCS2_CHAR('.')) goto nomatch; - n++; - break; + /* a '*' matches zero or more characters of any type */ + case UCS2_CHAR('*'): + if (max_n->predot && max_n->predot <= n) { + return null_match(p); + } + for (i=0; n[i]; i++) { + if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { + return 0; + } + } + if (!max_n->predot || max_n->predot > n) max_n->predot = n; + return null_match(p); + + /* a '<' matches zero or more characters of + any type, but stops matching at the last + '.' in the string. */ + case UCS2_CHAR('<'): + if (max_n->predot && max_n->predot <= n) { + return null_match(p); + } + if (max_n->postdot && max_n->postdot <= n && n <= ldot) { + return -1; + } + for (i=0; n[i]; i++) { + if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0; + if (n+i == ldot) { + if (ms_fnmatch_core(p, n+i+1, max_n+1, ldot) == 0) return 0; + if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n; + return -1; + } + } + if (!max_n->predot || max_n->predot > n) max_n->predot = n; + return null_match(p); + /* a '?' matches any single character */ case UCS2_CHAR('?'): - if (! *n) goto next; - if ((*n == UCS2_CHAR('.') && - n[1] != UCS2_CHAR('.')) || ! *n) - goto next; + if (! *n) { + return -1; + } n++; break; + /* a '?' matches any single character */ case UCS2_CHAR('>'): - if (! *n) goto next; if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_lanman_core(p, n+1, case_sensitive) == 0) goto match; - if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; - goto nomatch; - } - n++; - break; - - case UCS2_CHAR('*'): - if (! *n) goto next; - if (! *p) goto match; - for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; - } - break; - - case UCS2_CHAR('<'): - for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; - if (*n == UCS2_CHAR('.') && - !strchr_w(n+1,UCS2_CHAR('.'))) { - n++; - break; + if (! n[1] && null_match(p) == 0) { + return 0; } + break; } + if (! *n) return null_match(p); + n++; break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; - if (*n != UCS2_CHAR('.')) goto nomatch; + if (*n == 0 && null_match(p) == 0) { + return 0; + } + if (*n != UCS2_CHAR('.')) return -1; n++; break; default: - if (case_sensitive) { - if (c != *n) goto nomatch; - } else { - if (tolower_w(c) != tolower_w(*n)) goto nomatch; + if (c != *n && toupper_w(c) != toupper_w(*n)) { + return -1; } n++; + break; } } - if (! *n) goto match; + if (! *n) { + return 0; + } - nomatch: - /* - if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string); - */ return -1; - -next: - if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; - goto nomatch; - - match: - /* - if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string); - */ - return 0; } -static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, - const smb_ucs2_t *string, BOOL case_sensitive) +int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) { - if (!strpbrk_wa(pattern, "?*<>\"")) { - smb_ucs2_t s[] = {UCS2_CHAR('.'), 0}; - if (strcmp_wa(string,"..") == 0) string = s; - return strcasecmp_w(pattern, string); - } + wpstring p, s; + int ret, count, i; + struct max_n *max_n = NULL; - if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) { - smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0}; - smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0}; - return ms_fnmatch_lanman_core(pattern, dotdot, case_sensitive) && - ms_fnmatch_lanman_core(pattern, dot, case_sensitive); + if (strcmp(string, "..") == 0) { + string = "."; } - return ms_fnmatch_lanman_core(pattern, string, case_sensitive); -} - - -/* the following function was derived using the masktest utility - - after years of effort we finally have a perfect MS wildcard - matching routine! - - NOTE: this matches only filenames with no directory component - - Returns 0 on match, -1 on fail. -*/ -static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, - int protocol, BOOL case_sensitive) -{ - const smb_ucs2_t *p = pattern, *n = string; - smb_ucs2_t c; - - if (protocol <= PROTOCOL_LANMAN2) { - return ms_fnmatch_lanman1(pattern, string, case_sensitive); + if (strpbrk(pattern, "<>*?\"") == NULL) { + /* this is not just an optmisation - it is essential + for LANMAN1 correctness */ + return StrCaseCmp(pattern, string); } - while ((c = *p++)) { - switch (c) { - case UCS2_CHAR('?'): - if (! *n) return -1; - n++; - break; - - case UCS2_CHAR('>'): - if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_w(p, n+1, protocol, case_sensitive) == 0) return 0; - if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; - return -1; - } - if (! *n) return ms_fnmatch_w(p, n, protocol, case_sensitive); - n++; - break; - - case UCS2_CHAR('*'): - while (*p == UCS2_CHAR('*')) { - p++; - } - for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; - } - break; + pstrcpy_wa(p, pattern); + pstrcpy_wa(s, string); - case UCS2_CHAR('<'): - for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; - if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { - n++; - break; - } - } - break; - - case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; - if (*n != UCS2_CHAR('.')) return -1; - n++; - break; - - default: - if (case_sensitive) { - if (c != *n) return -1; - } else { - if (tolower_w(c) != tolower_w(*n)) return -1; + if (protocol <= PROTOCOL_LANMAN2) { + /* + for older negotiated protocols it is possible to + translate the pattern to produce a "new style" + pattern that exactly matches w2k behaviour + */ + for (i=0;p[i];i++) { + if (p[i] == UCS2_CHAR('?')) { + p[i] = UCS2_CHAR('>'); + } else if (p[i] == UCS2_CHAR('.') && + (p[i+1] == UCS2_CHAR('?') || + p[i+1] == UCS2_CHAR('*') || + p[i+1] == 0)) { + p[i] = UCS2_CHAR('"'); + } else if (p[i] == UCS2_CHAR('*') && p[i+1] == UCS2_CHAR('.')) { + p[i] = UCS2_CHAR('<'); } - n++; } } - - if (! *n) return 0; - - return -1; -} -int ms_fnmatch(const char *pattern, const char *string, int protocol, - BOOL case_senstive) -{ - wpstring buffer_pattern, buffer_string; - int ret; - size_t size; - - size = push_ucs2(NULL, buffer_pattern, pattern, sizeof(buffer_pattern), STR_TERMINATE); - if (size == (size_t)-1) { - return -1; - /* Not quite the right answer, but finding the right one - under this failure case is expensive, and it's pretty close */ + for (count=i=0;p[i];i++) { + if (p[i] == UCS2_CHAR('*') || p[i] == UCS2_CHAR('<')) count++; } - - size = push_ucs2(NULL, buffer_string, string, sizeof(buffer_string), STR_TERMINATE); - if (size == (size_t)-1) { - return -1; - /* Not quite the right answer, but finding the right one - under this failure case is expensive, and it's pretty close */ + + if (count != 0) { + max_n = calloc(sizeof(struct max_n), count); + if (!max_n) { + return -1; + } } - ret = ms_fnmatch_w(buffer_pattern, buffer_string, protocol, case_senstive); - DEBUG(10,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); + ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.'))); + + if (max_n) { + free(max_n); + } return ret; } + /* a generic fnmatch function - uses for non-CIFS pattern matching */ int gen_fnmatch(const char *pattern, const char *string) { - return ms_fnmatch(pattern, string, PROTOCOL_NT1, True); + return ms_fnmatch(pattern, string, PROTOCOL_NT1); } -- cgit From d9b8eaabc5e1d549aa56ed45f2e410ad766075be Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 5 Oct 2004 03:26:02 +0000 Subject: r2824: restored the is_case_sensitive option to ms_fnmatch() in Samba3. It is very rarely used, but we sohuldn't be removing a feature in a minor release of this kind. (This used to be commit 4ce0505bc369243aa77013519ce4e4f6e50f5a48) --- source3/lib/ms_fnmatch.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index bdfb26d0ca..3040dc7f9d 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -55,7 +55,8 @@ struct max_n { not contain a '.', otherwise it points at the last dot in 'n'. */ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, - struct max_n *max_n, const smb_ucs2_t *ldot) + struct max_n *max_n, const smb_ucs2_t *ldot, + BOOL is_case_sensitive) { smb_ucs2_t c; int i; @@ -68,7 +69,7 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, return null_match(p); } for (i=0; n[i]; i++) { - if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { + if (ms_fnmatch_core(p, n+i, max_n+1, ldot, is_case_sensitive) == 0) { return 0; } } @@ -86,9 +87,9 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, return -1; } for (i=0; n[i]; i++) { - if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0; + if (ms_fnmatch_core(p, n+i, max_n+1, ldot, is_case_sensitive) == 0) return 0; if (n+i == ldot) { - if (ms_fnmatch_core(p, n+i+1, max_n+1, ldot) == 0) return 0; + if (ms_fnmatch_core(p, n+i+1, max_n+1, ldot, is_case_sensitive) == 0) return 0; if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n; return -1; } @@ -125,8 +126,13 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, break; default: - if (c != *n && toupper_w(c) != toupper_w(*n)) { - return -1; + if (c != *n) { + if (is_case_sensitive) { + return -1; + } + if (toupper_w(c) != toupper_w(*n)) { + return -1; + } } n++; break; @@ -140,7 +146,8 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, return -1; } -int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) +int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol, + BOOL is_case_sensitive) { wpstring p, s; int ret, count, i; @@ -153,7 +160,11 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot if (strpbrk(pattern, "<>*?\"") == NULL) { /* this is not just an optmisation - it is essential for LANMAN1 correctness */ - return StrCaseCmp(pattern, string); + if (is_case_sensitive) { + return strcmp(pattern, string); + } else { + return StrCaseCmp(pattern, string); + } } pstrcpy_wa(p, pattern); @@ -190,7 +201,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot } } - ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.'))); + ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.')), is_case_sensitive); if (max_n) { free(max_n); @@ -203,5 +214,5 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot /* a generic fnmatch function - uses for non-CIFS pattern matching */ int gen_fnmatch(const char *pattern, const char *string) { - return ms_fnmatch(pattern, string, PROTOCOL_NT1); + return ms_fnmatch(pattern, string, PROTOCOL_NT1, False); } -- cgit From d7a1c4f79c7c9d7038096a34626ba7236e856929 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Dec 2004 00:55:47 +0000 Subject: r4032: Fix bug #2110 - ensure we convert to ucs2 correctly. Jeremy. (This used to be commit a1e5a2a6ab1abc9add7a606e2e3f2d6c88dcf96c) --- source3/lib/ms_fnmatch.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 3040dc7f9d..71f3959c24 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -167,8 +167,17 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot } } - pstrcpy_wa(p, pattern); - pstrcpy_wa(s, string); + if (push_ucs2(NULL, p, pattern, sizeof(p), STR_TERMINATE) == (size_t)-1) { + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + return -1; + } + + if (push_ucs2(NULL, s, string, sizeof(s), STR_TERMINATE) == (size_t)-1) { + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + return -1; + } if (protocol <= PROTOCOL_LANMAN2) { /* -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/lib/ms_fnmatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 71f3959c24..a0cbfd2ee2 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -204,7 +204,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot } if (count != 0) { - max_n = calloc(sizeof(struct max_n), count); + max_n = SMB_CALLOC_ARRAY(struct max_n, count); if (!max_n) { return -1; } -- cgit From 445a9729f03117afdaa141a6d074d8af064b4399 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Mar 2005 19:33:02 +0000 Subject: r6044: Ensure the old search calls always ask mask_match to translate patterns like ????????.??? - even if using an NT1 protocol. Matches W2K3 behavior. Jeremy. (This used to be commit 67f6473f50f3284b9ccbe6f983f23cd42b3b7c9f) --- source3/lib/ms_fnmatch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index a0cbfd2ee2..c7cf54d26b 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -146,7 +146,7 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, return -1; } -int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol, +int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern, BOOL is_case_sensitive) { wpstring p, s; @@ -179,7 +179,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot return -1; } - if (protocol <= PROTOCOL_LANMAN2) { + if (translate_pattern) { /* for older negotiated protocols it is possible to translate the pattern to produce a "new style" -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/lib/ms_fnmatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index c7cf54d26b..238d793b73 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/lib/ms_fnmatch.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 238d793b73..bdfaca143c 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ /* -- cgit From 3aaca8028e09db58381076f199a43680f81f04ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 22:03:41 +0000 Subject: r25170: Remove pstring limits from ms_fnmatch and module load. Jeremy. (This used to be commit 764574ee05ea4f13cdd30c0a0668ffeb81756989) --- source3/lib/ms_fnmatch.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index bdfaca143c..9dc942c5f2 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. filename matching routine Copyright (C) Andrew Tridgell 1992-2004 @@ -7,21 +7,21 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 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, see . + along with this program. If not, see . */ /* This module was originally based on fnmatch.c copyright by the Free Software Foundation. It bears little (if any) resemblence to that code now -*/ +*/ #include "includes.h" @@ -53,7 +53,7 @@ struct max_n { an optimisation only. The ldot pointer is NULL if the string does not contain a '.', otherwise it points at the last dot in 'n'. */ -static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, +static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, struct max_n *max_n, const smb_ucs2_t *ldot, BOOL is_case_sensitive) { @@ -137,22 +137,23 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, break; } } - + if (! *n) { return 0; } - + return -1; } int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern, BOOL is_case_sensitive) { - wpstring p, s; + smb_ucs2_t *p = NULL; + smb_ucs2_t *s = NULL; int ret, count, i; struct max_n *max_n = NULL; - if (strcmp(string, "..") == 0) { + if (ISDOTDOT(string)) { string = "."; } @@ -166,15 +167,12 @@ int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern, } } - if (push_ucs2(NULL, p, pattern, sizeof(p), STR_TERMINATE) == (size_t)-1) { - /* Not quite the right answer, but finding the right one - under this failure case is expensive, and it's pretty close */ + if (push_ucs2_allocate(&p, pattern) == (size_t)-1) { return -1; } - if (push_ucs2(NULL, s, string, sizeof(s), STR_TERMINATE) == (size_t)-1) { - /* Not quite the right answer, but finding the right one - under this failure case is expensive, and it's pretty close */ + if (push_ucs2_allocate(&s, string) == (size_t)-1) { + SAFE_FREE(p); return -1; } @@ -187,8 +185,8 @@ int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern, for (i=0;p[i];i++) { if (p[i] == UCS2_CHAR('?')) { p[i] = UCS2_CHAR('>'); - } else if (p[i] == UCS2_CHAR('.') && - (p[i+1] == UCS2_CHAR('?') || + } else if (p[i] == UCS2_CHAR('.') && + (p[i+1] == UCS2_CHAR('?') || p[i+1] == UCS2_CHAR('*') || p[i+1] == 0)) { p[i] = UCS2_CHAR('"'); @@ -205,16 +203,17 @@ int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern, if (count != 0) { max_n = SMB_CALLOC_ARRAY(struct max_n, count); if (!max_n) { + SAFE_FREE(p); + SAFE_FREE(s); return -1; } } ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.')), is_case_sensitive); - if (max_n) { - free(max_n); - } - + SAFE_FREE(max_n); + SAFE_FREE(p); + SAFE_FREE(s); return ret; } -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/lib/ms_fnmatch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 9dc942c5f2..a839b42588 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -55,7 +55,7 @@ struct max_n { */ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, struct max_n *max_n, const smb_ucs2_t *ldot, - BOOL is_case_sensitive) + bool is_case_sensitive) { smb_ucs2_t c; int i; @@ -145,8 +145,8 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, return -1; } -int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern, - BOOL is_case_sensitive) +int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, + bool is_case_sensitive) { smb_ucs2_t *p = NULL; smb_ucs2_t *s = NULL; -- cgit From 148f1eee4338bbe485f9b9bcf9569f76f906b665 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 8 Jan 2008 23:18:03 +0100 Subject: Save one popular malloc (This used to be commit 2150663d9eaf5cdab08de2ad1fcc952d7e85936c) --- source3/lib/ms_fnmatch.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index a839b42588..8b69f1c2d2 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -152,6 +152,8 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, smb_ucs2_t *s = NULL; int ret, count, i; struct max_n *max_n = NULL; + struct max_n *max_n_free = NULL; + struct max_n one_max_n; if (ISDOTDOT(string)) { string = "."; @@ -201,17 +203,27 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, } if (count != 0) { - max_n = SMB_CALLOC_ARRAY(struct max_n, count); - if (!max_n) { - SAFE_FREE(p); - SAFE_FREE(s); - return -1; + if (count == 1) { + /* + * We're doing this a LOT, so save the effort to allocate + */ + ZERO_STRUCT(one_max_n); + max_n = &one_max_n; + } + else { + max_n = SMB_CALLOC_ARRAY(struct max_n, count); + if (!max_n) { + SAFE_FREE(p); + SAFE_FREE(s); + return -1; + } + max_n_free = max_n; } } ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.')), is_case_sensitive); - SAFE_FREE(max_n); + SAFE_FREE(max_n_free); SAFE_FREE(p); SAFE_FREE(s); return ret; -- cgit From fb37f156009611af0dd454a0fb0829a09cd638ac Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Tue, 29 Apr 2008 14:36:24 -0700 Subject: Cleanup size_t return values in callers of convert_string_allocate This patch is the second iteration of an inside-out conversion to cleanup functions in charcnv.c returning size_t == -1 to indicate failure. (This used to be commit 6b189dabc562d86dcaa685419d0cb6ea276f100d) --- source3/lib/ms_fnmatch.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/lib/ms_fnmatch.c') diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 8b69f1c2d2..ca534467fa 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -154,6 +154,7 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, struct max_n *max_n = NULL; struct max_n *max_n_free = NULL; struct max_n one_max_n; + size_t converted_size; if (ISDOTDOT(string)) { string = "."; @@ -169,11 +170,11 @@ int ms_fnmatch(const char *pattern, const char *string, bool translate_pattern, } } - if (push_ucs2_allocate(&p, pattern) == (size_t)-1) { + if (!push_ucs2_allocate(&p, pattern, &converted_size)) { return -1; } - if (push_ucs2_allocate(&s, string) == (size_t)-1) { + if (!push_ucs2_allocate(&s, string, &converted_size)) { SAFE_FREE(p); return -1; } -- cgit