[PATCH] Fix Name mangling in HEAD

Simo Sorce idra at samba.org
Mon Mar 25 03:12:11 GMT 2002


On Mon, 2002-03-25 at 11:52, Simo Sorce wrote:
> Sorry Andrew but reverting back to 2.2 code is not the way to go on my
> opinion, I made that code to solve many problems and bugs that apperead
> in 2.2. code. The way to go is that me and tridge discussed on IRC, eg:
> 
> change the code to use a hash instead of numbering as windows (2k at
> least) does after a few similar entries (five).
> eg:
> averylongname[1-10].txt
> 
> windows do this:
> averyl~1.txt
> averyl~2.txt
> averyl~3.txt
> averyl~4.txt
> averyl~5.txt
> aERWF4~1.txt
> aehw64~1.txt
> .
> .

Sorry, my mistake, windows use a little different scheme!
averyl~1.txt
averyl~2.txt
averyl~3.txt
averyl~4.txt
averyl~5.txt
avA4BD~1.txt
avA4FC~1.txt
avF3D6~1.txt
avAB5F~1.txt
avAB54~1.txt

windows use a week 16 bit number as hash and put it as a hex number in
the file name after the first 2 letters of the original name.

> 
> we would do this:
> 
> aRtf6e~9.txt
> aWE456~3.txt
> ...
> 
> the number of letters that will be used will be based on a configurable
> option (1 to 7).
> 
> We need to keep the a tdb as base but make an in meory cache to spead up
> things.
> 
> And above all move everything to VFS and merge in also the case
> sensitivity handling.
> 
> 
> Simo.
> 
> On Mon, 2002-03-25 at 09:41, Andrew Bartlett wrote:
> > Attached is a partial, unfinished (but apparently functional) name
> > mangling patch for HEAD. 
> > This patch reintroduces hash (rather that db/counter) based mangling.
> > 
> > This fixes the issue that samba gets very slow when more than 99 files
> > exist on the server with the same 5 chars in their name.  This
> > particular bug also causes MS word to leave temporay files behind. 
> > 
> > When I get more time, I'll fix this to use more unicode and the
> > mangle_get_prefix() function.
> > 
> > Andrew Bartlett
> > 
> > -- 
> > Andrew Bartlett                                 abartlet at pcug.org.au
> > Manager, Authentication Subsystems, Samba Team  abartlet at samba.org
> > Student Network Administrator, Hawker College   abartlet at hawkerc.net
> > http://samba.org     http://build.samba.org     http://hawkerc.net
> > ----
> > 
> 
> > Index: smbd/filename.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/filename.c,v
> > retrieving revision 1.46
> > diff -u -r1.46 filename.c
> > --- smbd/filename.c	2002/01/30 06:08:38	1.46
> > +++ smbd/filename.c	2002/03/25 08:24:41
> > @@ -75,6 +75,17 @@
> >  ****************************************************************************/
> >  static BOOL mangled_equal(char *name1, char *name2)
> >  {
> > +#if 1
> > +	pstring tmpname;
> > +	if (is_8_3(name2, True)) {
> > +		return False;
> > +	}
> > +	
> > +	pstrcpy(tmpname, name2);
> > +	mangle_name_83(tmpname);
> > +
> > +	return strequal(name1, tmpname);
> > +#else	
> >  	char *tmpname;
> >  	BOOL ret = False;
> >  
> > @@ -86,6 +97,8 @@
> >  		SAFE_FREE(tmpname);
> >  	}
> >  	return ret;
> > +#endif
> > +	
> >  }
> >  
> >  
> > @@ -116,7 +129,7 @@
> >  for nlinks = 0, which can never be true for any file).
> >  ****************************************************************************/
> >  
> > -BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, 
> > +BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component, 
> >                    BOOL *bad_path, SMB_STRUCT_STAT *pst)
> >  {
> >    SMB_STRUCT_STAT st;
> > Index: smbd/mangle.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/mangle.c,v
> > retrieving revision 1.66
> > diff -u -r1.66 mangle.c
> > --- smbd/mangle.c	2002/03/14 22:52:19	1.66
> > +++ smbd/mangle.c	2002/03/25 08:24:43
> > @@ -1,6 +1,7 @@
> >  /* 
> >     Unix SMB/CIFS implementation.
> > -   Name mangling with persistent tdb
> > +   Name mangling
> > +   Copyright (C) Andrew Tridgell 1992-1998
> >     Copyright (C) Simo Sorce 2001
> >     Copyright (C) Andrew Bartlett 2002
> >     
> > @@ -19,9 +20,31 @@
> >     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> >  */
> >  
> > -/****************************************************************************
> > -  Rewritten from scrach in 2001 by Simo Sorce <idra at samba.org>
> > - ****************************************************************************/
> > +/* -------------------------------------------------------------------------- **
> > + * Notable problems...
> > + *
> > + *  March/April 1998  CRH
> > + *  - Many of the functions in this module overwrite string buffers passed to
> > + *    them.  This causes a variety of problems and is, generally speaking,
> > + *    dangerous and scarry.  See the kludge notes in name_map_mangle()
> > + *    below.
> > + *  - It seems that something is calling name_map_mangle() twice.  The
> > + *    first call is probably some sort of test.  Names which contain
> > + *    illegal characters are being doubly mangled.  I'm not sure, but
> > + *    I'm guessing the problem is in server.c.
> > + *
> > + * -------------------------------------------------------------------------- **
> > + */
> > +
> > +/* -------------------------------------------------------------------------- **
> > + * History...
> > + *
> > + *  March/April 1998  CRH
> > + *  Updated a bit.  Rewrote is_mangled() to be a bit more selective.
> > + *  Rewrote the mangled name cache.  Added comments here and there.
> > + *  &c.
> > + * -------------------------------------------------------------------------- **
> > + */
> >  
> >  #include "includes.h"
> >  
> > @@ -33,36 +56,88 @@
> >  extern int case_default;    /* Are conforming 8.3 names all upper or lower?   */
> >  extern BOOL case_mangle;    /* If true, all chars in 8.3 should be same case. */
> >  
> > +/* -------------------------------------------------------------------------- **
> > + * Other stuff...
> > + *
> > + * magic_char     - This is the magic char used for mangling.  It's
> > + *                  global.  There is a call to lp_magicchar() in server.c
> > + *                  that is used to override the initial value.
> > + *
> > + * MANGLE_BASE    - This is the number of characters we use for name mangling.
> > + *
> > + * basechars      - The set characters used for name mangling.  This
> > + *                  is static (scope is this file only).
> > + *
> > + * mangle()       - Macro used to select a character from basechars (i.e.,
> > + *                  mangle(n) will return the nth digit, modulo MANGLE_BASE).
> > + *
> > + * chartest       - array 0..255.  The index range is the set of all possible
> > + *                  values of a byte.  For each byte value, the content is a
> > + *                  two nibble pair.  See BASECHAR_MASK and ILLEGAL_MASK,
> > + *                  below.
> > + *
> > + * ct_initialized - False until the chartest array has been initialized via
> > + *                  a call to init_chartest().
> > + *
> > + * BASECHAR_MASK  - Masks the upper nibble of a one-byte value.
> > + *
> > + * ILLEGAL_MASK   - Masks the lower nibble of a one-byte value.
> > + *
> > + * isbasecahr()   - Given a character, check the chartest array to see
> > + *                  if that character is in the basechars set.  This is
> > + *                  faster than using strchr_m().
> > + *
> > + * isillegal()    - Given a character, check the chartest array to see
> > + *                  if that character is in the illegal characters set.
> > + *                  This is faster than using strchr_m().
> > + *
> > + * mangled_cache  - Cache header used for storing mangled -> original
> > + *                  reverse maps.
> > + *
> > + * mc_initialized - False until the mangled_cache structure has been
> > + *                  initialized via a call to reset_mangled_cache().
> > + *
> > + * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the
> > + *                  cache.  A value of 0 indicates "infinite".
> > + *
> > + * MANGLED_CACHE_MAX_MEMORY  - Default maximum amount of memory for the
> > + *                  cache.  When the cache was kept as an array of 256
> > + *                  byte strings, the default cache size was 50 entries.
> > + *                  This required a fixed 12.5Kbytes of memory.  The
> > + *                  mangled stack parameter is no longer used (though
> > + *                  this might change).  We're now using a fixed 16Kbyte
> > + *                  maximum cache size.  This will probably be much more
> > + *                  than 50 entries.
> > + */
> > +
> >  char magic_char = '~';
> >  
> > -/* -------------------------------------------------------------------- */
> > +static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
> > +#define MANGLE_BASE       (sizeof(basechars)/sizeof(char)-1)
> >  
> > -#define MANGLE_TDB_VERSION		"20010927"
> > -#define MANGLE_TDB_FILE_NAME		"mangle.tdb"
> > -#define MANGLED_PREFIX			"MANGLED_"
> > -#define LONG_PREFIX			"LONG_"
> > -#define COUNTER_PREFIX			"COUNTER_"
> > -#define	MANGLE_COUNTER_MAX		99
> > -#define MANGLE_SUFFIX_SIZE		3 /* "~XX" */
> > +static unsigned char chartest[256]  = { 0 };
> > +static BOOL          ct_initialized = False;
> >  
> > +#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
> > +#define BASECHAR_MASK 0xf0
> > +#define ILLEGAL_MASK  0x0f
> > +#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK )
> > +#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK )
> > +
> > +static ubi_cacheRoot mangled_cache[1] =  { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } };
> > +static BOOL          mc_initialized   = False;
> > +#define MANGLED_CACHE_MAX_ENTRIES 0
> > +#define MANGLED_CACHE_MAX_MEMORY  16384
> >  
> > -static TDB_CONTEXT	*mangle_tdb;
> >  
> > -BOOL init_mangle_tdb(void)
> > -{
> > -	char *tdbfile;
> > -	
> > -	tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */
> > +/* -------------------------------------------------------------------------- **
> > + * External Variables...
> > + */
> >  
> > -	/* Open tdb */
> > -	if (!(mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600)))
> > -	{
> > -		DEBUG(0, ("Unable to open Mangle TDB\n"));
> > -		return False;
> > -	}
> > +extern int case_default;    /* Are conforming 8.3 names all upper or lower?   */
> > +extern BOOL case_mangle;    /* If true, all chars in 8.3 should be same case. */
> >  
> > -	return True;
> > -}
> > +/* -------------------------------------------------------------------- */
> >  
> >  /* trasform a unicode string into a dos charset string */
> >  static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len)
> > @@ -81,6 +156,24 @@
> >  	return ret;
> >  }
> >  
> > +NTSTATUS has_valid_chars(const smb_ucs2_t *s)
> > +{
> > +	if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
> > +
> > +	DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */
> > +	
> > +	/* CHECK: this should not be necessary if the ms wild chars
> > +	   are not valid in valid.dat  --- simo */
> > +	if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
> > +
> > +	while (*s) {
> > +		if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
> > +		s++;
> > +	}
> > +
> > +	return NT_STATUS_OK;
> > +}
> > +
> >  /* trasform in a string that contain only valid chars for win filenames,
> >   not including a '.' */
> >  static void strvalid(smb_ucs2_t *src)
> > @@ -128,524 +221,19 @@
> >  	return NT_STATUS_OK;
> >  }
> >  
> > -
> > -/* mangled must contain only the file name, not a path.
> > -   and MUST be ZERO terminated */
> > -smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
> > -{
> > -	TDB_DATA data, key;
> > -	fstring keystr;
> > -	fstring mufname;
> > -	smb_ucs2_t *pref, *ext, *retstr;
> > -	size_t long_len, ext_len, muf_len;
> > -
> > -	if (strlen_w(mangled) > 12) return NULL;
> > -	if (!strchr_w(mangled, UCS2_CHAR('~'))) return NULL;
> > -
> > -	/* if it is a path refuse to proceed */
> > -	if (strchr_w(mangled, UCS2_CHAR('/'))) {
> > -		DEBUG(10, ("unmangle: cannot unmangle a path\n"));
> > -		return NULL;
> > -	}
> > -
> > -	if (NT_STATUS_IS_ERR(mangle_get_prefix(mangled, &pref, &ext)))
> > -		return NULL;
> > -
> > -	/* mangled names are stored lowercase only */	
> > -	strlower_w(pref);
> > -	/* set search key */
> > -	muf_len = ucs2_to_dos(mufname, pref, sizeof(mufname));
> > -	SAFE_FREE(pref);
> > -	if (!muf_len) return NULL;
> > -	
> > -	slprintf(keystr, sizeof(keystr) - 1, "%s%s", MANGLED_PREFIX, mufname);
> > -	key.dptr = keystr;
> > -	key.dsize = strlen (keystr) + 1;
> > -	
> > -	/* get the record */
> > -	data = tdb_fetch(mangle_tdb, key);
> > -	
> > -	if (!data.dptr) /* not found */
> > -	{
> > -		DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(mangle_tdb)));
> > -		retstr = NULL;
> > -		goto done;
> > -	}
> > -
> > -	if (ext)
> > -	{
> > -		long_len = (data.dsize / 2) - 1;
> > -		ext_len = strlen_w(ext);
> > -		retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 2)*sizeof(smb_ucs2_t));
> > -		if (!retstr)
> > -		{
> > -			DEBUG(0, ("unamngle: out of memory!\n"));
> > -			goto done;
> > -		}
> > -		strncpy_w(retstr, (smb_ucs2_t *)data.dptr, long_len);
> > -		retstr[long_len] = UCS2_CHAR('.');
> > -		retstr[long_len + 1] = 0;
> > -		strncat_w(retstr, ext, ext_len);
> > -	}
> > -	else
> > -	{
> > -		retstr = strdup_w((smb_ucs2_t *)data.dptr);
> > -		if (!retstr)
> > -		{
> > -			DEBUG(0, ("unamngle: out of memory!\n"));
> > -			goto done;
> > -		}
> > -
> > -	}
> > -
> > -done:
> > -	SAFE_FREE(data.dptr);
> > -	SAFE_FREE(pref);
> > -	SAFE_FREE(ext);
> > -
> > -	return retstr;
> > -}
> > -
> > -/* unmangled must contain only the file name, not a path.
> > -   and MUST be ZERO terminated.
> > -   return a new allocated string if the name is yet valid 8.3
> > -   or is mangled successfully.
> > -   return null on error.
> > +/* ************************************************************************** **
> > + * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name.
> > + *
> > + *  Input:  fname - String containing the name to be tested.
> > + *
> > + *  Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names.
> > + *
> > + *  Notes:  This is a static function called by is_8_3(), below.
> > + *
> > + * ************************************************************************** **
> >   */
> > -
> > -smb_ucs2_t *mangle(const smb_ucs2_t *unmangled)
> > -{
> > -	TDB_DATA data, key, klock;
> > -	pstring keystr;
> > -	pstring longname;
> > -	fstring keylock;
> > -	fstring mufname;
> > -	fstring prefix;
> > -	BOOL tclock = False;
> > -	char suffix[7];
> > -	smb_ucs2_t *mangled = NULL;
> > -	smb_ucs2_t *umpref, *ext, *p = NULL;
> > -	size_t pref_len, ext_len, ud83_len;
> > -
> > -	/* if it is a path refuse to proceed */
> > -	if (strchr_w(unmangled, UCS2_CHAR('/'))) {
> > -		DEBUG(10, ("mangle: cannot mangle a path\n"));
> > -		return NULL;
> > -	}
> > -
> > -	/* if it is a valid 8_3 do not mangle again */
> > -	if (NT_STATUS_IS_OK(is_8_3_w(unmangled)))
> > -		return NULL;
> > -
> > -	if (NT_STATUS_IS_ERR(mangle_get_prefix(unmangled, &umpref, &ext)))
> > -		return NULL;
> > -
> > -	/* test if the same is yet mangled */
> > -
> > -	/* set search key */
> > -	pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
> > -	slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
> > -	key.dptr = keystr;
> > -	key.dsize = strlen(keystr) + 1;
> > -
> > -	/* get the record */
> > -	data = tdb_fetch (mangle_tdb, key);
> > -	if (!data.dptr) /* not found */
> > -	{
> > -		smb_ucs2_t temp[9];
> > -		size_t c, pos;
> > -
> > -		if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST)
> > -		{
> > -			DEBUG(0, ("mangle: database retrieval error: %s\n",
> > -					tdb_errorstr(mangle_tdb)));
> > -			goto done;
> > -		}
> > -
> > -		/* if not find the first free possibile mangled name */
> > -
> > -		pos = strlen_w(umpref);
> > -		if ((8 - MANGLE_SUFFIX_SIZE) < pos)
> > -			pos = 8 - MANGLE_SUFFIX_SIZE;
> > -		pos++;
> > -		do
> > -		{
> > -			pos--;
> > -			if (pos == 0)
> > -			{
> > -				char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > -				DEBUG(0, ("mangle: unable to mangle file name (%s)!\n",unmangled_unix));
> > -				SAFE_FREE(unmangled_unix);
> > -				goto done;
> > -			}
> > -			strncpy_w(temp, umpref, pos);
> > -			temp[pos] = 0;
> > -			strlower_w(temp);
> > -
> > -			/* convert any invalid char into '_' */
> > -			strvalid(temp);
> > -			ud83_len = ucs2_to_dos(prefix, temp, sizeof(prefix));
> > -			if (!ud83_len) goto done;
> > -		}
> > -		while (ud83_len > 8 - MANGLE_SUFFIX_SIZE);
> > -
> > -		slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix);
> > -		klock.dptr = keylock;
> > -		klock.dsize = strlen(keylock) + 1;
> > -
> > -		c = 0;
> > -		data.dptr = (char *)&c;
> > -		data.dsize = sizeof(uint32);
> > -		/* try to insert a new counter prefix, if it exist the call will
> > -		   fail (correct) otherwise it will create a new entry with counter set
> > -		   to 0
> > -		 */
> > -		if(tdb_store(mangle_tdb, klock, data, TDB_INSERT) != TDB_SUCCESS)
> > -		{
> > -			if (tdb_error(mangle_tdb) != TDB_ERR_EXISTS)
> > -			{
> > -				char *unmangled_unix = acnv_u2ux(unmangled);
> > -				DEBUG(0, ("mangle: database store error: %s for filename: %s\n",
> > -					tdb_errorstr(mangle_tdb), unmangled_unix));
> > -				SAFE_FREE(unmangled_unix);
> > -				goto done;
> > -			}
> > -		}
> > -
> > -		/* lock the mangle counter for this prefix */		
> > -		if (tdb_chainlock(mangle_tdb, klock))
> > -		{
> > -			char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > -			DEBUG(0,("mangle: failed to lock database for filename %s\n!", unmangled_unix));
> > -			SAFE_FREE(unmangled_unix);
> > -			goto done;
> > -		}
> > -		tclock = True;
> > -
> > -		data = tdb_fetch(mangle_tdb, klock);
> > -		if (!data.dptr)
> > -		{
> > -			char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > -			DEBUG(0, ("mangle: database retrieval error: %s for filename: %s\n",
> > -				  tdb_errorstr(mangle_tdb), unmangled_unix));
> > -			SAFE_FREE(unmangled_unix);
> > -			goto done;
> > -		}
> > -		c = *((uint32 *)data.dptr);
> > -		c++;
> > -		
> > -		if (c > MANGLE_COUNTER_MAX)
> > -		{
> > -			char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > -			DEBUG(0, ("mangle: error, counter overflow (max=%d, counter=%d) for file: [%s] prefix (dos charset): [%s]!\n", MANGLE_COUNTER_MAX, c, unmangled_unix, prefix));
> > -			SAFE_FREE(unmangled_unix);
> > -			goto done;
> > -		}
> > -			
> > -		temp[pos] = UCS2_CHAR('~');
> > -		temp[pos+1] = 0;
> > -		snprintf(suffix, 7, "%.6d", c);
> > -		strncat_wa(temp, &suffix[7 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE);
> > -
> > -		ud83_len = ucs2_to_dos(mufname, temp, sizeof(mufname));
> > -		if (!ud83_len) goto done;
> > -		if (ud83_len > 8)
> > -		{
> > -			char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > -			DEBUG(0, ("mangle: darn, logic error aborting!  Filename was %s\n", unmangled_unix));
> > -			SAFE_FREE(unmangled_unix);
> > -			goto done;
> > -		}
> > -			
> > -		/* store the long entry with mangled key */
> > -		slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
> > -		key.dptr = keystr;
> > -		key.dsize = strlen (keystr) + 1;
> > -		data.dsize = (strlen_w(umpref) + 1) * sizeof (smb_ucs2_t);
> > -		data.dptr = (void *)umpref;
> > -
> > -		if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
> > -		{
> > -			char *unmangled_unix = acnv_u2ux(unmangled);
> > -
> > -			DEBUG(0, ("mangle: database store error: %s for filename: %s\n",
> > -					tdb_errorstr(mangle_tdb), unmangled_unix));
> > -			SAFE_FREE(unmangled_unix);
> > -			goto done;
> > -		}
> > -
> > -		/* store the mangled entry with long key*/
> > -		pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
> > -		slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
> > -		key.dptr = keystr;
> > -		key.dsize = strlen (keystr) + 1;
> > -		data.dsize = strlen(mufname) + 1;
> > -		data.dptr = mufname;
> > -		if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
> > -		{
> > -			char *unmangled_unix = acnv_u2ux(unmangled);
> > -			DEBUG(0, ("mangle: database store failed: %s for filename: %s\n",
> > -					tdb_errorstr(mangle_tdb), unmangled_unix));
> > -			SAFE_FREE(unmangled_unix);
> > -
> > -			/* try to delete the mangled key entry to avoid later inconsistency */
> > -			slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
> > -			key.dptr = keystr;
> > -			key.dsize = strlen (keystr) + 1;
> > -			if (!tdb_delete(mangle_tdb, key))
> > -			{
> > -				DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
> > -			}
> > -			goto done;
> > -		}
> > -
> > -		p = strdup_w(temp);
> > -		if (!p)
> > -		{
> > -			DEBUG(0,("mangle: out of memory!\n"));
> > -			goto done;
> > -		}
> > -		
> > -		data.dptr = (char *)&c;
> > -		data.dsize = sizeof(uint32);
> > -		/* store the counter */
> > -		if(tdb_store(mangle_tdb, klock, data, TDB_REPLACE) != TDB_SUCCESS)
> > -		{
> > -			char *unmangled_unix = acnv_u2ux(unmangled);
> > -			DEBUG(0, ("mangle: database store failed: %s for filename: %s\n", 
> > -					tdb_errorstr(mangle_tdb), unmangled_unix));
> > -			SAFE_FREE(unmangled_unix);
> > -			/* try to delete the mangled and long key entry to avoid later inconsistency */
> > -			slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
> > -			key.dptr = keystr;
> > -			key.dsize = strlen (keystr) + 1;
> > -			if (!tdb_delete(mangle_tdb, key))
> > -			{
> > -				DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
> > -			}
> > -			slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
> > -			key.dptr = keystr;
> > -			key.dsize = strlen (keystr) + 1;
> > -			if (!tdb_delete(mangle_tdb, key))
> > -			{
> > -				DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
> > -			}
> > -			goto done;
> > -		}
> > -
> > -		tclock = False;
> > -		tdb_chainunlock(mangle_tdb, klock);
> > -	}
> > -	else /* FOUND */
> > -	{
> > -		p = acnv_dosu2(data.dptr);
> > -		if (!p)
> > -		{
> > -			DEBUG(0,("mangle: internal error acnv_dosu2() failed!\n"));
> > -			goto done;
> > -		}
> > -	}
> > -		
> > -	if (ext)
> > -	{
> > -		pref_len = strlen_w(p);
> > -		ext_len = strlen_w(ext);
> > -		mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 2)*sizeof(smb_ucs2_t));
> > -		if (!mangled)
> > -		{
> > -			DEBUG(0,("mangle: out of memory!\n"));
> > -			goto done;
> > -		}
> > -		strncpy_w (mangled, p, pref_len);
> > -		mangled[pref_len] = UCS2_CHAR('.');
> > -		mangled[pref_len + 1] = 0;
> > -		strncat_w (mangled, ext, ext_len);
> > -	}
> > -	else
> > -	{
> > -		mangled = strdup_w(p);
> > -		if (!mangled)
> > -		{
> > -			DEBUG(0,("mangle: out of memory!\n"));
> > -			goto done;
> > -		}
> > -	}
> > -
> > -	/* mangled name are returned in upper or lower case depending on
> > -	   case_default value */
> > -	strnorm_w(mangled);
> > -
> > -done:
> > -	if (tclock) tdb_chainunlock(mangle_tdb, klock);
> > -	SAFE_FREE(p);
> > -	SAFE_FREE(umpref);
> > -	SAFE_FREE(ext);
> > -
> > -	return mangled;
> > -}
> > -
> > -
> > -/* non unicode compatibility functions */
> > -
> > -char *dos_mangle(const char *dos_unmangled)
> > -{
> > -	smb_ucs2_t *in, *out;
> > -	char *dos_mangled;
> > -
> > -	if (!dos_unmangled || !*dos_unmangled) return NULL;
> > -
> > -	in = acnv_dosu2(dos_unmangled);
> > -	if (!in)
> > -	{
> > -		DEBUG(0,("dos_mangle: internal error acnv_dosu2() failed!\n"));
> > -		return NULL;
> > -	}
> > -
> > -	out = mangle(in);
> > -	if (!out)
> > -	{
> > -		SAFE_FREE(in);
> > -		return NULL;
> > -	}
> > -
> > -	dos_mangled = acnv_u2dos(out);
> > -	if (!dos_mangled)
> > -	{
> > -		DEBUG(0,("dos_mangle: internal error acnv_u2dos() failed!\n"));
> > -		goto done;
> > -	}
> > -
> > -done:
> > -	SAFE_FREE(in);
> > -	SAFE_FREE(out);
> > -	return dos_mangled;
> > -}
> > -
> > -char *dos_unmangle(const char *dos_mangled)
> > -{
> > -	smb_ucs2_t *in, *out;
> > -	char *dos_unmangled;
> > -
> > -	if (!dos_mangled || !*dos_mangled) return NULL;
> > -
> > -	in = acnv_dosu2(dos_mangled);
> > -	if (!in)
> > -	{
> > -		DEBUG(0,("dos_unmangle: internal error acnv_dosu2() failed!\n"));
> > -		return NULL;
> > -	}
> > -
> > -	out = unmangle(in);
> > -	if (!out)
> > -	{
> > -		SAFE_FREE(in);
> > -		return NULL;
> > -	}
> > -
> > -	dos_unmangled = acnv_u2dos(out);
> > -	if (!dos_unmangled)
> > -	{
> > -		DEBUG(0,("dos_unmangle: internal error acnv_u2dos failed!\n"));
> > -		goto done;
> > -	}
> > -
> > -done:
> > -	SAFE_FREE(in);
> > -	SAFE_FREE(out);
> > -	return dos_unmangled;
> > -}
> > -
> > -BOOL is_8_3(const char *fname, BOOL check_case)
> > +static NTSTATUS is_valid_name(const smb_ucs2_t *fname)
> >  {
> > -	const char *f;
> > -	smb_ucs2_t *ucs2name;
> > -	NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> > -
> > -	if (!fname || !*fname) return False;
> > -	if ((f = strrchr(fname, '/')) == NULL) f = fname;
> > -	else f++;
> > -
> > -	DEBUG(10,("is_8_3: testing [%s]\n", f));
> > -
> > -	if (strlen(f) > 12) return False;
> > -	
> > -	ucs2name = acnv_uxu2(f);
> > -	if (!ucs2name)
> > -	{
> > -		DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n"));
> > -		goto done;
> > -	}
> > -
> > -	ret = is_8_3_w(ucs2name);
> > -
> > -done:
> > -	SAFE_FREE(ucs2name);
> > -
> > -	DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False"));
> > -
> > -	if (NT_STATUS_IS_ERR(ret)) return False;
> > -	else return True;
> > -}
> > -
> > -NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
> > -{
> > -	smb_ucs2_t *pref = 0, *ext = 0;
> > -	size_t plen;
> > -	NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> > -
> > -	if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
> > -
> > -	DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */
> > -
> > -	if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
> > -	
> > -	if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
> > -		return NT_STATUS_OK;
> > -
> > -	if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
> > -
> > -	if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
> > -	plen = strlen_w(pref);
> > -
> > -	if (strchr_wa(pref, '.')) goto done;
> > -	if (plen < 1 || plen > 8) goto done;
> > -	if (ext) if (strlen_w(ext) > 3) goto done;
> > -
> > -	ret = NT_STATUS_OK;
> > -
> > -done:
> > -	SAFE_FREE(pref);
> > -	SAFE_FREE(ext);
> > -	return ret;
> > -}
> > -
> > -NTSTATUS has_valid_chars(const smb_ucs2_t *s)
> > -{
> > -	NTSTATUS ret = NT_STATUS_OK;
> > -
> > -	if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
> > -
> > -	DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */
> > -	
> > -	/* CHECK: this should not be necessary if the ms wild chars
> > -	   are not valid in valid.dat  --- simo */
> > -	if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
> > -
> > -	while (*s) {
> > -		if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
> > -		s++;
> > -	}
> > -
> > -	return ret;
> > -}
> > -
> > -NTSTATUS is_valid_name(const smb_ucs2_t *fname)
> > -{
> >  	smb_ucs2_t *str, *p;
> >  	NTSTATUS ret = NT_STATUS_OK;
> >  
> > @@ -702,297 +290,712 @@
> >  	SAFE_FREE(str);
> >  	return ret;
> >  }
> > -
> > -BOOL is_mangled(const char *s)
> > -{
> > -	smb_ucs2_t *u2, *res;
> > -	BOOL ret = False;
> > -	
> > -	DEBUG(10,("is_mangled: testing [%s]\n", s));
> > -	
> > -	if (!s || !*s) return False;
> > -	if ((strlen(s) > 12) || (!strchr(s, '~'))) return False;
> > -	
> > -	u2 = acnv_dosu2(s);
> > -	if (!u2)
> > -	{
> > -		DEBUG(0,("is_mangled: internal error acnv_dosu2() failed!!\n"));
> > -		return ret;
> > -	}
> > -
> > -	res = unmangle(u2);
> > -	if (res) ret = True;
> > -	SAFE_FREE(res);
> > -	SAFE_FREE(u2);
> > -	DEBUG(10,("is_mangled: returning  [%s]\n", ret?"True":"False"));
> > -	return ret;
> > -}
> >  
> > -NTSTATUS is_mangled_w(const smb_ucs2_t *s)
> > +static NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
> >  {
> > -	smb_ucs2_t *res;
> > -	NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> > -	
> > -	res = unmangle(s);
> > -	if (res) ret = NT_STATUS_OK;
> > -	SAFE_FREE(res);
> > -	return ret;
> > -}
> > -
> > -NTSTATUS path_has_mangled(const smb_ucs2_t *s)
> > -{
> > -	smb_ucs2_t *p, *f, *b;
> > +	smb_ucs2_t *pref = 0, *ext = 0;
> > +	size_t plen;
> >  	NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> >  
> > -	if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
> > -
> > -	p = strdup_w(s);
> > -	if (!p) return NT_STATUS_NO_MEMORY;
> > -	trim_string_wa(p, "/", "/");
> > -	f = b = p;
> > -	while (b) {
> > -		b = strchr_w(f, UCS2_CHAR('/'));
> > -		if (b) *b = 0;
> > -		if (NT_STATUS_IS_OK(is_mangled_w(f))) {
> > -			ret = NT_STATUS_OK;
> > -			goto done;
> > -		}
> > -		f = b + 1;
> > -	}
> > -done:
> > -	SAFE_FREE(p);
> > -	return ret;
> > -}
> > +	if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
> >  
> > -/* backward compatibility functions */
> > +	DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */
> >  
> > -void reset_mangled_cache(void)
> > -{
> > -	DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n"));
> > -}
> > +	if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
> > +	
> > +	if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
> > +		return NT_STATUS_OK;
> >  
> > -BOOL check_mangled_cache(char *s)
> > -{
> > -	smb_ucs2_t *u2, *res;
> > -	BOOL ret = False;
> > +	if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
> >  
> > -	DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n"));
> > -	DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s));
> > +	if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
> > +	plen = strlen_w(pref);
> >  
> > -	if (!s || !*s) return False;
> > +	if (strchr_wa(pref, '.')) goto done;
> > +	if (plen < 1 || plen > 8) goto done;
> > +	if (ext) if (strlen_w(ext) > 3) goto done;
> >  
> > -	u2 = acnv_dosu2(s);
> > -	if (!u2)
> > -	{
> > -		DEBUG(0,("check_mangled_cache: out of memory!\n"));
> > -		return ret;
> > -	}
> > +	ret = NT_STATUS_OK;
> >  
> > -	res = unmangle(u2);
> > -	if (res)
> > -	{
> > -		
> > -		ucs2_to_dos (s, res, PSTRING_LEN);
> > -		/* We MUST change this brainded interface,
> > -		   we do not know how many chars will be used
> > -		   in dos so i guess they will be no more than
> > -		   double the size of the unicode string
> > -		          ---simo */
> > -		DEBUG(10,("check_mangled_cache: returning -> [%s]\n", s));
> > -		ret = True;
> > -	}
> > -	SAFE_FREE(res);
> > -	SAFE_FREE(u2);
> > -	DEBUG(10,("check_mangled_cache: returning -> %s\n", ret?"True":"False"));
> > +done:
> > +	SAFE_FREE(pref);
> > +	SAFE_FREE(ext);
> >  	return ret;
> >  }
> >  
> > -void mangle_name_83(char *s)
> > +BOOL is_8_3(const char *fname, BOOL check_case)
> >  {
> > -	smb_ucs2_t *u2, *res;
> > +	const char *f;
> > +	smb_ucs2_t *ucs2name;
> > +	NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> >  
> > -	DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n"));
> > -	DEBUG(10,("mangle_name_83: testing -> [%s]\n", s));
> > +	if (!fname || !*fname) return False;
> > +	if ((f = strrchr(fname, '/')) == NULL) f = fname;
> > +	else f++;
> >  
> > -	if (!s || !*s) return;
> > +	DEBUG(10,("is_8_3: testing [%s]\n", f));
> > +
> > +	if (strlen(f) > 12) return False;
> >  	
> > -	u2 = acnv_dosu2(s);
> > -	if (!u2)
> > +	ucs2name = acnv_uxu2(f);
> > +	if (!ucs2name)
> >  	{
> > -		DEBUG(0,("mangle_name_83: internal error acnv_dosu2() failed!\n"));
> > -		return;
> > +		DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n"));
> > +		goto done;
> >  	}
> >  
> > -	res = mangle(u2);
> > -	if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */
> > -	DEBUG(10,("mangle_name_83: returning -> [%s]\n", s));
> > -	SAFE_FREE(res);
> > -	SAFE_FREE(u2);
> > -}
> > +	ret = is_8_3_w(ucs2name);
> >  
> > -BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
> > -{
> > -	DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n"));
> > +done:
> > +	SAFE_FREE(ucs2name);
> >  
> > -	if (!need83) return True;
> > -	/* if (is_8_3(OutName, True)) return True; */
> > -	/* Warning: we should check for invalid chars in file name and mangle
> > -	   if invalid chars found --simo*/
> > +	DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False"));
> >  
> > -	mangle_name_83(OutName);
> > +	if (!NT_STATUS_IS_OK(ret)) { 
> > +		return False;
> > +	}
> > +	
> >  	return True;
> >  }
> >  
> >  
> >  
> > -#if 0 /* TEST_MANGLE_CODE */
> > +/* -------------------------------------------------------------------------- **
> > + * Functions...
> > + */
> >  
> > -#define LONG		"this_is_a_long_file_name"
> > -#define	LONGM		"this_~01"
> > -#define SHORT		"short"
> > -#define	SHORTM		"short~01"
> > -#define EXT1		"ex1"
> > -#define EXT2		"e2"
> > -#define EXT3		"3"
> > -#define EXTFAIL		"longext"
> > -#define EXTNULL		""
> > +/* ************************************************************************** **
> > + * Initialize the static character test array.
> > + *
> > + *  Input:  none
> > + *
> > + *  Output: none
> > + *
> > + *  Notes:  This function changes (loads) the contents of the <chartest>
> > + *          array.  The scope of <chartest> is this file.
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void init_chartest( void )
> > +  {
> > +  char          *illegalchars = "*\\/?<>|\":";
> > +  unsigned char *s;
> > +  
> > +  memset( (char *)chartest, '\0', 256 );
> > +
> > +  for( s = (unsigned char *)illegalchars; *s; s++ )
> > +    chartest[*s] = ILLEGAL_MASK;
> > +
> > +  for( s = (unsigned char *)basechars; *s; s++ )
> > +    chartest[*s] |= BASECHAR_MASK;
> > +
> > +  ct_initialized = True;
> > +  } /* init_chartest */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Return True if the name *could be* a mangled name.
> > + *
> > + *  Input:  s - A path name - in UNIX pathname format.
> > + *
> > + *  Output: True if the name matches the pattern described below in the
> > + *          notes, else False.
> > + *
> > + *  Notes:  The input name is *not* tested for 8.3 compliance.  This must be
> > + *          done separately.  This function returns true if the name contains
> > + *          a magic character followed by excactly two characters from the
> > + *          basechars list (above), which in turn are followed either by the
> > + *          nul (end of string) byte or a dot (extension) or by a '/' (end of
> > + *          a directory name).
> > + *
> > + * ************************************************************************** **
> > + */
> > +BOOL is_mangled( char *s )
> > +  {
> > +  char *magic;
> > +
> > +  if( !ct_initialized )
> > +    init_chartest();
> > +
> > +  magic = strchr_m( s, magic_char );
> > +  while( magic && magic[1] && magic[2] )          /* 3 chars, 1st is magic. */
> > +    {
> > +    if( ('.' == magic[3] || '/' == magic[3] || !(magic[3]))          /* Ends with '.' or nul or '/' ?  */
> > +     && isbasechar( toupper(magic[1]) )           /* is 2nd char basechar?  */
> > +     && isbasechar( toupper(magic[2]) ) )         /* is 3rd char basechar?  */
> > +      return( True );                           /* If all above, then true, */
> > +    magic = strchr_m( magic+1, magic_char );      /*    else seek next magic. */
> > +    }
> > +  return( False );
> > +  } /* is_mangled */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Compare two cache keys and return a value indicating their ordinal
> > + * relationship.
> > + *
> > + *  Input:  ItemPtr - Pointer to a comparison key.  In this case, this will
> > + *                    be a mangled name string.
> > + *          NodePtr - Pointer to a node in the cache.  The node structure
> > + *                    will be followed in memory by a mangled name string.
> > + *
> > + *  Output: A signed integer, as follows:
> > + *            (x < 0)  <==> Key1 less than Key2
> > + *            (x == 0) <==> Key1 equals Key2
> > + *            (x > 0)  <==> Key1 greater than Key2
> > + *
> > + *  Notes:  This is a ubiqx-style comparison routine.  See ubi_BinTree for
> > + *          more info.
> > + *
> > + * ************************************************************************** **
> > + */
> > +static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
> > +  {
> > +  char *Key1 = (char *)ItemPtr;
> > +  char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
> > +
> > +  return( StrCaseCmp( Key1, Key2 ) );
> > +  } /* cache_compare */
> > +
> > +/* ************************************************************************** **
> > + * Free a cache entry.
> > + *
> > + *  Input:  WarrenZevon - Pointer to the entry that is to be returned to
> > + *                        Nirvana.
> > + *  Output: none.
> > + *
> > + *  Notes:  This function gets around the possibility that the standard
> > + *          free() function may be implemented as a macro, or other evil
> > + *          subversions (oh, so much fun).
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void cache_free_entry( ubi_trNodePtr WarrenZevon )
> > +  {
> > +	  ZERO_STRUCTP(WarrenZevon);
> > +	  SAFE_FREE( WarrenZevon );
> > +  } /* cache_free_entry */
> > +
> > +/* ************************************************************************** **
> > + * Initializes or clears the mangled cache.
> > + *
> > + *  Input:  none.
> > + *  Output: none.
> > + *
> > + *  Notes:  There is a section below that is commented out.  It shows how
> > + *          one might use lp_ calls to set the maximum memory and entry size
> > + *          of the cache.  You might also want to remove the constants used
> > + *          in ubi_cacheInit() and replace them with lp_ calls.  If so, then
> > + *          the calls to ubi_cacheSetMax*() would be moved into the else
> > + *          clause.  Another option would be to pass in the max_entries and
> > + *          max_memory values as parameters.  crh 09-Apr-1998.
> > + *
> > + * ************************************************************************** **
> > + */
> > +void reset_mangled_cache( void )
> > +  {
> > +  if( !mc_initialized )
> > +    {
> > +    (void)ubi_cacheInit( mangled_cache,
> > +                         cache_compare,
> > +                         cache_free_entry,
> > +                         MANGLED_CACHE_MAX_ENTRIES,
> > +                         MANGLED_CACHE_MAX_MEMORY );
> > +    mc_initialized = True;
> > +    }
> > +  else
> > +    {
> > +    (void)ubi_cacheClear( mangled_cache );
> > +    }
> > +
> > +  /*
> > +  (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
> > +  (void)ubi_cacheSetMaxMemory(  mangled_cache, lp_mangled_cache_memory() );
> > +  */
> > +  } /* reset_mangled_cache  */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Add a mangled name into the cache.
> > + *
> > + *  Notes:  If the mangled cache has not been initialized, then the
> > + *          function will simply fail.  It could initialize the cache,
> > + *          but that's not the way it was done before I changed the
> > + *          cache mechanism, so I'm sticking with the old method.
> > + *
> > + *          If the extension of the raw name maps directly to the
> > + *          extension of the mangled name, then we'll store both names
> > + *          *without* extensions.  That way, we can provide consistent
> > + *          reverse mangling for all names that match.  The test here is
> > + *          a bit more careful than the one done in earlier versions of
> > + *          mangle.c:
> > + *
> > + *            - the extension must exist on the raw name,
> > + *            - it must be all lower case
> > + *            - it must match the mangled extension (to prove that no
> > + *              mangling occurred).
> > + *
> > + *  crh 07-Apr-1998
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void cache_mangled_name( char *mangled_name, char *raw_name )
> > +  {
> > +  ubi_cacheEntryPtr new_entry;
> > +  char             *s1;
> > +  char             *s2;
> > +  size_t               mangled_len;
> > +  size_t               raw_len;
> > +  size_t               i;
> > +
> > +  /* If the cache isn't initialized, give up. */
> > +  if( !mc_initialized )
> > +    return;
> > +
> > +  /* Init the string lengths. */
> > +  mangled_len = strlen( mangled_name );
> > +  raw_len     = strlen( raw_name );
> > +
> > +  /* See if the extensions are unmangled.  If so, store the entry
> > +   * without the extension, thus creating a "group" reverse map.
> > +   */
> > +  s1 = strrchr( mangled_name, '.' );
> > +  if( s1 && (s2 = strrchr( raw_name, '.' )) )
> > +    {
> > +    i = 1;
> > +    while( s1[i] && (tolower( s1[1] ) == s2[i]) )
> > +      i++;
> > +    if( !s1[i] && !s2[i] )
> > +      {
> > +      mangled_len -= i;
> > +      raw_len     -= i;
> > +      }
> > +    }
> > +
> > +  /* Allocate a new cache entry.  If the allocation fails, just return. */
> > +  i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
> > +  new_entry = malloc( i );
> > +  if( !new_entry )
> > +    return;
> > +
> > +  /* Fill the new cache entry, and add it to the cache. */
> > +  s1 = (char *)(new_entry + 1);
> > +  s2 = (char *)&(s1[mangled_len + 1]);
> > +  (void)StrnCpy( s1, mangled_name, mangled_len );
> > +  (void)StrnCpy( s2, raw_name,     raw_len );
> > +  ubi_cachePut( mangled_cache, i, new_entry, s1 );
> > +  } /* cache_mangled_name */
> > +
> > +/* ************************************************************************** **
> > + * Check for a name on the mangled name stack
> > + *
> > + *  Input:  s - Input *and* output string buffer.
> > + *
> > + *  Output: True if the name was found in the cache, else False.
> > + *
> > + *  Notes:  If a reverse map is found, the function will overwrite the string
> > + *          space indicated by the input pointer <s>.  This is frightening.
> > + *          It should be rewritten to return NULL if the long name was not
> > + *          found, and a pointer to the long name if it was found.
> > + *
> > + * ************************************************************************** **
> > + */
> >  
> > -static void unmangle_test (char *name, char *ext)
> > +BOOL check_mangled_cache( char *s )
> > +{
> > +  ubi_cacheEntryPtr FoundPtr;
> > +  char             *ext_start = NULL;
> > +  char             *found_name;
> > +  char             *saved_ext = NULL;
> > +
> > +  /* If the cache isn't initialized, give up. */
> > +  if( !mc_initialized )
> > +    return( False );
> > +
> > +  FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
> > +
> > +  /* If we didn't find the name *with* the extension, try without. */
> > +  if( !FoundPtr )
> > +  {
> > +    ext_start = strrchr( s, '.' );
> > +    if( ext_start )
> > +    {
> > +      if((saved_ext = strdup(ext_start)) == NULL)
> > +        return False;
> > +
> > +      *ext_start = '\0';
> > +      FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
> > +      /* 
> > +       * At this point s is the name without the
> > +       * extension. We re-add the extension if saved_ext
> > +       * is not null, before freeing saved_ext.
> > +       */
> > +    }
> > +  }
> > +
> > +  /* Okay, if we haven't found it we're done. */
> > +  if( !FoundPtr )
> > +  {
> > +    if(saved_ext)
> > +    {
> > +      /* Replace the saved_ext as it was truncated. */
> > +      (void)pstrcat( s, saved_ext );
> > +      SAFE_FREE(saved_ext);
> > +    }
> > +    return( False );
> > +  }
> > +
> > +  /* If we *did* find it, we need to copy it into the string buffer. */
> > +  found_name = (char *)(FoundPtr + 1);
> > +  found_name += (strlen( found_name ) + 1);
> > +
> > +  DEBUG( 3, ("Found %s on mangled stack ", s) );
> > +
> > +  (void)pstrcpy( s, found_name );
> > +  if( saved_ext )
> > +  {
> > +    /* Replace the saved_ext as it was truncated. */
> > +    (void)pstrcat( s, saved_ext );
> > +    SAFE_FREE(saved_ext);
> > +  }
> > +
> > +  DEBUG( 3, ("as %s\n", s) );
> > +
> > +  return( True );
> > +} /* check_mangled_cache */
> > +
> > +
> > +/* ************************************************************************** **
> > + * Used only in do_fwd_mangled_map(), below.
> > + * ************************************************************************** **
> > + */
> > +static char *map_filename( char *s,         /* This is null terminated */
> > +                           char *pattern,   /* This isn't. */
> > +                           int len )        /* This is the length of pattern. */
> > +  {
> > +  static pstring matching_bit;  /* The bit of the string which matches */
> > +                                /* a * in pattern if indeed there is a * */
> > +  char *sp;                     /* Pointer into s. */
> > +  char *pp;                     /* Pointer into p. */
> > +  char *match_start;            /* Where the matching bit starts. */
> > +  pstring pat;
> > +
> > +  StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */
> > +  pstrcpy( matching_bit, "" );  /* Match but no star gets this. */
> > +  pp = pat;                     /* Initialize the pointers. */
> > +  sp = s;
> > +
> > +  if( strequal(s, ".") || strequal(s, ".."))
> > +    {
> > +    return NULL;                /* Do not map '.' and '..' */
> > +    }
> > +
> > +  if( (len == 1) && (*pattern == '*') )
> > +    {
> > +    return NULL;                /* Impossible, too ambiguous for */
> > +    }                           /* words! */
> > +
> > +  while( (*sp)                  /* Not the end of the string. */
> > +      && (*pp)                  /* Not the end of the pattern. */
> > +      && (*sp == *pp)           /* The two match. */
> > +      && (*pp != '*') )         /* No wildcard. */
> > +    {
> > +    sp++;                       /* Keep looking. */
> > +    pp++;
> > +    }
> > +
> > +  if( !*sp && !*pp )            /* End of pattern. */
> > +    return( matching_bit );     /* Simple match.  Return empty string. */
> > +
> > +  if( *pp == '*' )
> > +    {
> > +    pp++;                       /* Always interrested in the chacter */
> > +                                /* after the '*' */
> > +    if( !*pp )                  /* It is at the end of the pattern. */
> > +      {
> > +      StrnCpy( matching_bit, s, sp-s );
> > +      return( matching_bit );
> > +      }
> > +    else
> > +      {
> > +      /* The next character in pattern must match a character further */
> > +      /* along s than sp so look for that character. */
> > +      match_start = sp;
> > +      while( (*sp)              /* Not the end of s. */
> > +          && (*sp != *pp) )     /* Not the same  */
> > +        sp++;                   /* Keep looking. */
> > +      if( !*sp )                /* Got to the end without a match. */
> > +        {
> > +        return( NULL );
> > +        }                       /* Still hope for a match. */
> > +      else
> > +        {
> > +        /* Now sp should point to a matching character. */
> > +        StrnCpy(matching_bit, match_start, sp-match_start);
> > +        /* Back to needing a stright match again. */
> > +        while( (*sp)            /* Not the end of the string. */
> > +            && (*pp)            /* Not the end of the pattern. */
> > +            && (*sp == *pp) )   /* The two match. */
> > +          {
> > +          sp++;                 /* Keep looking. */
> > +          pp++;
> > +          }
> > +        if( !*sp && !*pp )      /* Both at end so it matched */
> > +          return( matching_bit );
> > +        else
> > +          return( NULL );
> > +        }
> > +      }
> > +    }
> > +  return( NULL );               /* No match. */
> > +  } /* map_filename */
> > +
> > +
> > +/* ************************************************************************** **
> > + * MangledMap is a series of name pairs in () separated by spaces.
> > + * If s matches the first of the pair then the name given is the
> > + * second of the pair.  A * means any number of any character and if
> > + * present in the second of the pair as well as the first the
> > + * matching part of the first string takes the place of the * in the
> > + * second.
> > + *
> > + * I wanted this so that we could have RCS files which can be used
> > + * by UNIX and DOS programs.  My mapping string is (RCS rcs) which
> > + * converts the UNIX RCS file subdirectory to lowercase thus
> > + * preventing mangling.
> > + *
> > + * (I think Andrew wrote the above, but I'm not sure. -- CRH)
> > + *
> > + * See 'mangled map' in smb.conf(5).
> > + *
> > + * ************************************************************************** **
> > + */
> > +static void do_fwd_mangled_map(char *s, char *MangledMap)
> > +  {
> > +  char *start=MangledMap;       /* Use this to search for mappings. */
> > +  char *end;                    /* Used to find the end of strings. */
> > +  char *match_string;
> > +  pstring new_string;           /* Make up the result here. */
> > +  char *np;                     /* Points into new_string. */
> > +
> > +  DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) );
> > +  while( *start )
> > +    {
> > +    while( (*start) && (*start != '(') )
> > +      start++;
> > +    if( !*start )
> > +      continue;                 /* Always check for the end. */
> > +    start++;                    /* Skip the ( */
> > +    end = start;                /* Search for the ' ' or a ')' */
> > +    DEBUG( 5, ("Start of first in pair '%s'\n", start) );
> > +    while( (*end) && !((*end == ' ') || (*end == ')')) )
> > +      end++;
> > +    if( !*end )
> > +      {
> > +      start = end;
> > +      continue;                 /* Always check for the end. */
> > +      }
> > +    DEBUG( 5, ("End of first in pair '%s'\n", end) );
> > +    if( (match_string = map_filename( s, start, end-start )) )
> > +      {
> > +      DEBUG( 5, ("Found a match\n") );
> > +      /* Found a match. */
> > +      start = end + 1;          /* Point to start of what it is to become. */
> > +      DEBUG( 5, ("Start of second in pair '%s'\n", start) );
> > +      end = start;
> > +      np = new_string;
> > +      while( (*end)             /* Not the end of string. */
> > +          && (*end != ')')      /* Not the end of the pattern. */
> > +          && (*end != '*') )    /* Not a wildcard. */
> > +        *np++ = *end++;
> > +      if( !*end )
> > +        {
> > +        start = end;
> > +        continue;               /* Always check for the end. */
> > +        }
> > +      if( *end == '*' )
> > +        {
> > +        pstrcpy( np, match_string );
> > +        np += strlen( match_string );
> > +        end++;                  /* Skip the '*' */
> > +        while( (*end)             /* Not the end of string. */
> > +            && (*end != ')')      /* Not the end of the pattern. */
> > +            && (*end != '*') )    /* Not a wildcard. */
> > +          *np++ = *end++;
> > +        }
> > +      if( !*end )
> > +        {
> > +        start = end;
> > +        continue;               /* Always check for the end. */
> > +        }
> > +      *np++ = '\0';             /* NULL terminate it. */
> > +      DEBUG(5,("End of second in pair '%s'\n", end));
> > +      pstrcpy( s, new_string );  /* Substitute with the new name. */
> > +      DEBUG( 5, ("s is now '%s'\n", s) );
> > +      }
> > +    start = end;              /* Skip a bit which cannot be wanted anymore. */
> > +    start++;
> > +    }
> > +  } /* do_fwd_mangled_map */
> > +
> > +/*****************************************************************************
> > + * do the actual mangling to 8.3 format
> > + * the buffer must be able to hold 13 characters (including the null)
> > + *****************************************************************************
> > + */
> > +void mangle_name_83( char *s)
> > +  {
> > +  int csum;
> > +  char *p;
> > +  char extension[4];
> > +  char base[9];
> > +  int baselen = 0;
> > +  int extlen = 0;
> > +  int skip;
> > +
> > +  extension[0] = 0;
> > +  base[0] = 0;
> > +
> > +  p = strrchr(s,'.');  
> > +  if( p && (strlen(p+1) < (size_t)4) )
> > +    {
> > +    BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
> > +
> > +    if( all_normal && p[1] != 0 )
> > +      {
> > +      *p = 0;
> > +      csum = str_checksum( s );
> > +      *p = '.';
> > +      }
> > +    else
> > +      csum = str_checksum(s);
> > +    }
> > +  else
> > +    csum = str_checksum(s);
> > +
> > +  strupper( s );
> > +
> > +  DEBUG( 5, ("Mangling name %s to ",s) );
> > +
> > +  if( p )
> > +  {
> > +	  if( p == s )
> > +		  safe_strcpy( extension, "___", 3 );
> > +	  else
> > +	  {
> > +		  *p++ = 0;
> > +		  while( *p && extlen < 3 )
> > +		  {
> > +			  if ( *p != '.') {
> > +				  extension[extlen++] = p[0];
> > +			  }
> > +			  p++;
> > +		  }
> > +		  extension[extlen] = 0;
> > +      }
> > +  }
> > +  
> > +  p = s;
> > +
> > +  while( *p && baselen < 5 )
> > +  {
> > +	  if (*p != '.') {
> > +		  base[baselen++] = p[0];
> > +	  }
> > +	  p++;
> > +  }
> > +  base[baselen] = 0;
> > +  
> > +  csum = csum % (MANGLE_BASE*MANGLE_BASE);
> > +  
> > +  (void)slprintf(s, 12, "%s%c%c%c",
> > +                 base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
> > +  
> > +  if( *extension )
> > +  {
> > +	  (void)pstrcat( s, "." );
> > +	  (void)pstrcat( s, extension );
> > +  }
> > +  
> > +  DEBUG( 5, ( "%s\n", s ) );
> > +
> > +  } /* mangle_name_83 */
> > +
> > +/*****************************************************************************
> > + * Convert a filename to DOS format.  Return True if successful.
> > + *
> > + *  Input:  OutName - Source *and* destination buffer. 
> > + *
> > + *                    NOTE that OutName must point to a memory space that
> > + *                    is at least 13 bytes in size!
> > + *
> > + *          need83  - If False, name mangling will be skipped unless the
> > + *                    name contains illegal characters.  Mapping will still
> > + *                    be done, if appropriate.  This is probably used to
> > + *                    signal that a client does not require name mangling,
> > + *                    thus skipping the name mangling even on shares which
> > + *                    have name-mangling turned on.
> > + *          cache83 - If False, the mangled name cache will not be updated.
> > + *                    This is usually used to prevent that we overwrite
> > + *                    a conflicting cache entry prematurely, i.e. before
> > + *                    we know whether the client is really interested in the
> > + *                    current name.  (See PR#13758).  UKD.
> > + *          snum    - Share number.  This identifies the share in which the
> > + *                    name exists.
> > + *
> > + *  Output: Returns False only if the name wanted mangling but the share does
> > + *          not have name mangling turned on.
> > + *
> > + * ****************************************************************************
> > + */
> > +BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
> >  {
> > -	smb_ucs2_t ucs2_name[2048];
> > -	smb_ucs2_t *retstr;
> > -	pstring unix_name;	
> > +	char *map;
> > +	smb_ucs2_t *OutName_ucs2;
> > +	DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s, %d )\n", OutName,
> > +		 need83 ? "True" : "False", cache83 ? "True" : "False", snum));
> > +	
> > +	if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) {
> > +		DEBUG(0, ("push_ucs2_allocate failed!\n"));
> > +		return False;
> > +	}
> >  
> > -	push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
> > -	if (ext)
> > -	{
> > -		strncat_wa(ucs2_name, ".", 1);
> > -		strncat_wa(ucs2_name, ext, strlen(ext) + 1);
> > +#ifdef MANGLE_LONG_FILENAMES
> > +
> > +	if( !need83 && !NT_STATUS_IS_OK(has_valid_chars(OutName_ucs2 ))) {
> > +		need83 = True;
> >  	}
> > -	retstr = unmangle(ucs2_name);
> > -	if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
> > -	else unix_name[0] = 0;
> > -	if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
> > -	else printf ("[%s] ---> [%s]\n", name, unix_name);
> > -	SAFE_FREE(retstr);
> > -}
> > +#endif  
> >  
> > -static void mangle_test (char *name, char *ext)
> > -{
> > -	smb_ucs2_t ucs2_name[2048];
> > -	smb_ucs2_t *retstr;
> > -	pstring unix_name;	
> > +	/* apply any name mappings */
> > +	map = lp_mangled_map(snum);
> >  
> > -	push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
> > -	if (ext)
> > -	{
> > -		strncat_wa(ucs2_name, ".", 1);
> > -		strncat_wa(ucs2_name, ext, strlen(ext) + 1);
> > +	if (map && *map) {
> > +		do_fwd_mangled_map( OutName, map );
> >  	}
> > -	retstr = mangle(ucs2_name);
> > -	if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
> > -	else unix_name[0] = 0;
> > -	if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
> > -	else printf ("[%s] ---> [%s]\n", name, unix_name);
> > -	SAFE_FREE(retstr);
> > -}
> >  
> > -void mangle_test_code(void)
> > -{
> > -	init_mangle_tdb();
> > +	/* check if it's already in 8.3 format */
> > +	if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) {
> > +		char *tmp = NULL; 
> >  
> > -	/* unmangle every */
> > -	printf("Unmangle test 1:\n");
> > +		if (!lp_manglednames(snum)) {
> > +			return(False);
> > +		}
> >  
> > -	unmangle_test (LONG, NULL);
> > -	unmangle_test (LONG, EXT1);
> > -	unmangle_test (LONG, EXT2);
> > -	unmangle_test (LONG, EXT3);
> > -	unmangle_test (LONG, EXTFAIL);
> > -	unmangle_test (LONG, EXTNULL);
> > -
> > -	unmangle_test (LONGM, NULL);
> > -	unmangle_test (LONGM, EXT1);
> > -	unmangle_test (LONGM, EXT2);
> > -	unmangle_test (LONGM, EXT3);
> > -	unmangle_test (LONGM, EXTFAIL);
> > -	unmangle_test (LONGM, EXTNULL);
> > -
> > -	unmangle_test (SHORT, NULL);
> > -	unmangle_test (SHORT, EXT1);
> > -	unmangle_test (SHORT, EXT2);
> > -	unmangle_test (SHORT, EXT3);
> > -	unmangle_test (SHORT, EXTFAIL);
> > -	unmangle_test (SHORT, EXTNULL);
> > -
> > -	unmangle_test (SHORTM, NULL);
> > -	unmangle_test (SHORTM, EXT1);
> > -	unmangle_test (SHORTM, EXT2);
> > -	unmangle_test (SHORTM, EXT3);
> > -	unmangle_test (SHORTM, EXTFAIL);
> > -	unmangle_test (SHORTM, EXTNULL);
> > -
> > -	/* mangle every */
> > -	printf("Mangle test\n");
> > -
> > -	mangle_test (LONG, NULL);
> > -	mangle_test (LONG, EXT1);
> > -	mangle_test (LONG, EXT2);
> > -	mangle_test (LONG, EXT3);
> > -	mangle_test (LONG, EXTFAIL);
> > -	mangle_test (LONG, EXTNULL);
> > -
> > -	mangle_test (LONGM, NULL);
> > -	mangle_test (LONGM, EXT1);
> > -	mangle_test (LONGM, EXT2);
> > -	mangle_test (LONGM, EXT3);
> > -	mangle_test (LONGM, EXTFAIL);
> > -	mangle_test (LONGM, EXTNULL);
> > -
> > -	mangle_test (SHORT, NULL);
> > -	mangle_test (SHORT, EXT1);
> > -	mangle_test (SHORT, EXT2);
> > -	mangle_test (SHORT, EXT3);
> > -	mangle_test (SHORT, EXTFAIL);
> > -	mangle_test (SHORT, EXTNULL);
> > -
> > -	mangle_test (SHORTM, NULL);
> > -	mangle_test (SHORTM, EXT1);
> > -	mangle_test (SHORTM, EXT2);
> > -	mangle_test (SHORTM, EXT3);
> > -	mangle_test (SHORTM, EXTFAIL);
> > -	mangle_test (SHORTM, EXTNULL);
> > -
> > -	/* unmangle again every */
> > -	printf("Unmangle test 2:\n");
> > -
> > -	unmangle_test (LONG, NULL);
> > -	unmangle_test (LONG, EXT1);
> > -	unmangle_test (LONG, EXT2);
> > -	unmangle_test (LONG, EXT3);
> > -	unmangle_test (LONG, EXTFAIL);
> > -	unmangle_test (LONG, EXTNULL);
> > -
> > -	unmangle_test (LONGM, NULL);
> > -	unmangle_test (LONGM, EXT1);
> > -	unmangle_test (LONGM, EXT2);
> > -	unmangle_test (LONGM, EXT3);
> > -	unmangle_test (LONGM, EXTFAIL);
> > -	unmangle_test (LONGM, EXTNULL);
> > -
> > -	unmangle_test (SHORT, NULL);
> > -	unmangle_test (SHORT, EXT1);
> > -	unmangle_test (SHORT, EXT2);
> > -	unmangle_test (SHORT, EXT3);
> > -	unmangle_test (SHORT, EXTFAIL);
> > -	unmangle_test (SHORT, EXTNULL);
> > -
> > -	unmangle_test (SHORTM, NULL);
> > -	unmangle_test (SHORTM, EXT1);
> > -	unmangle_test (SHORTM, EXT2);
> > -	unmangle_test (SHORTM, EXT3);
> > -	unmangle_test (SHORTM, EXTFAIL);
> > -	unmangle_test (SHORTM, EXTNULL);
> > -}
> > +		/* mangle it into 8.3 */
> > +		if (cache83)
> > +			tmp = strdup(OutName);
> > +
> > +		mangle_name_83(OutName);
> > +
> > +		if(tmp != NULL) {
> > +			cache_mangled_name(OutName, tmp);
> > +			SAFE_FREE(tmp);
> > +		}
> > +	}
> > +
> > +	DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName));
> > +	SAFE_FREE(OutName_ucs2);
> > +	return(True);
> > +} /* name_map_mangle */
> >  
> > -#endif /* TEST_MANGLE_CODE */
> > Index: smbd/reply.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/reply.c,v
> > retrieving revision 1.376
> > diff -u -r1.376 reply.c
> > --- smbd/reply.c	2002/03/23 02:57:43	1.376
> > +++ smbd/reply.c	2002/03/25 08:24:47
> > @@ -3054,10 +3054,10 @@
> >  	 * Tine Smukavec <valentin.smukavec at hermes.si>.
> >  	 */
> >  
> > -#if 0
> > +#if 1
> >  	if (!rc && is_mangled(mask))
> >  		check_mangled_cache( mask );
> > -#endif
> > +#else
> >  	if (!rc)
> >  	{
> >  		char *unmangled;
> > @@ -3068,6 +3068,7 @@
> >  			
> >  		SAFE_FREE(unmangled);
> >  	}
> > +#endif
> >  
> >  	has_wild = ms_has_wild(mask);
> >  
> > @@ -3470,10 +3471,10 @@
> >     * Tine Smukavec <valentin.smukavec at hermes.si>.
> >     */
> >  
> > -#if 0
> > +#if 1
> >  	if (!rc && is_mangled(mask))
> >  		check_mangled_cache( mask );
> > -#endif
> > +#else
> >  	if (!rc)
> >  	{
> >  		char *unmangled;
> > @@ -3484,7 +3485,7 @@
> >  			
> >  		SAFE_FREE(unmangled);
> >  	}
> > -
> > +#endif
> >  
> >    has_wild = ms_has_wild(mask);
> >  
> > Index: smbd/server.c
> > ===================================================================
> > RCS file: /data/cvs/samba/source/smbd/server.c,v
> > retrieving revision 1.369
> > diff -u -r1.369 server.c
> > --- smbd/server.c	2002/03/14 02:15:08	1.369
> > +++ smbd/server.c	2002/03/25 08:24:48
> > @@ -882,10 +882,6 @@
> >  	if (!init_oplocks())
> >  		exit(1);
> >  	
> > -	/* Setup mangle */
> > -	if (!init_mangle_tdb())
> > -		exit(1);
> > -
> >  	/* Setup change notify */
> >  	if (!init_change_notify())
> >  		exit(1);
> -- 
> Simo Sorce
> ----------
> Una scelta di liberta': Software Libero.
> A choice of freedom: Free Software.
> http://www.softwarelibero.it
> 
-- 
Simo Sorce
----------
Una scelta di liberta': Software Libero.
A choice of freedom: Free Software.
http://www.softwarelibero.it




More information about the samba-technical mailing list