diff options
author | Andrew Tridgell <tridge@samba.org> | 2000-04-30 11:04:28 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2000-04-30 11:04:28 +0000 |
commit | 700f72453ed8dfd356a5591b9447127b5066ac4b (patch) | |
tree | 46a30958a2f160cf389a9309355c3ebc39c584fd /source3/lib/util.c | |
parent | 71e7974f3f847759ba6f844ea7f482786cc5db02 (diff) | |
download | samba-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.c | 657 |
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)(); |