summaryrefslogtreecommitdiff
path: root/source3/lib/util.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-04-30 11:04:28 +0000
committerAndrew Tridgell <tridge@samba.org>2000-04-30 11:04:28 +0000
commit700f72453ed8dfd356a5591b9447127b5066ac4b (patch)
tree46a30958a2f160cf389a9309355c3ebc39c584fd /source3/lib/util.c
parent71e7974f3f847759ba6f844ea7f482786cc5db02 (diff)
downloadsamba-700f72453ed8dfd356a5591b9447127b5066ac4b.tar.gz
samba-700f72453ed8dfd356a5591b9447127b5066ac4b.tar.bz2
samba-700f72453ed8dfd356a5591b9447127b5066ac4b.zip
- removed all our old wildcard matching code and replaced it with a
call to ms_fnmatch(). This also removes all the Win9X semantics stuff and a bunch of other associated cruft. - moved the stat cache code into statcache.c - fixed the uint16 alignment requirements of ascii_to_unistr() and unistr_to_ascii() - trans2 SMB_FIND_FILE_BOTH_DIRECTORY_INFO returns the short name as unicode always (at least thats what NT4 does) - fixed some errors in the in-memory tdb code. Still ugly, but doesn't crash as much (This used to be commit 03e9cea004bbba72161a5323cf3b4556c94aed8e)
Diffstat (limited to 'source3/lib/util.c')
-rw-r--r--source3/lib/util.c657
1 files changed, 53 insertions, 604 deletions
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 7d9f6a5a50..955e1df080 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -90,9 +90,6 @@ pstring global_myname = "";
fstring global_myworkgroup = "";
char **my_netbios_names;
-static char *filename_dos(char *path,char *buf);
-
-
/****************************************************************************
find a suitable temporary directory. The result should be copied immediately
@@ -543,85 +540,6 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
#endif
}
-/****************************************************************************
-expand some *s
-****************************************************************************/
-static void expand_one(char *Mask,int len)
-{
- char *p1;
- while ((p1 = strchr(Mask,'*')) != NULL)
- {
- int lfill = (len+1) - strlen(Mask);
- int l1= (p1 - Mask);
- pstring tmp;
- pstrcpy(tmp,Mask);
- memset(tmp+l1,'?',lfill);
- pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
- pstrcpy(Mask,tmp);
- }
-}
-
-/****************************************************************************
-expand a wildcard expression, replacing *s with ?s
-****************************************************************************/
-void expand_mask(char *Mask,BOOL doext)
-{
- pstring mbeg,mext;
- pstring dirpart;
- pstring filepart;
- BOOL hasdot = False;
- char *p1;
- BOOL absolute = (*Mask == '\\');
-
- *mbeg = *mext = *dirpart = *filepart = 0;
-
- /* parse the directory and filename */
- if (strchr(Mask,'\\'))
- split_at_last_component(Mask,dirpart,'\\',NULL);
-
- filename_dos(Mask,filepart);
-
- pstrcpy(mbeg,filepart);
- if ((p1 = strchr(mbeg,'.')) != NULL)
- {
- hasdot = True;
- *p1 = 0;
- p1++;
- pstrcpy(mext,p1);
- }
- else
- {
- pstrcpy(mext,"");
- if (strlen(mbeg) > 8)
- {
- pstrcpy(mext,mbeg + 8);
- mbeg[8] = 0;
- }
- }
-
- if (*mbeg == 0)
- pstrcpy(mbeg,"????????");
- if ((*mext == 0) && doext && !hasdot)
- pstrcpy(mext,"???");
-
- if (strequal(mbeg,"*") && *mext==0)
- pstrcpy(mext,"*");
-
- /* expand *'s */
- expand_one(mbeg,8);
- if (*mext)
- expand_one(mext,3);
-
- pstrcpy(Mask,dirpart);
- if (*dirpart || absolute) pstrcat(Mask,"\\");
- pstrcat(Mask,mbeg);
- pstrcat(Mask,".");
- pstrcat(Mask,mext);
-
- DEBUG(6,("Mask expanded to [%s]\n",Mask));
-}
-
-
/****************************************************************************
make a dir struct
@@ -818,502 +736,6 @@ void msleep(int t)
}
-/*********************************************************
-* Recursive routine that is called by unix_mask_match.
-* Does the actual matching. This is the 'original code'
-* used by the unix matcher.
-*********************************************************/
-
-BOOL unix_do_match(char *str, char *regexp, BOOL case_sig)
-{
- char *p;
-
- for( p = regexp; *p && *str; ) {
- switch(*p) {
- case '?':
- str++; p++;
- break;
-
- case '*':
- /*
- * Look for a character matching
- * the one after the '*'.
- */
- p++;
- if(!*p)
- return True; /* Automatic match */
- while(*str) {
-
- while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
- str++;
-
- /*
- * Patch from weidel@multichart.de. In the case of the regexp
- * '*XX*' we want to ensure there are at least 2 'X' characters
- * in the filename after the '*' for a match to be made.
- */
-
- {
- int matchcount=0;
-
- /*
- * Eat all the characters that match, but count how many there were.
- */
-
- while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
- str++;
- matchcount++;
- }
-
- /*
- * Now check that if the regexp had n identical characters that
- * matchcount had at least that many matches.
- */
-
- while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
- p++;
- matchcount--;
- }
- if ( matchcount <= 0 ) {
- return False;
- }
- }
- str--; /* We've eaten the match char after the '*' */
- if(unix_do_match(str,p,case_sig))
- return True;
- if(!*str)
- return False;
- else
- str++;
- }
- return False;
-
- default:
- if(case_sig) {
- if(*str != *p)
- return False;
- } else {
- if(toupper(*str) != toupper(*p))
- return False;
- }
- str++, p++;
- break;
- }
- }
-
- if(!*p && !*str)
- return True;
-
- if (!*p && str[0] == '.' && str[1] == 0)
- return(True);
-
- if (!*str && *p == '?')
- {
- while (*p == '?') p++;
- return(!*p);
- }
-
- if(!*str && (*p == '*' && p[1] == '\0'))
- return True;
- return False;
-}
-
-
-/*********************************************************
-* Routine to match a given string with a regexp - uses
-* simplified regexp that takes * and ? only. Case can be
-* significant or not.
-* This is the 'original code' used by the unix matcher.
-*********************************************************/
-
-static BOOL unix_mask_match(char *str, char *regexp, BOOL case_sig)
-{
- char *p;
- pstring p1, p2;
- fstring ebase,sbase;
- BOOL matched;
-
- /* Make local copies of str and regexp */
- StrnCpy(p1,regexp,sizeof(pstring)-1);
- StrnCpy(p2,str,sizeof(pstring)-1);
-
- /* Remove any *? and ** as they are meaningless */
- for(p = p1; *p; p++)
- while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
- (void)pstrcpy( &p[1], &p[2]);
-
- if (strequal(p1,"*")) return(True);
-
- DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
-
- fstrcpy(ebase,p1);
- fstrcpy(sbase,p2);
-
- matched = unix_do_match(sbase,ebase,case_sig);
-
- DEBUG(8,("unix_mask_match returning %d\n", matched));
-
- return matched;
-}
-
-/*********************************************************
-* Recursive routine that is called by mask_match.
-* Does the actual matching. Returns True if matched,
-* False if failed. This is the 'new' NT style matcher.
-* The win9x_semantics parameter is needed as Win9x matching
-* is *actually different*. In Win9x, trailing '?' characters
-* will only match the *exact* number of characters. Under
-* DOS and NT they match any number. This makes no
-* sense.....
-*********************************************************/
-
-static BOOL do_match(char *str, char *regexp, int case_sig, BOOL win9x_semantics)
-{
- char *p;
-
- for( p = regexp; *p && *str; ) {
- switch(*p) {
- case '?':
- str++; p++;
- break;
-
- case '*':
- /* Look for a character matching
- the one after the '*' */
- p++;
- if(!*p)
- return True; /* Automatic match */
- while(*str) {
- while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
- str++;
-
- /*
- * Patch from weidel@multichart.de. In the case of the regexp
- * '*XX*' we want to ensure there are at least 2 'X' characters
- * in the filename after the '*' for a match to be made.
- */
-
- {
- int matchcount=0;
-
- /*
- * Eat all the characters that match, but count how many there were.
- */
-
- while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
- str++;
- matchcount++;
- }
-
- /*
- * Now check that if the regexp had n identical characters that
- * matchcount had at least that many matches.
- */
-
- while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
- p++;
- matchcount--;
- }
- if ( matchcount <= 0 ) {
- return False;
- }
- }
- str--; /* We've eaten the match char after the '*' */
- if(do_match(str,p,case_sig,win9x_semantics)) {
- return True;
- }
- if(!*str) {
- return False;
- } else {
- str++;
- }
- }
- return False;
-
- default:
- if(case_sig) {
- if(*str != *p) {
- return False;
- }
- } else {
- if(toupper(*str) != toupper(*p)) {
- return False;
- }
- }
- str++, p++;
- break;
- }
- }
-
- if(!*p && !*str)
- return True;
-
- if (!*p && str[0] == '.' && str[1] == 0) {
- return(True);
- }
-
- if (!win9x_semantics) {
- if (!*str && *p == '?') {
- while (*p == '?')
- p++;
- return(!*p);
- }
- }
-
- if(!*str && (*p == '*' && p[1] == '\0')) {
- return True;
- }
-
- return False;
-}
-
-/*********************************************************
-* Routine to match a given string with a regexp - uses
-* simplified regexp that takes * and ? only. Case can be
-* significant or not.
-* The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
-* This is the new 'NT style' matcher.
-*********************************************************/
-
-BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
-{
- char *p;
- pstring t_pattern, t_filename, te_pattern, te_filename;
- fstring ebase,eext,sbase,sext;
- BOOL matched = False;
- BOOL win9x_semantics = (get_remote_arch() == RA_WIN95) && trans2;
-
- /* special case - if it is exactly the same then it always matches! */
- if(exact_match(str, regexp, case_sig))
- return True;
-
- /* Make local copies of str and regexp */
- pstrcpy(t_pattern,regexp);
- pstrcpy(t_filename,str);
-
- if(trans2) {
-
- /* a special case for 16 bit apps */
- if (strequal(t_pattern,"????????.???"))
- pstrcpy(t_pattern,"*");
-
-#if 0
- /*
- * Handle broken clients that send us old 8.3 format.
- */
- pstring_sub(t_pattern,"????????","*");
- pstring_sub(t_pattern,".???",".*");
-#endif
- }
-
-#if 0
- /*
- * Not sure if this is a good idea. JRA.
- */
- if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
- trans2 = False;
-#endif
-
-#if 0
- if (!strchr(t_filename,'.')) {
- pstrcat(t_filename,".");
- }
-#endif
-
- /* Remove any *? and ** as they are meaningless */
- for(p = t_pattern; *p; p++)
- while( *p == '*' && (p[1] == '?' || p[1] == '*'))
- (void)pstrcpy( &p[1], &p[2]);
-
- if (strequal(t_pattern,"*"))
- return(True);
-
- DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
-
- if(trans2) {
- /*
- * Match each component of the regexp, split up by '.'
- * characters.
- */
- char *fp, *rp, *cp2, *cp1;
- BOOL last_wcard_was_star = False;
- int num_path_components, num_regexp_components;
-
- pstrcpy(te_pattern,t_pattern);
- pstrcpy(te_filename,t_filename);
- /*
- * Remove multiple "*." patterns.
- */
- pstring_sub(te_pattern, "*.*.", "*.");
- num_regexp_components = count_chars(te_pattern, '.');
- num_path_components = count_chars(te_filename, '.');
-
- /*
- * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
- */
- if(num_regexp_components == 0)
- matched = do_match( te_filename, te_pattern, case_sig, win9x_semantics);
- else {
- for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
- fp = strchr(cp2, '.');
- if(fp)
- *fp = '\0';
- rp = strchr(cp1, '.');
- if(rp)
- *rp = '\0';
-
- if(cp1[0] && cp1[strlen(cp1)-1] == '*')
- last_wcard_was_star = True;
- else
- last_wcard_was_star = False;
-
- if(!do_match(cp2, cp1, case_sig, win9x_semantics))
- break;
-
- /*
- * Ugly ! Special case for Win9x *only*. If filename is XXXX and pattern extension
- * is '*' or all '?' then disallow match.
- */
-
- if (win9x_semantics) {
- if (*cp2 == '\0' && str_is_all(cp1, '?'))
- break;
- }
-
- cp1 = rp ? rp + 1 : NULL;
- cp2 = fp ? fp + 1 : "";
-
- if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
- /* Eat the extra path components. */
- int i;
-
- for(i = 0; i < num_path_components - num_regexp_components; i++) {
- fp = strchr(cp2, '.');
- if(fp)
- *fp = '\0';
-
- if((cp1 != NULL) && do_match( cp2, cp1, case_sig, win9x_semantics)) {
- cp2 = fp ? fp + 1 : "";
- break;
- }
- cp2 = fp ? fp + 1 : "";
- }
- num_path_components -= i;
- }
- }
- if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
- matched = True;
- }
- } else {
-
- /* -------------------------------------------------
- * Behaviour of Win95
- * for 8.3 filenames and 8.3 Wildcards
- * -------------------------------------------------
- */
- if (strequal (t_filename, ".")) {
- /*
- * Patterns: *.* *. ?. ? ????????.??? are valid.
- *
- */
- if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
- strequal(t_pattern, "????????.???") ||
- strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
- matched = True;
- } else if (strequal (t_filename, "..")) {
- /*
- * Patterns: *.* *. ?. ? *.? ????????.??? are valid.
- *
- */
- if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
- strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
- strequal(t_pattern, "????????.???") ||
- strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
- matched = True;
- } else {
-
- if ((p = strrchr (t_pattern, '.'))) {
- /*
- * Wildcard has a suffix.
- */
- *p = 0;
- fstrcpy (ebase, t_pattern);
- if (p[1]) {
- fstrcpy (eext, p + 1);
- } else {
- /* pattern ends in DOT: treat as if there is no DOT */
- *eext = 0;
- if (strequal (ebase, "*"))
- return (True);
- }
- } else {
- /*
- * No suffix for wildcard.
- */
- fstrcpy (ebase, t_pattern);
- eext[0] = 0;
- }
-
- p = strrchr (t_filename, '.');
- if (p && (p[1] == 0) ) {
- /*
- * Filename has an extension of '.' only.
- */
- *p = 0; /* nuke dot at end of string */
- p = 0; /* and treat it as if there is no extension */
- }
-
- if (p) {
- /*
- * Filename has an extension.
- */
- *p = 0;
- fstrcpy (sbase, t_filename);
- fstrcpy (sext, p + 1);
- if (*eext) {
- matched = do_match(sbase, ebase, case_sig, False)
- && do_match(sext, eext, case_sig, False);
- } else {
- /* pattern has no extension */
- /* Really: match complete filename with pattern ??? means exactly 3 chars */
- matched = do_match(str, ebase, case_sig, False);
- }
- } else {
- /*
- * Filename has no extension.
- */
- fstrcpy (sbase, t_filename);
- fstrcpy (sext, "");
- if (*eext) {
- /* pattern has extension */
- matched = do_match(sbase, ebase, case_sig, False)
- && do_match(sext, eext, case_sig, False);
-
- } else {
- matched = do_match(sbase, ebase, case_sig, False);
-#ifdef EMULATE_WEIRD_W95_MATCHING
- /*
- * Even Microsoft has some problems
- * Behaviour Win95 -> local disk
- * is different from Win95 -> smb drive from Nt 4.0
- * This branch would reflect the Win95 local disk behaviour
- */
- if (!matched) {
- /* a? matches aa and a in w95 */
- fstrcat (sbase, ".");
- matched = do_match(sbase, ebase, case_sig, False);
- }
-#endif
- }
- }
- }
- }
-
- DEBUG(8,("mask_match returning %d\n", matched));
-
- return matched;
-}
-
/****************************************************************************
become a daemon, discarding the controlling terminal
****************************************************************************/
@@ -1419,24 +841,6 @@ this is a version of setbuffer() for those machines that only have setvbuf
}
#endif
-
-/****************************************************************************
-parse out a filename from a path name. Assumes dos style filenames.
-****************************************************************************/
-static char *filename_dos(char *path,char *buf)
-{
- char *p = strrchr(path,'\\');
-
- if (!p)
- pstrcpy(buf,path);
- else
- pstrcpy(buf,p+1);
-
- return(buf);
-}
-
-
-
/****************************************************************************
expand a pointer to be a particular size
****************************************************************************/
@@ -1961,12 +1365,7 @@ BOOL is_in_path(char *name, name_compare_entry *namelist)
{
if(namelist->is_wild)
{
- /*
- * Look for a wildcard match. Use the old
- * 'unix style' mask match, rather than the
- * new NT one.
- */
- if (unix_mask_match(last_component, namelist->name, case_sensitive))
+ if (mask_match(last_component, namelist->name, case_sensitive))
{
DEBUG(8,("is_in_path: mask match succeeded\n"));
return True;
@@ -2067,8 +1466,7 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
if(name_end == NULL)
break;
- (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
- (strchr( nameptr, '*')!=NULL));
+ (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
{
DEBUG(0,("set_namearray: malloc fail (1)\n"));
@@ -2653,7 +2051,58 @@ char *parent_dirname(const char *path)
}
+/*******************************************************************
+determine if a pattern contains any Microsoft wildcard characters
+ *******************************************************************/
+BOOL ms_has_wild(char *s)
+{
+ char c;
+ while ((c = *s++)) {
+ switch (c) {
+ case '*':
+ case '?':
+ case '<':
+ case '>':
+ case '"':
+ return True;
+ }
+ }
+ return False;
+}
+
+
+/*******************************************************************
+ a wrapper that handles case sensitivity and the special handling
+ of the ".." name
+
+ case_sensitive is a boolean
+ *******************************************************************/
+BOOL mask_match(char *string, char *pattern, BOOL case_sensitive)
+{
+ fstring p2, s2;
+ if (strcmp(string,"..") == 0) string = ".";
+ if (strcmp(pattern,".") == 0) return False;
+
+ if (case_sensitive) {
+ return ms_fnmatch(pattern, string) == 0;
+ }
+
+ fstrcpy(p2, pattern);
+ fstrcpy(s2, string);
+ strlower(p2);
+ strlower(s2);
+ return ms_fnmatch(p2, s2) == 0;
+}
+
+
+
#ifdef __INSURE__
+
+/*******************************************************************
+This routine is a trick to immediately catch errors when debugging
+with insure. A xterm with a gdb is popped up when insure catches
+a error. It is Linux specific.
+********************************************************************/
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
{
static int (*fn)();