From dfc517b05395d925a4d7b1ce9633a849f9468e70 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 23 Feb 2006 15:52:24 +0000 Subject: r13658: More moving around of files: - Collect the generic utility functions into a lib/util/ (a la GLib is for the GNOME folks) - Remove even more files from include/ (This used to be commit ba62880f5b05c2a505dc7f54676b231197a7e707) --- source4/lib/util/ms_fnmatch.c | 219 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 source4/lib/util/ms_fnmatch.c (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c new file mode 100644 index 0000000000..699341bede --- /dev/null +++ b/source4/lib/util/ms_fnmatch.c @@ -0,0 +1,219 @@ +/* + Unix SMB/CIFS implementation. + filename matching routine + 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 + 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 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" + +static int null_match(const char *p) +{ + for (;*p;p++) { + if (*p != '*' && + *p != '<' && + *p != '"' && + *p != '>') 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 char *predot; + const char *postdot; +}; + + +/* + 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 char *p, const char *n, + struct max_n *max_n, const char *ldot) +{ + codepoint_t c, c2; + int i; + size_t size, size_n; + + while ((c = next_codepoint(p, &size))) { + p += size; + + switch (c) { + case '*': + /* a '*' matches zero or more characters of any type */ + if (max_n->predot && max_n->predot <= n) { + return null_match(p); + } + for (i=0; n[i]; i += size_n) { + next_codepoint(n+i, &size_n); + 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); + + case '<': + /* a '<' matches zero or more characters of + any type, but stops matching at the last + '.' in the string. */ + 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 += size_n) { + next_codepoint(n+i, &size_n); + 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+size_n, 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); + + case '?': + /* a '?' matches any single character */ + if (! *n) { + return -1; + } + next_codepoint(n, &size_n); + n += size_n; + break; + + case '>': + /* a '?' matches any single character, but + treats '.' specially */ + if (n[0] == '.') { + if (! n[1] && null_match(p) == 0) { + return 0; + } + break; + } + if (! *n) return null_match(p); + next_codepoint(n, &size_n); + n += size_n; + break; + + case '"': + /* a bit like a soft '.' */ + if (*n == 0 && null_match(p) == 0) { + return 0; + } + if (*n != '.') return -1; + next_codepoint(n, &size_n); + n += size_n; + break; + + default: + c2 = next_codepoint(n, &size_n); + if (c != c2 && codepoint_cmpi(c, c2) != 0) { + return -1; + } + n += size_n; + break; + } + } + + if (! *n) { + return 0; + } + + return -1; +} + +int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) +{ + int ret, count, i; + struct max_n *max_n = NULL; + + if (strcmp(string, "..") == 0) { + string = "."; + } + + if (strpbrk(pattern, "<>*?\"") == NULL) { + /* this is not just an optmisation - it is essential + for LANMAN1 correctness */ + return strcasecmp_m(pattern, string); + } + + if (protocol <= PROTOCOL_LANMAN2) { + char *p = talloc_strdup(NULL, pattern); + if (p == NULL) { + return -1; + } + /* + 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] == '?') { + p[i] = '>'; + } else if (p[i] == '.' && + (p[i+1] == '?' || + p[i+1] == '*' || + p[i+1] == 0)) { + p[i] = '"'; + } else if (p[i] == '*' && + p[i+1] == '.') { + p[i] = '<'; + } + } + ret = ms_fnmatch(p, string, PROTOCOL_NT1); + talloc_free(p); + return ret; + } + + for (count=i=0;pattern[i];i++) { + if (pattern[i] == '*' || pattern[i] == '<') count++; + } + + max_n = talloc_array(NULL, struct max_n, count); + if (!max_n) { + return -1; + } + memset(max_n, 0, sizeof(struct max_n) * count); + + ret = ms_fnmatch_core(pattern, string, max_n, strrchr(string, '.')); + + talloc_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); +} -- cgit From 57a55df196aa12529546c6f2ccc893fe68b32f2a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 23 Feb 2006 20:56:10 +0000 Subject: r13662: Typo fix, add more public headers (This used to be commit d98948716f237c3a501b283a0bbc3837bb3fd3c8) --- source4/lib/util/ms_fnmatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index 699341bede..d44c8b87da 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/ms_fnmatch.c @@ -161,7 +161,7 @@ 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 + /* this is not just an optimisation - it is essential for LANMAN1 correctness */ return strcasecmp_m(pattern, string); } -- cgit From aa04388943fe5d7d8c873a6ee8a4cc9af2491532 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 28 Feb 2006 13:12:39 +0000 Subject: r13752: Add doxyfile and fix formatting of comments. Current output is available at http://samba.org/~jelmer/util-api/ (This used to be commit 90812203df151a5e62394306827c72adfe13c63c) --- source4/lib/util/ms_fnmatch.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index d44c8b87da..a4fca4fa0a 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/ms_fnmatch.c @@ -24,6 +24,10 @@ code now */ +/** + * @file + * @brief MS-style Filename matching + */ #include "includes.h" @@ -212,7 +216,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot } -/* a generic fnmatch function - uses for non-CIFS pattern matching */ +/** 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 0479a2f1cbae51fcd8dbdc3c148c808421fb4d25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 02:07:03 +0000 Subject: r23792: convert Samba4 to GPLv3 There are still a few tidyups of old FSF addresses to come (in both s3 and s4). More commits soon. (This used to be commit fcf38a38ac691abd0fa51b89dc951a08e89fdafa) --- source4/lib/util/ms_fnmatch.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index a4fca4fa0a..8e216b0226 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/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, @@ -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 7e297ecfa4db2c7ab720a63c7764bc0e20f8058c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 9 Sep 2007 19:34:30 +0000 Subject: r25047: Fix more warnings. (This used to be commit 69de86d2d2e49439760fbc61901eb87fb7fc5d55) --- source4/lib/util/ms_fnmatch.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index 8e216b0226..73fb0e0966 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/ms_fnmatch.c @@ -201,11 +201,10 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot if (pattern[i] == '*' || pattern[i] == '<') count++; } - max_n = talloc_array(NULL, struct max_n, count); - if (!max_n) { + max_n = talloc_zero_array(NULL, struct max_n, count); + if (max_n == NULL) { return -1; } - memset(max_n, 0, sizeof(struct max_n) * count); ret = ms_fnmatch_core(pattern, string, max_n, strrchr(string, '.')); -- cgit From 39ee38d9c1aabf4db065b433d067d0da053d7d61 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 6 Dec 2007 17:52:23 +0100 Subject: r26316: Use contexts for conversion functions. (This used to be commit f6420d933b5b011d428974f3a2a57edf19e6f482) --- source4/lib/util/ms_fnmatch.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index 73fb0e0966..e1bf6f94c5 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/ms_fnmatch.c @@ -64,7 +64,7 @@ static int ms_fnmatch_core(const char *p, const char *n, int i; size_t size, size_n; - while ((c = next_codepoint(p, &size))) { + while ((c = next_codepoint(global_smb_iconv_convenience, p, &size))) { p += size; switch (c) { @@ -74,7 +74,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return null_match(p); } for (i=0; n[i]; i += size_n) { - next_codepoint(n+i, &size_n); + next_codepoint(global_smb_iconv_convenience, n+i, &size_n); if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { return 0; } @@ -93,7 +93,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return -1; } for (i=0; n[i]; i += size_n) { - next_codepoint(n+i, &size_n); + next_codepoint(global_smb_iconv_convenience, n+i, &size_n); 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+size_n, max_n+1, ldot) == 0) return 0; @@ -109,7 +109,7 @@ static int ms_fnmatch_core(const char *p, const char *n, if (! *n) { return -1; } - next_codepoint(n, &size_n); + next_codepoint(global_smb_iconv_convenience, n, &size_n); n += size_n; break; @@ -123,7 +123,7 @@ static int ms_fnmatch_core(const char *p, const char *n, break; } if (! *n) return null_match(p); - next_codepoint(n, &size_n); + next_codepoint(global_smb_iconv_convenience, n, &size_n); n += size_n; break; @@ -133,12 +133,12 @@ static int ms_fnmatch_core(const char *p, const char *n, return 0; } if (*n != '.') return -1; - next_codepoint(n, &size_n); + next_codepoint(global_smb_iconv_convenience, n, &size_n); n += size_n; break; default: - c2 = next_codepoint(n, &size_n); + c2 = next_codepoint(global_smb_iconv_convenience, n, &size_n); if (c != c2 && codepoint_cmpi(c, c2) != 0) { return -1; } -- cgit From d891c0c74a03d797aed1c5ac0329fd9d1d78da63 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 13 Dec 2007 22:46:09 +0100 Subject: r26429: Avoid use of global_smb_iconv_convenience. (This used to be commit d37136b7abfbba75ef2e5ab855eb3382b9648b8c) --- source4/lib/util/ms_fnmatch.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index e1bf6f94c5..1fb57b07a4 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/ms_fnmatch.c @@ -29,6 +29,7 @@ */ #include "includes.h" +#include "param/param.h" static int null_match(const char *p) { @@ -64,7 +65,7 @@ static int ms_fnmatch_core(const char *p, const char *n, int i; size_t size, size_n; - while ((c = next_codepoint(global_smb_iconv_convenience, p, &size))) { + while ((c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &size))) { p += size; switch (c) { @@ -74,7 +75,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return null_match(p); } for (i=0; n[i]; i += size_n) { - next_codepoint(global_smb_iconv_convenience, n+i, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n+i, &size_n); if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { return 0; } @@ -93,7 +94,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return -1; } for (i=0; n[i]; i += size_n) { - next_codepoint(global_smb_iconv_convenience, n+i, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n+i, &size_n); 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+size_n, max_n+1, ldot) == 0) return 0; @@ -109,7 +110,7 @@ static int ms_fnmatch_core(const char *p, const char *n, if (! *n) { return -1; } - next_codepoint(global_smb_iconv_convenience, n, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); n += size_n; break; @@ -123,7 +124,7 @@ static int ms_fnmatch_core(const char *p, const char *n, break; } if (! *n) return null_match(p); - next_codepoint(global_smb_iconv_convenience, n, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); n += size_n; break; @@ -133,12 +134,12 @@ static int ms_fnmatch_core(const char *p, const char *n, return 0; } if (*n != '.') return -1; - next_codepoint(global_smb_iconv_convenience, n, &size_n); + next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); n += size_n; break; default: - c2 = next_codepoint(global_smb_iconv_convenience, n, &size_n); + c2 = next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); if (c != c2 && codepoint_cmpi(c, c2) != 0) { return -1; } -- cgit From ede79ae482b16c3cea65d3019bc1a68f07354e89 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 21 Feb 2008 15:38:35 +0100 Subject: Remove more uses of global_loadparm. (This used to be commit 58a5b1de2b093fe642eb11d76d12db0edf60c25c) --- source4/lib/util/ms_fnmatch.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'source4/lib/util/ms_fnmatch.c') diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c index 1fb57b07a4..5e04ec1f4b 100644 --- a/source4/lib/util/ms_fnmatch.c +++ b/source4/lib/util/ms_fnmatch.c @@ -64,8 +64,9 @@ static int ms_fnmatch_core(const char *p, const char *n, codepoint_t c, c2; int i; size_t size, size_n; + struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(global_loadparm); - while ((c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &size))) { + while ((c = next_codepoint(iconv_convenience, p, &size))) { p += size; switch (c) { @@ -75,7 +76,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return null_match(p); } for (i=0; n[i]; i += size_n) { - next_codepoint(lp_iconv_convenience(global_loadparm), n+i, &size_n); + next_codepoint(iconv_convenience, n+i, &size_n); if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { return 0; } @@ -94,7 +95,7 @@ static int ms_fnmatch_core(const char *p, const char *n, return -1; } for (i=0; n[i]; i += size_n) { - next_codepoint(lp_iconv_convenience(global_loadparm), n+i, &size_n); + next_codepoint(iconv_convenience, n+i, &size_n); 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+size_n, max_n+1, ldot) == 0) return 0; @@ -110,7 +111,7 @@ static int ms_fnmatch_core(const char *p, const char *n, if (! *n) { return -1; } - next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); + next_codepoint(iconv_convenience, n, &size_n); n += size_n; break; @@ -124,7 +125,7 @@ static int ms_fnmatch_core(const char *p, const char *n, break; } if (! *n) return null_match(p); - next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); + next_codepoint(iconv_convenience, n, &size_n); n += size_n; break; @@ -134,12 +135,12 @@ static int ms_fnmatch_core(const char *p, const char *n, return 0; } if (*n != '.') return -1; - next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); + next_codepoint(iconv_convenience, n, &size_n); n += size_n; break; default: - c2 = next_codepoint(lp_iconv_convenience(global_loadparm), n, &size_n); + c2 = next_codepoint(iconv_convenience, n, &size_n); if (c != c2 && codepoint_cmpi(c, c2) != 0) { return -1; } -- cgit