Work in progress.

Jeremy Allison jra at samba.org
Thu Sep 6 20:24:25 GMT 2007


On Wed, Sep 05, 2007 at 07:13:04PM -0700, Jeremy Allison wrote:
> On Wed, Sep 05, 2007 at 05:47:19PM -0700, Jeremy Allison wrote:
> > On Wed, Sep 05, 2007 at 12:38:02PM -0700, Jeremy Allison wrote:
> > > Work in progress, part2. Still doesn't fully compile but getting
> > > better. Shows the new (sane) mangling interface.
> > 
> > And here is a version that actually compiles. I'm going to do some
> > testing and once it passes check into SAMBA_3_2 (only for now) and
> > then work on making the dfs_redirect calls talloc based, and start
> > removing the pstrings from the main code paths.
> 
> Now with working statcache ! :-).

Getting better, still fails a few make test tests but no longer
crashes. This is a checkpoint - I'll post the final when I'm
done.

Jeremy.
-------------- next part --------------
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 24984)
+++ Makefile.in	(working copy)
@@ -511,7 +511,7 @@
 	   auth/auth_compat.o auth/auth_ntlmssp.o \
 	   $(PLAINTEXT_AUTH_OBJ) $(SLCACHE_OBJ) $(DCUTIL_OBJ)
 
-MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_map.o smbd/mangle_hash2.o
+MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_hash2.o
 
 SMBD_OBJ_MAIN = smbd/server.o
 
Index: smbd/mangle_hash.c
===================================================================
--- smbd/mangle_hash.c	(revision 24984)
+++ smbd/mangle_hash.c	(working copy)
@@ -1,20 +1,21 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    Name mangling
    Copyright (C) Andrew Tridgell 1992-2002
    Copyright (C) Simo Sorce 2001
    Copyright (C) Andrew Bartlett 2002
-   
+   Copyright (C) Jeremy Allison 2007
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -244,14 +245,14 @@
 
 	if (strlen_w(fname) > 12)
 		return NT_STATUS_UNSUCCESSFUL;
-	
+
 	if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
 		return NT_STATUS_OK;
 
 	/* Name cannot start with '.' */
 	if (*fname == UCS2_CHAR('.'))
 		return NT_STATUS_UNSUCCESSFUL;
-	
+
 	if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards, True)))
 		goto done;
 
@@ -293,7 +294,7 @@
 
 	if (strlen(f) > 12)
 		return False;
-	
+
 	size = push_ucs2_allocate(&ucs2name, f);
 	if (size == (size_t)-1) {
 		DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n"));
@@ -305,15 +306,13 @@
 done:
 	SAFE_FREE(ucs2name);
 
-	if (!NT_STATUS_IS_OK(ret)) { 
+	if (!NT_STATUS_IS_OK(ret)) {
 		return False;
 	}
-	
+
 	return True;
 }
 
-
-
 /* -------------------------------------------------------------------------- **
  * Functions...
  */
@@ -330,10 +329,11 @@
  *
  * ************************************************************************** **
  */
+
 static void init_chartest( void )
 {
 	const unsigned char *s;
-  
+
 	memset( (char *)chartest, '\0', 256 );
 
 	for( s = (const unsigned char *)basechars; *s; s++ ) {
@@ -360,6 +360,7 @@
  *
  * ************************************************************************** **
  */
+
 static BOOL is_mangled(const char *s, const struct share_params *p)
 {
 	char *magic;
@@ -406,7 +407,8 @@
   crh 07-Apr-1998
 **************************************************************************/
 
-static void cache_mangled_name( const char mangled_name[13], char *raw_name )
+static void cache_mangled_name( const char mangled_name[13],
+				const char *raw_name )
 {
 	TDB_DATA data_val;
 	char mangled_name_key[13];
@@ -459,30 +461,37 @@
  * ************************************************************************** **
  */
 
-static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
+static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx,
+				const char *in,
+				char **out, /* talloced on the given context. */
+				const struct share_params *p)
 {
 	TDB_DATA data_val;
-	char *ext_start = NULL;
 	char *saved_ext = NULL;
+	char *s = talloc_strdup(ctx, in);
 
 	magic_char = lp_magicchar(p);
 
 	/* If the cache isn't initialized, give up. */
-	if( !tdb_mangled_cache )
-		return( False );
+	if(!s || !tdb_mangled_cache ) {
+		TALLOC_FREE(s);
+		return False;
+	}
 
 	data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
 
 	/* If we didn't find the name *with* the extension, try without. */
 	if(data_val.dptr == NULL || data_val.dsize == 0) {
-		ext_start = strrchr( s, '.' );
+		char *ext_start = strrchr( s, '.' );
 		if( ext_start ) {
-			if((saved_ext = SMB_STRDUP(ext_start)) == NULL)
+			if((saved_ext = talloc_strdup(ctx,ext_start)) == NULL) {
+				TALLOC_FREE(s);
 				return False;
+			}
 
 			*ext_start = '\0';
 			data_val = tdb_fetch_bystring(tdb_mangled_cache, 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.
@@ -492,31 +501,32 @@
 
 	/* Okay, if we haven't found it we're done. */
 	if(data_val.dptr == NULL || data_val.dsize == 0) {
-		if(saved_ext) {
-			/* Replace the saved_ext as it was truncated. */
-			(void)safe_strcat( s, saved_ext, maxlen );
-			SAFE_FREE(saved_ext);
-		}
-		return( False );
+		TALLOC_FREE(saved_ext);
+		TALLOC_FREE(s);
+		return False;
 	}
 
-	/* If we *did* find it, we need to copy it into the string buffer. */
-	(void)safe_strcpy( s, (const char *)data_val.dptr, maxlen );
-	if( saved_ext ) {
-		/* Replace the saved_ext as it was truncated. */
-		(void)safe_strcat( s, saved_ext, maxlen );
-		SAFE_FREE(saved_ext);
+	/* If we *did* find it, we need to talloc it on the given ctx. */
+	if (saved_ext) {
+		*out = talloc_asprintf(ctx, "%s%s",
+					(char *)data_val.dptr,
+					saved_ext);
+	} else {
+		*out = talloc_strdup(ctx, (char *)data_val.dptr);
 	}
+
+	TALLOC_FREE(s);
+	TALLOC_FREE(saved_ext);
 	SAFE_FREE(data_val.dptr);
-	return( True );
+
+	return *out ? True : False;
 }
 
 /*****************************************************************************
- * do the actual mangling to 8.3 format
- * the buffer must be able to hold 13 characters (including the null)
- *****************************************************************************
- */
-static void to_8_3(char *s, int default_case)
+ Do the actual mangling to 8.3 format.
+*****************************************************************************/
+
+static BOOL to_8_3(const char *in, char out[13], int default_case)
 {
 	int csum;
 	char *p;
@@ -524,11 +534,16 @@
 	char base[9];
 	int baselen = 0;
 	int extlen = 0;
+	char *s = SMB_STRDUP(in);
 
 	extension[0] = 0;
 	base[0] = 0;
 
-	p = strrchr(s,'.');  
+	if (!s) {
+		return False;
+	}
+
+	p = strrchr(s,'.');
 	if( p && (strlen(p+1) < (size_t)4) ) {
 		BOOL all_normal = ( strisnormal(p+1, default_case) ); /* XXXXXXXXX */
 
@@ -557,7 +572,7 @@
 			extension[extlen] = 0;
 		}
 	}
-  
+
 	p = s;
 
 	while( *p && baselen < 5 ) {
@@ -567,79 +582,88 @@
 		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 ) );
-  
+
+	memcpy(out, base, baselen);
+	out[baselen] = magic_char;
+	out[baselen+1] = mangle( csum/MANGLE_BASE );
+	out[baselen+2] = mangle( csum );
+
 	if( *extension ) {
-		(void)pstrcat( s, "." );
-		(void)pstrcat( s, extension );
+		out[baselen+3] = '.';
+		safe_strcpy(&out[baselen+4], extension, 3);
 	}
+
+	SAFE_FREE(s);
+	return True;
 }
 
+static BOOL must_mangle(const char *name,
+			const struct share_params *p)
+{
+	smb_ucs2_t *name_ucs2 = NULL;
+	NTSTATUS status;
+	magic_char = lp_magicchar(p);
+
+	if (push_ucs2_allocate(&name_ucs2, name) == (size_t)-1) {
+		DEBUG(0, ("push_ucs2_allocate failed!\n"));
+		return False;
+	}
+	status = is_valid_name(name_ucs2, False, False);
+	SAFE_FREE(name_ucs2);
+	return NT_STATUS_IS_OK(status);
+}
+
 /*****************************************************************************
  * Convert a filename to DOS format.  Return True if successful.
+ *  Input:  in        Incoming name.
  *
- *  Input:  OutName - Source *and* destination buffer. 
+ *          out       8.3 DOS name.
  *
- *                    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.
  *
- *  Output: Returns False only if the name wanted mangling but the share does
- *          not have name mangling turned on.
- *
  * ****************************************************************************
  */
 
-static void name_map(char *OutName, BOOL need83, BOOL cache83,
-		     int default_case, const struct share_params *p)
+static BOOL hash_name_to_8_3(const char *in,
+			char out[13],
+			BOOL cache83,
+			int default_case,
+			const struct share_params *p)
 {
-	smb_ucs2_t *OutName_ucs2;
+	smb_ucs2_t *in_ucs2 = NULL;
 	magic_char = lp_magicchar(p);
 
-	DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
-		 need83 ? "True" : "False", cache83 ? "True" : "False"));
-	
-	if (push_ucs2_allocate(&OutName_ucs2, OutName) == (size_t)-1) {
+	DEBUG(5,("hash_name_to_8_3( %s, cache83 = %s)\n", in,
+		 cache83 ? "True" : "False"));
+
+	if (push_ucs2_allocate(&in_ucs2, in) == (size_t)-1) {
 		DEBUG(0, ("push_ucs2_allocate failed!\n"));
-		return;
+		return False;
 	}
 
-	if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False, False)))
-		need83 = True;
+	/* If it's already 8.3, just copy. */
+	if (NT_STATUS_IS_OK(is_valid_name(in_ucs2, False, False)) &&
+				NT_STATUS_IS_OK(is_8_3_w(in_ucs2, False))) {
+		SAFE_FREE(in_ucs2);
+		safe_strcpy(out, in, 12);
+		return True;
+	}
 
-	/* check if it's already in 8.3 format */
-	if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2, False))) {
-		char *tmp = NULL; 
+	SAFE_FREE(in_ucs2);
+	if (!to_8_3(in, out, default_case)) {
+		return False;
+	}
 
-		/* mangle it into 8.3 */
-		if (cache83)
-			tmp = SMB_STRDUP(OutName);
+	cache_mangled_name(out, in);
 
-		to_8_3(OutName, default_case);
-
-		if(tmp != NULL) {
-			cache_mangled_name(OutName, tmp);
-			SAFE_FREE(tmp);
-		}
-	}
-
-	DEBUG(5,("name_map() ==> [%s]\n", OutName));
-	SAFE_FREE(OutName_ucs2);
+	DEBUG(5,("hash_name_to_8_3(%s) ==> [%s]\n", in, out));
+	return True;
 }
 
 /*
@@ -649,9 +673,10 @@
 static struct mangle_fns mangle_fns = {
 	mangle_reset,
 	is_mangled,
+	must_mangle,
 	is_8_3,
-	check_cache,
-	name_map
+	lookup_name_from_8_3,
+	hash_name_to_8_3
 };
 
 /* return the methods for this mangling implementation */
Index: smbd/msdfs.c
===================================================================
--- smbd/msdfs.c	(revision 24984)
+++ smbd/msdfs.c	(working copy)
@@ -369,7 +369,8 @@
 	char *q = NULL;
 	SMB_STRUCT_STAT sbuf;
 	NTSTATUS status;
-	pstring localpath;
+	pstring localpath_in;
+	char *localpath = NULL;
 	pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */
 
 	DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n",
@@ -387,8 +388,8 @@
 	 * think this is needed. JRA.
 	 */
 
-	pstrcpy(localpath, pdp->reqpath);
-	status = unix_convert(conn, localpath, search_flag, NULL, &sbuf);
+	pstrcpy(localpath_in, pdp->reqpath);
+	status = unix_convert(conn, localpath_in, search_flag, &localpath, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,
 					NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
 		return status;
Index: smbd/mangle_hash2.c
===================================================================
--- smbd/mangle_hash2.c	(revision 24984)
+++ smbd/mangle_hash2.c	(working copy)
@@ -368,18 +368,23 @@
 
 /*
   try to find a 8.3 name in the cache, and if found then
-  replace the string with the original long name. 
+  replace the string with the original long name.
 */
-static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
+static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx,
+			const char *name,
+			char **pp_out, /* talloced on the given context. */
+			const struct share_params *p)
 {
 	unsigned int hash, multiplier;
 	unsigned int i;
 	const char *prefix;
 	char extension[4];
 
+	*pp_out = NULL;
+
 	/* make sure that this is a mangled name from this cache */
 	if (!is_mangled(name, p)) {
-		M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
+		M_DEBUG(10,("lookup_name_from_8_3: %s -> not mangled\n", name));
 		return False;
 	}
 
@@ -394,7 +399,8 @@
 	/* now look in the prefix cache for that hash */
 	prefix = cache_lookup(hash);
 	if (!prefix) {
-		M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash));
+		M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n",
+					name, hash));
 		return False;
 	}
 
@@ -407,17 +413,22 @@
 	}
 
 	if (extension[0]) {
-		M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension));
-		slprintf(name, maxlen, "%s.%s", prefix, extension);
+		M_DEBUG(10,("lookup_name_from_8_3: %s -> %s.%s\n",
+					name, prefix, extension));
+		*pp_out = talloc_asprintf(ctx, "%s.%s", prefix, extension);
 	} else {
-		M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix));
-		safe_strcpy(name, prefix, maxlen);
+		M_DEBUG(10,("lookup_name_from_8_3: %s -> %s\n", name, prefix));
+		*pp_out = talloc_strdup(ctx, prefix);
 	}
 
+	if (!pp_out) {
+		M_DEBUG(0,("talloc_fail"));
+		return False;
+	}
+
 	return True;
 }
 
-
 /*
   look for a DOS reserved name
 */
@@ -499,18 +510,27 @@
 	return True;
 }
 
+static BOOL must_mangle(const char *name,
+			const struct share_params *p)
+{
+	if (is_reserved_name(name)) {
+		return True;
+	}
+	return !is_legal_name(name);
+}
+
 /*
   the main forward mapping function, which converts a long filename to 
   a 8.3 name
 
-  if need83 is not set then we only do the mangling if the name is illegal
-  as a long name
-
   if cache83 is not set then we don't cache the result
 
-  the name parameter must be able to hold 13 bytes
 */
-static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
+static BOOL hash2_name_to_8_3(const char *name,
+			char new_name[13],
+			BOOL cache83,
+			int default_case,
+			const struct share_params *p)
 {
 	char *dot_p;
 	char lead_chars[7];
@@ -518,21 +538,15 @@
 	unsigned int extension_length, i;
 	unsigned int prefix_len;
 	unsigned int hash, v;
-	char new_name[13];
 
 	/* reserved names are handled specially */
 	if (!is_reserved_name(name)) {
-		/* if the name is already a valid 8.3 name then we don't need to 
-		   do anything */
-		if (is_8_3(name, False, False, p)) {
-			return;
+		/* if the name is already a valid 8.3 name then we don't need to
+		 * change anything */
+		if (is_legal_name(name) && is_8_3(name, False, False, p)) {
+			safe_strcpy(new_name, name, 12);
+			return True;
 		}
-
-		/* if the caller doesn't strictly need 8.3 then just check for illegal 
-		   filenames */
-		if (!need83 && is_legal_name(name)) {
-			return;
-		}
 	}
 
 	/* find the '.' if any */
@@ -548,7 +562,9 @@
 				break;
 			}
 		}
-		if (i == 0 || i == 4) dot_p = NULL;
+		if (i == 0 || i == 4) {
+			dot_p = NULL;
+		}
 	}
 
 	/* the leading characters in the mangled name is taken from
@@ -580,11 +596,12 @@
 		for (i=1; extension_length < 3 && dot_p[i]; i++) {
 			char c = dot_p[i];
 			if (FLAG_CHECK(c, FLAG_ASCII)) {
-				extension[extension_length++] = toupper_ascii(c);
+				extension[extension_length++] =
+					toupper_ascii(c);
 			}
 		}
 	}
-	   
+
 	/* find the hash for this prefix */
 	v = hash = mangle_hash(name, prefix_len);
 
@@ -593,7 +610,7 @@
 		new_name[i] = lead_chars[i];
 	}
 	new_name[7] = base_forward(v % 36);
-	new_name[6] = '~';	
+	new_name[6] = '~';
 	for (i=5; i>=mangle_prefix; i--) {
 		v = v / 36;
 		new_name[i] = base_forward(v % 36);
@@ -613,22 +630,18 @@
 		cache_insert(name, prefix_len, hash);
 	}
 
-	M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", 
+	M_DEBUG(10,("hash2_name_to_8_3: %s -> %08X -> %s (cache=%d)\n",
 		   name, hash, new_name, cache83));
 
-	/* and overwrite the old name */
-	fstrcpy(name, new_name);
-
-	/* all done, we've managed to mangle it */
+	return True;
 }
 
+/* initialise the flags table
 
-/* initialise the flags table 
-
   we allow only a very restricted set of characters as 'ascii' in this
   mangling backend. This isn't a significant problem as modern clients
   use the 'long' filenames anyway, and those don't have these
-  restrictions. 
+  restrictions.
 */
 static void init_tables(void)
 {
@@ -642,8 +655,8 @@
 			char_flags[i] |= FLAG_ILLEGAL;
 		}
 
-		if ((i >= '0' && i <= '9') || 
-		    (i >= 'a' && i <= 'z') || 
+		if ((i >= '0' && i <= '9') ||
+		    (i >= 'a' && i <= 'z') ||
 		    (i >= 'A' && i <= 'Z')) {
 			char_flags[i] |=  (FLAG_ASCII | FLAG_BASECHAR);
 		}
@@ -663,7 +676,7 @@
 	memset(base_reverse, 0, sizeof(base_reverse));
 	for (i=0;i<36;i++) {
 		base_reverse[(unsigned char)base_forward(i)] = i;
-	}	
+	}
 
 	/* fill in the reserved names flags. These are used as a very
 	   fast filter for finding possible DOS reserved filenames */
@@ -694,9 +707,10 @@
 static struct mangle_fns mangle_fns = {
 	mangle_reset,
 	is_mangled,
+	must_mangle,
 	is_8_3,
-	check_cache,
-	name_map
+	lookup_name_from_8_3,
+	hash2_name_to_8_3
 };
 
 /* return the methods for this mangling implementation */
@@ -729,30 +743,45 @@
 	return False;
 }
 
-static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
+static BOOL posix_must_mangle(const char *s, const struct share_params *p)
 {
 	return False;
 }
 
-static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p )
+static BOOL posix_is_8_3(const char *fname,
+			BOOL check_case,
+			BOOL allow_wildcards,
+			const struct share_params *p)
 {
 	return False;
 }
 
-static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
+static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx,
+				const char *in,
+				char **out, /* talloced on the given context. */
+				const struct share_params *p)
 {
-	if (need83) {
-		memset(OutName, '\0', 13);
-	}
+	return False;
 }
 
+static BOOL posix_name_to_8_3(const char *in,
+				char out[13],
+				BOOL cache83,
+				int default_case,
+				const struct share_params *p)
+{
+	memset(out, '\0', 13);
+	return True;
+}
+
 /* POSIX paths backend - no mangle. */
 static struct mangle_fns posix_mangle_fns = {
-        posix_mangle_reset,
-        posix_is_mangled,
-        posix_is_8_3,
-        posix_check_cache,
-        posix_name_map
+	posix_mangle_reset,
+	posix_is_mangled,
+	posix_must_mangle,
+	posix_is_8_3,
+	posix_lookup_name_from_8_3,
+	posix_name_to_8_3
 };
 
 struct mangle_fns *posix_mangle_init(void)
Index: smbd/nttrans.c
===================================================================
--- smbd/nttrans.c	(revision 24984)
+++ smbd/nttrans.c	(working copy)
@@ -489,7 +489,8 @@
 void reply_ntcreate_and_X(connection_struct *conn,
 			  struct smb_request *req)
 {  
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	uint32 flags;
 	uint32 access_mask;
 	uint32 file_attributes;
@@ -589,8 +590,8 @@
 
 		if(!dir_fsp->is_directory) {
 
-			srvstr_get_path((char *)req->inbuf, req->flags2, fname,
-					smb_buf(req->inbuf), sizeof(fname), 0,
+			srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+					smb_buf(req->inbuf), sizeof(fname_in), 0,
 					STR_TERMINATE, &status);
 			if (!NT_STATUS_IS_OK(status)) {
 				reply_nterror(req, status);
@@ -602,7 +603,7 @@
 			 * Check to see if this is a mac fork of some kind.
 			 */
 
-			if( is_ntfs_stream_name(fname)) {
+			if( is_ntfs_stream_name(fname_in)) {
 				reply_nterror(
 					req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
 				END_PROFILE(SMBntcreateX);
@@ -625,15 +626,15 @@
 		 * Copy in the base directory name.
 		 */
 
-		pstrcpy( fname, dir_fsp->fsp_name );
-		dir_name_len = strlen(fname);
+		pstrcpy( fname_in, dir_fsp->fsp_name );
+		dir_name_len = strlen(fname_in);
 
 		/*
 		 * Ensure it ends in a '\'.
 		 */
 
-		if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
-			pstrcat(fname, "/");
+		if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) {
+			pstrcat(fname_in, "/");
 			dir_name_len++;
 		}
 
@@ -645,10 +646,10 @@
 			END_PROFILE(SMBntcreateX);
 			return;
 		}
-		pstrcat(fname, rel_fname);
+		pstrcat(fname_in, rel_fname);
 	} else {
-		srvstr_get_path((char *)req->inbuf, req->flags2, fname,
-				smb_buf(req->inbuf), sizeof(fname), 0,
+		srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+				smb_buf(req->inbuf), sizeof(fname_in), 0,
 				STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			reply_nterror(req, status);
@@ -660,8 +661,8 @@
 		 * Check to see if this is a mac fork of some kind.
 		 */
 
-		if( is_ntfs_stream_name(fname)) {
-			enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname);
+		if( is_ntfs_stream_name(fname_in)) {
+			enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname_in);
 			if (fake_file_type!=FAKE_FILE_TYPE_NONE) {
 				/*
 				 * Here we go! support for changing the disk quotas --metze
@@ -673,7 +674,7 @@
 				 * xp also tries a QUERY_FILE_INFO on the file and then close it
 				 */
 				reply_ntcreate_and_X_quota(conn, req,
-							  fake_file_type, fname);
+							  fake_file_type, fname_in);
 			} else {
 				reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
 			}
@@ -686,7 +687,7 @@
 	 * Now contruct the smb_open_mode value from the filename, 
 	 * desired access and the share access.
 	 */
-	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname);
+	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -707,17 +708,17 @@
 	/*
 	 * Ordinary file or directory.
 	 */
-		
+
 	/*
 	 * Check if POSIX semantics are wanted.
 	 */
-		
+
 	if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
 		case_state = set_posix_case_semantics(NULL, conn);
 		file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
 	}
-		
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(case_state);
 		reply_nterror(req, status);
@@ -1200,7 +1201,7 @@
 		}
 		offset += next_offset;
 	}
-                                                                                                                             
+
 	return ea_list_head;
 }
 
@@ -1215,7 +1216,8 @@
 				    char **ppdata, uint32 data_count,
 				    uint32 max_data_count)
 {
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	char *params = *ppparams;
 	char *data = *ppdata;
 	/* Breakout the oplock request bits so we can set the reply bits separately. */
@@ -1334,8 +1336,8 @@
 		}
 
 		if(!dir_fsp->is_directory) {
-			srvstr_get_path(params, req->flags2, fname,
-					params+53, sizeof(fname),
+			srvstr_get_path(params, req->flags2, fname_in,
+					params+53, sizeof(fname_in),
 					parameter_count-53, STR_TERMINATE,
 					&status);
 			if (!NT_STATUS_IS_OK(status)) {
@@ -1347,7 +1349,7 @@
 			 * Check to see if this is a mac fork of some kind.
 			 */
 
-			if( is_ntfs_stream_name(fname)) {
+			if( is_ntfs_stream_name(fname_in)) {
 				reply_nterror(req,
 					      NT_STATUS_OBJECT_PATH_NOT_FOUND);
 				return;
@@ -1361,15 +1363,15 @@
 		 * Copy in the base directory name.
 		 */
 
-		pstrcpy( fname, dir_fsp->fsp_name );
-		dir_name_len = strlen(fname);
+		pstrcpy( fname_in, dir_fsp->fsp_name );
+		dir_name_len = strlen(fname_in);
 
 		/*
 		 * Ensure it ends in a '\'.
 		 */
 
-		if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
-			pstrcat(fname, "/");
+		if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) {
+			pstrcat(fname_in, "/");
 			dir_name_len++;
 		}
 
@@ -1383,11 +1385,11 @@
 				reply_nterror(req, status);
 				return;
 			}
-			pstrcat(fname, tmpname);
+			pstrcat(fname_in, tmpname);
 		}
 	} else {
-		srvstr_get_path(params, req->flags2, fname, params+53,
-				sizeof(fname), parameter_count-53,
+		srvstr_get_path(params, req->flags2, fname_in, params+53,
+				sizeof(fname_in), parameter_count-53,
 				STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			reply_nterror(req, status);
@@ -1398,7 +1400,7 @@
 		 * Check to see if this is a mac fork of some kind.
 		 */
 
-		if( is_ntfs_stream_name(fname)) {
+		if( is_ntfs_stream_name(fname_in)) {
 			reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
 			return;
 		}
@@ -1412,7 +1414,7 @@
 	/*
 	 * Ordinary file or directory.
 	 */
-		
+
 	/*
 	 * Check if POSIX semantics are wanted.
 	 */
@@ -1421,9 +1423,9 @@
 		case_state = set_posix_case_semantics(NULL, conn);
 		file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
 	}
-		
+
 	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 fname);
+				 fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(case_state);
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -1435,7 +1437,7 @@
 		return;
 	}
 
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(case_state);
 		reply_nterror(req, status);
@@ -1776,11 +1778,15 @@
 
 static NTSTATUS copy_internals(connection_struct *conn,
 			       struct smb_request *req,
-			       char *oldname, char *newname, uint32 attrs)
+			       const char *oldname_in,
+			       const char *newname_in,
+			       uint32 attrs)
 {
 	SMB_STRUCT_STAT sbuf1, sbuf2;
-	pstring last_component_oldname;
-	pstring last_component_newname;
+	char *oldname = NULL;
+	char *newname = NULL;
+	char *last_component_oldname = NULL;
+	char *last_component_newname = NULL;
 	files_struct *fsp1,*fsp2;
 	uint32 fattr;
 	int info;
@@ -1794,7 +1800,8 @@
 		return NT_STATUS_MEDIA_WRITE_PROTECTED;
 	}
 
-	status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+	status = unix_convert(conn, oldname_in, False, &oldname,
+			&last_component_oldname, &sbuf1);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -1814,7 +1821,8 @@
 		return NT_STATUS_NO_SUCH_FILE;
 	}
 
-	status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+	status = unix_convert(conn, newname_in, False, &newname,
+			&last_component_newname, &sbuf2);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -1840,7 +1848,8 @@
 		return status;
 	}
 
-	DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
+	DEBUG(10,("copy_internals: doing file copy %s to %s\n",
+				oldname, newname));
 
         status = open_file_ntcreate(conn, req, oldname, &sbuf1,
 			FILE_READ_DATA, /* Read-only. */
Index: smbd/reply.c
===================================================================
--- smbd/reply.c	(revision 24984)
+++ smbd/reply.c	(working copy)
@@ -809,14 +809,15 @@
 
 void reply_checkpath(connection_struct *conn, struct smb_request *req)
 {
-	pstring name;
+	pstring name_in;
+	char *name = NULL;
 	SMB_STRUCT_STAT sbuf;
 	NTSTATUS status;
 
 	START_PROFILE(SMBcheckpath);
 
-	srvstr_get_path((char *)req->inbuf, req->flags2, name,
-			smb_buf(req->inbuf) + 1, sizeof(name), 0,
+	srvstr_get_path((char *)req->inbuf, req->flags2, name_in,
+			smb_buf(req->inbuf) + 1, sizeof(name_in), 0,
 			STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		status = map_checkpath_error((char *)req->inbuf, status);
@@ -825,7 +826,7 @@
 		return;
 	}
 
-	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
+	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -836,9 +837,9 @@
 		goto path_err;
 	}
 
-	DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
+	DEBUG(3,("reply_checkpath %s mode=%d\n", name_in, (int)SVAL(req->inbuf,smb_vwv0)));
 
-	status = unix_convert(conn, name, False, NULL, &sbuf);
+	status = unix_convert(conn, name_in, False, &name, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto path_err;
 	}
@@ -899,7 +900,8 @@
 
 void reply_getatr(connection_struct *conn, struct smb_request *req)
 {
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	SMB_STRUCT_STAT sbuf;
 	int mode=0;
 	SMB_OFF_T size=0;
@@ -910,8 +912,8 @@
 	START_PROFILE(SMBgetatr);
 
 	p = smb_buf(req->inbuf) + 1;
-	p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
-			     sizeof(fname), 0, STR_TERMINATE, &status);
+	p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p,
+			     sizeof(fname_in), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBgetatr);
@@ -919,7 +921,7 @@
 	}
 
 	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 fname);
+				 fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -934,7 +936,7 @@
   
 	/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
 		under WfWg - weird! */
-	if (*fname == '\0') {
+	if (*fname_in == '\0') {
 		mode = aHIDDEN | aDIR;
 		if (!CAN_WRITE(conn)) {
 			mode |= aRONLY;
@@ -942,7 +944,7 @@
 		size = 0;
 		mtime = 0;
 	} else {
-		status = unix_convert(conn, fname, False, NULL,&sbuf);
+		status = unix_convert(conn, fname_in, False, &fname, NULL,&sbuf);
 		if (!NT_STATUS_IS_OK(status)) {
 			reply_nterror(req, status);
 			END_PROFILE(SMBgetatr);
@@ -997,7 +999,8 @@
 
 void reply_setatr(connection_struct *conn, struct smb_request *req)
 {
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	int mode;
 	time_t mtime;
 	SMB_STRUCT_STAT sbuf;
@@ -1012,8 +1015,8 @@
 	}
 
 	p = smb_buf(req->inbuf) + 1;
-	p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
-			     sizeof(fname), 0, STR_TERMINATE, &status);
+	p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p,
+			     sizeof(fname_in), 0, STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBsetatr);
@@ -1021,7 +1024,7 @@
 	}
 
 	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 fname);
+				 fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -1034,7 +1037,7 @@
 		return;
 	}
   
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBsetatr);
@@ -1147,7 +1150,7 @@
 void reply_search(connection_struct *conn, struct smb_request *req)
 {
 	pstring mask;
-	pstring directory;
+	char *directory = NULL;
 	pstring fname;
 	SMB_OFF_T size;
 	uint32 mode;
@@ -1181,7 +1184,7 @@
 		return;
 	}
 
-	*mask = *directory = *fname = 0;
+	*mask = *fname = 0;
 
 	/* If we were called as SMBffirst then we must expect close. */
 	if(CVAL(req->inbuf,smb_com) == SMBffirst) {
@@ -1225,8 +1228,7 @@
 	if (status_len == 0) {
 		SMB_STRUCT_STAT sbuf;
 
-		pstrcpy(directory,path);
-		nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
+		nt_status = unix_convert(conn, path, True, &directory, NULL, &sbuf);
 		if (!NT_STATUS_IS_OK(nt_status)) {
 			reply_nterror(req, nt_status);
 			END_PROFILE(SMBsearch);
@@ -1243,17 +1245,43 @@
 		p = strrchr_m(directory,'/');
 		if (!p) {
 			pstrcpy(mask,directory);
-			pstrcpy(directory,".");
+			directory = talloc_strdup(talloc_tos(),".");
+			if (!directory) {
+				reply_nterror(req, NT_STATUS_NO_MEMORY);
+				END_PROFILE(SMBsearch);
+				return;
+			}
 		} else {
 			*p = 0;
 			pstrcpy(mask,p+1);
 		}
 
 		if (*directory == '\0') {
-			pstrcpy(directory,".");
+			directory = talloc_strdup(talloc_tos(),".");
+			if (!directory) {
+				reply_nterror(req, NT_STATUS_NO_MEMORY);
+				END_PROFILE(SMBsearch);
+				return;
+			}
 		}
 		memset((char *)status,'\0',21);
 		SCVAL(status,0,(dirtype & 0x1F));
+
+		nt_status = dptr_create(conn,
+					directory,
+					True,
+					expect_close,
+					req->smbpid,
+					mask,
+					mask_contains_wcard,
+					dirtype,
+					&conn->dirptr);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			reply_nterror(req, nt_status);
+			END_PROFILE(SMBsearch);
+			return;
+		}
+		dptr_num = dptr_dnum(conn->dirptr);
 	} else {
 		int status_dirtype;
 
@@ -1263,7 +1291,7 @@
 			dirtype = status_dirtype;
 		}
 
-		conn->dirptr = dptr_fetch(status+12,&dptr_num);      
+		conn->dirptr = dptr_fetch(status+12,&dptr_num);
 		if (!conn->dirptr) {
 			goto SearchEmpty;
 		}
@@ -1274,25 +1302,6 @@
 		 * check from the initial saved string.
 		 */
 		mask_contains_wcard = ms_has_wild(mask);
-	}
-
-	if (status_len == 0) {
-		nt_status = dptr_create(conn,
-					directory,
-					True,
-					expect_close,
-					req->smbpid,
-					mask,
-					mask_contains_wcard,
-					dirtype,
-					&conn->dirptr);
-		if (!NT_STATUS_IS_OK(nt_status)) {
-			reply_nterror(req, nt_status);
-			END_PROFILE(SMBsearch);
-			return;
-		}
-		dptr_num = dptr_dnum(conn->dirptr);
-	} else {
 		dirtype = dptr_attr(dptr_num);
 	}
 
@@ -1393,13 +1402,18 @@
 	/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
 	SSVAL(req->outbuf, smb_flg2,
 	      (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
-	  
-	if ((! *directory) && dptr_path(dptr_num))
-		slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
 
-	DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
+	if (!directory) {
+		directory = dptr_path(dptr_num);
+	}
+
+	DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
 		smb_fn_name(CVAL(req->inbuf,smb_com)),
-		mask, directory, dirtype, numentries, maxentries ) );
+		mask,
+		directory ? directory : "./",
+		dirtype,
+		numentries,
+		maxentries ));
 
 	END_PROFILE(SMBsearch);
 	return;
@@ -1468,7 +1482,8 @@
 
 void reply_open(connection_struct *conn, struct smb_request *req)
 {
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	uint32 fattr=0;
 	SMB_OFF_T size = 0;
 	time_t mtime=0;
@@ -1496,8 +1511,8 @@
 	deny_mode = SVAL(req->inbuf,smb_vwv0);
 	dos_attr = SVAL(req->inbuf,smb_vwv1);
 
-	srvstr_get_path((char *)req->inbuf, req->flags2, fname,
-			smb_buf(req->inbuf)+1, sizeof(fname), 0,
+	srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+			smb_buf(req->inbuf)+1, sizeof(fname_in), 0,
 			STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
@@ -1506,7 +1521,7 @@
 	}
 
 	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 fname);
+				 fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -1519,7 +1534,7 @@
 		return;
 	}
 
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBopen);
@@ -1602,7 +1617,8 @@
 
 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
 {
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	uint16 open_flags;
 	int deny_mode;
 	uint32 smb_attr;
@@ -1658,8 +1674,8 @@
 	}
 
 	/* XXXX we need to handle passed times, sattr and flags */
-	srvstr_get_path((char *)req->inbuf, req->flags2, fname,
-			smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
+	srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+			smb_buf(req->inbuf), sizeof(fname_in), 0, STR_TERMINATE,
 			&status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
@@ -1668,7 +1684,7 @@
 	}
 
 	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 fname);
+				 fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBopenX);
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -1680,7 +1696,7 @@
 		return;
 	}
 
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBopenX);
@@ -1846,7 +1862,8 @@
 
 void reply_mknew(connection_struct *conn, struct smb_request *req)
 {
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	int com;
 	uint32 fattr = 0;
 	struct timespec ts[2];
@@ -1875,8 +1892,8 @@
 			srv_make_unix_date3(req->inbuf + smb_vwv1));
 			/* mtime. */
 
-	srvstr_get_path((char *)req->inbuf, req->flags2, fname,
-                        smb_buf(req->inbuf) + 1, sizeof(fname), 0,
+	srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+                        smb_buf(req->inbuf) + 1, sizeof(fname_in), 0,
 			STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
@@ -1885,7 +1902,7 @@
 	}
 
 	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-			fname);
+			fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		END_PROFILE(SMBcreate);
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -1897,7 +1914,7 @@
 		return;
 	}
 
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBcreate);
@@ -1974,7 +1991,8 @@
 
 void reply_ctemp(connection_struct *conn, struct smb_request *req)
 {
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	uint32 fattr;
 	files_struct *fsp;
 	int oplock_request;
@@ -1994,22 +2012,22 @@
 	fattr = SVAL(req->inbuf,smb_vwv0);
 	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
 
-	srvstr_get_path((char *)req->inbuf, req->flags2, fname,
-			smb_buf(req->inbuf)+1, sizeof(fname), 0, STR_TERMINATE,
+	srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+			smb_buf(req->inbuf)+1, sizeof(fname_in), 0, STR_TERMINATE,
 			&status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBctemp);
 		return;
 	}
-	if (*fname) {
-		pstrcat(fname,"/TMXXXXXX");
+	if (fname_in) {
+		pstrcat(fname_in,"/TMXXXXXX");
 	} else {
-		pstrcat(fname,"TMXXXXXX");
+		pstrcat(fname_in,"TMXXXXXX");
 	}
 
 	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 fname);
+				 fname_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -2022,7 +2040,7 @@
 		return;
 	}
 
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBctemp);
@@ -2266,22 +2284,23 @@
 ****************************************************************************/
 
 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
-			  uint32 dirtype, char *name, BOOL has_wild)
+			  uint32 dirtype, const char *name_in, BOOL has_wild)
 {
 	pstring directory;
 	pstring mask;
+	char *name = NULL;
 	char *p;
 	int count=0;
 	NTSTATUS status = NT_STATUS_OK;
 	SMB_STRUCT_STAT sbuf;
-	
+
 	*directory = *mask = 0;
-	
-	status = unix_convert(conn, name, has_wild, NULL, &sbuf);
+
+	status = unix_convert(conn, name_in, has_wild, &name, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
-	
+
 	p = strrchr_m(name,'/');
 	if (!p) {
 		pstrcpy(directory,".");
@@ -2291,7 +2310,7 @@
 		pstrcpy(directory,name);
 		pstrcpy(mask,p+1);
 	}
-	
+
 	/*
 	 * We should only check the mangled cache
 	 * here if unix_convert failed. This means
@@ -2300,10 +2319,18 @@
 	 * for a possible mangle. This patch from
 	 * Tine Smukavec <valentin.smukavec at hermes.si>.
 	 */
-	
-	if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
-		mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
-	
+
+	if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
+		char *new_mask = NULL;
+		mangle_lookup_name_from_8_3(talloc_tos(),
+				mask,
+				&new_mask,
+				conn->params );
+		if (new_mask) {
+			pstrcpy(mask, new_mask);
+		}
+	}
+
 	if (!has_wild) {
 		pstrcat(directory,"/");
 		pstrcat(directory,mask);
@@ -2326,7 +2353,7 @@
 		struct smb_Dir *dir_hnd = NULL;
 		long offset = 0;
 		const char *dname;
-		
+
 		if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
 			return NT_STATUS_OBJECT_NAME_INVALID;
 		}
@@ -4600,14 +4627,15 @@
 
 void reply_mkdir(connection_struct *conn, struct smb_request *req)
 {
-	pstring directory;
+	pstring directory_in;
+	char *directory = NULL;
 	NTSTATUS status;
 	SMB_STRUCT_STAT sbuf;
 
 	START_PROFILE(SMBmkdir);
  
-	srvstr_get_path((char *)req->inbuf, req->flags2, directory,
-			smb_buf(req->inbuf) + 1, sizeof(directory), 0,
+	srvstr_get_path((char *)req->inbuf, req->flags2, directory_in,
+			smb_buf(req->inbuf) + 1, sizeof(directory_in), 0,
 			STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
@@ -4617,7 +4645,7 @@
 
 	status = resolve_dfspath(conn,
 				 req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 directory);
+				 directory_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -4630,7 +4658,7 @@
 		return;
 	}
 
-	status = unix_convert(conn, directory, False, NULL, &sbuf);
+	status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBmkdir);
@@ -4853,13 +4881,14 @@
 
 void reply_rmdir(connection_struct *conn, struct smb_request *req)
 {
-	pstring directory;
+	pstring directory_in;
+	char *directory = NULL;
 	SMB_STRUCT_STAT sbuf;
 	NTSTATUS status;
 	START_PROFILE(SMBrmdir);
 
-	srvstr_get_path((char *)req->inbuf, req->flags2, directory,
-			smb_buf(req->inbuf) + 1, sizeof(directory), 0,
+	srvstr_get_path((char *)req->inbuf, req->flags2, directory_in,
+			smb_buf(req->inbuf) + 1, sizeof(directory_in), 0,
 			STR_TERMINATE, &status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
@@ -4869,7 +4898,7 @@
 
 	status = resolve_dfspath(conn,
 				 req->flags2 & FLAGS2_DFS_PATHNAMES,
-				 directory);
+				 directory_in);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -4882,7 +4911,8 @@
 		return;
 	}
 
-	status = unix_convert(conn, directory, False, NULL, &sbuf);
+	status = unix_convert(conn, directory_in, False, &directory,
+			NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBrmdir);
@@ -5286,8 +5316,8 @@
 ****************************************************************************/
 
 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
-				pstring name,
-				pstring newname,
+				const char *name_in,
+				const char *newname_in,
 				uint32 attrs,
 				BOOL replace_if_exists,
 				BOOL src_has_wild,
@@ -5295,8 +5325,10 @@
 {
 	pstring directory;
 	pstring mask;
-	pstring last_component_src;
-	pstring last_component_dest;
+	char *last_component_src = NULL;
+	char *last_component_dest = NULL;
+	char *name = NULL;
+	char *newname = NULL;
 	char *p;
 	int count=0;
 	NTSTATUS status = NT_STATUS_OK;
@@ -5311,12 +5343,14 @@
 	ZERO_STRUCT(sbuf1);
 	ZERO_STRUCT(sbuf2);
 
-	status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
+	status = unix_convert(conn, name_in, src_has_wild, &name,
+			&last_component_src, &sbuf1);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
 
-	status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
+	status = unix_convert(conn, newname_in, dest_has_wild, &newname,
+			&last_component_dest, &sbuf2);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -5351,7 +5385,14 @@
 	 */
 
 	if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
-		mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+		char *new_mask = NULL;
+		mangle_lookup_name_from_8_3(talloc_tos(),
+					mask,
+					&new_mask,
+					conn->params );
+		if (new_mask) {
+			pstrcpy(mask, new_mask);
+		}
 	}
 
 	if (!src_has_wild) {
@@ -5365,16 +5406,17 @@
 		/* Add a terminating '/' to the directory name. */
 		pstrcat(directory,"/");
 		pstrcat(directory,mask);
-		
+
 		/* Ensure newname contains a '/' also */
 		if(strrchr_m(newname,'/') == 0) {
-			pstring tmpstr;
-			
-			pstrcpy(tmpstr, "./");
-			pstrcat(tmpstr, newname);
-			pstrcpy(newname, tmpstr);
+			newname = talloc_asprintf(talloc_tos(),
+						"./%s",
+						newname);
+			if (!newname) {
+				return NT_STATUS_NO_MEMORY;
+			}
 		}
-		
+
 		DEBUG(3, ("rename_internals: case_sensitive = %d, "
 			  "case_preserve = %d, short case preserve = %d, "
 			  "directory = %s, newname = %s, "
@@ -5756,9 +5798,12 @@
 
 void reply_copy(connection_struct *conn, struct smb_request *req)
 {
-	pstring name;
+	pstring name_in;
+	char *name = NULL;
+	pstring newname_in;
+	char *newname = NULL;
 	pstring directory;
-	pstring mask,newname;
+	pstring mask;
 	char *p;
 	int count=0;
 	int error = ERRnoaccess;
@@ -5787,16 +5832,16 @@
 	*directory = *mask = 0;
 
 	p = smb_buf(req->inbuf);
-	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p,
-				   sizeof(name), 0, STR_TERMINATE, &status,
+	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, p,
+				   sizeof(name_in), 0, STR_TERMINATE, &status,
 				   &source_has_wild);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBcopy);
 		return;
 	}
-	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p,
-				   sizeof(newname), 0, STR_TERMINATE, &status,
+	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p,
+				   sizeof(newname_in), 0, STR_TERMINATE, &status,
 				   &dest_has_wild);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
@@ -5804,7 +5849,7 @@
 		return;
 	}
    
-	DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
+	DEBUG(3,("reply_copy : %s -> %s\n",name_in,newname_in));
    
 	if (tid2 != conn->cnum) {
 		/* can't currently handle inter share copies XXXX */
@@ -5816,7 +5861,7 @@
 
 	status = resolve_dfspath_wcard(conn,
 				       req->flags2 & FLAGS2_DFS_PATHNAMES,
-				       name, &source_has_wild);
+				       name_in, &source_has_wild);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -5831,7 +5876,7 @@
 
 	status = resolve_dfspath_wcard(conn,
 				       req->flags2 & FLAGS2_DFS_PATHNAMES,
-				       newname, &dest_has_wild);
+				       newname_in, &dest_has_wild);
 	if (!NT_STATUS_IS_OK(status)) {
 		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -5844,14 +5889,14 @@
 		return;
 	}
 
-	status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
+	status = unix_convert(conn, name_in, source_has_wild, &name, NULL, &sbuf1);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBcopy);
 		return;
 	}
 
-	status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
+	status = unix_convert(conn, newname_in, dest_has_wild, &newname, NULL, &sbuf2);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		END_PROFILE(SMBcopy);
@@ -5900,7 +5945,14 @@
 	 */
 
 	if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
-		mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+		char *new_mask = NULL;
+		mangle_lookup_name_from_8_3( talloc_tos(),
+					mask,
+					&new_mask,
+					conn->params );
+		if (new_mask) {
+			pstrcpy(mask, new_mask);
+		}
 	}
 
 	if (!source_has_wild) {
Index: smbd/statcache.c
===================================================================
--- smbd/statcache.c	(revision 24984)
+++ smbd/statcache.c	(working copy)
@@ -2,7 +2,7 @@
    Unix SMB/CIFS implementation.
    stat cache code
    Copyright (C) Andrew Tridgell 1992-2000
-   Copyright (C) Jeremy Allison 1999-2004
+   Copyright (C) Jeremy Allison 1999-2007
    Copyright (C) Andrew Bartlett <abartlet at samba.org> 2003
    Copyright (C) Volker Lendecke 2007
 
@@ -40,7 +40,8 @@
  *
  */
 
-void stat_cache_add( const char *full_orig_name, const char *translated_path,
+void stat_cache_add( const char *full_orig_name,
+		char *translated_path,
 		BOOL case_sensitive)
 {
 	size_t translated_path_length;
@@ -48,9 +49,12 @@
 	char *original_path;
 	size_t original_path_length;
 	size_t sc_size = lp_max_stat_cache_size();
+	char saved_char;
+	TALLOC_CTX *ctx = talloc_tos();
 
-	if (!lp_stat_cache())
+	if (!lp_stat_cache()) {
 		return;
+	}
 
 	if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) {
 		reset_stat_cache();
@@ -73,20 +77,15 @@
 	 * would be a waste.
 	 */
 
-	if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0))
+	if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) {
 		return;
+	}
 
 	/*
 	 * Remove any trailing '/' characters from the
 	 * translated path.
 	 */
 
-	/*
-	 * To save a strdup we don't necessarily 0-terminate the translated
-	 * path in the tdb. Instead, we do it directly after the tdb_fetch in
-	 * stat_cache_lookup.
-	 */
-
 	translated_path_length = strlen(translated_path);
 
 	if(translated_path[translated_path_length-1] == '/') {
@@ -94,9 +93,9 @@
 	}
 
 	if(case_sensitive) {
-		original_path = SMB_STRDUP(full_orig_name);
+		original_path = talloc_strdup(ctx,full_orig_name);
 	} else {
-		original_path = strdup_upper(full_orig_name);
+		original_path = talloc_strdup_upper(ctx,full_orig_name);
 	}
 
 	if (!original_path) {
@@ -118,7 +117,7 @@
 				  (unsigned long)original_path_length,
 				  translated_path,
 				  (unsigned long)translated_path_length));
-			SAFE_FREE(original_path);
+			TALLOC_FREE(original_path);
 			return;
 		}
 
@@ -129,13 +128,17 @@
 		original_path_length = translated_path_length;
 	}
 
+	/* Ensure we're null terminated. */
+	saved_char = translated_path[translated_path_length];
+	translated_path[translated_path_length] = '\0';
+
+	data_val.dsize = translated_path_length + 1;
+	data_val.dptr = (uint8 *)translated_path;
+
 	/*
 	 * New entry or replace old entry.
 	 */
 
-	data_val.dsize = translated_path_length + 1;
-	data_val.dptr = (uint8 *)translated_path;
-
 	if (tdb_store_bystring(tdb_stat_cache, original_path, data_val,
 				TDB_REPLACE) != 0) {
 		DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n",
@@ -148,7 +151,8 @@
 			translated_path));
 	}
 
-	SAFE_FREE(original_path);
+	translated_path[translated_path_length] = saved_char;
+	TALLOC_FREE(original_path);
 }
 
 /**
@@ -157,8 +161,10 @@
  * @param conn    A connection struct to do the stat() with.
  * @param name    The path we are attempting to cache, modified by this routine
  *                to be correct as far as the cache can tell us. We assume that
- *		  it is a malloc'ed string, we free it if necessary.
- * @param dirpath The path as far as the stat cache told us.
+ *		  it is a talloc'ed string from top of stack, we free it if
+ *		  necessary.
+ * @param dirpath The path as far as the stat cache told us. Also talloced
+ * 		  from top of stack.
  * @param start   A pointer into name, for where to 'start' in fixing the rest
  * 		  of the name up.
  * @param psd     A stat buffer, NOT from the cache, but just a side-effect.
@@ -168,8 +174,11 @@
  *
  */
 
-BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
-		       char **start, SMB_STRUCT_STAT *pst)
+BOOL stat_cache_lookup(connection_struct *conn,
+			char **pp_name,
+			char **pp_dirpath,
+			char **pp_start,
+			SMB_STRUCT_STAT *pst)
 {
 	char *chk_name;
 	size_t namelen;
@@ -179,15 +188,18 @@
 	size_t translated_path_length;
 	TDB_DATA data_val;
 	char *name;
+	TALLOC_CTX *ctx = talloc_tos();
 
-	if (!lp_stat_cache())
+	*pp_dirpath = NULL;
+	*pp_start = *pp_name;
+
+	if (!lp_stat_cache()) {
 		return False;
+	}
 
-	name = *pname;
+	name = *pp_name;
 	namelen = strlen(name);
 
-	*start = name;
-
 	DO_PROFILE_INC(statcache_lookups);
 
 	/*
@@ -198,14 +210,14 @@
 	}
 
 	if (conn->case_sensitive) {
-		chk_name = SMB_STRDUP(name);
+		chk_name = talloc_strdup(ctx,name);
 		if (!chk_name) {
 			DEBUG(0, ("stat_cache_lookup: strdup failed!\n"));
 			return False;
 		}
 
 	} else {
-		chk_name = strdup_upper(name);
+		chk_name = talloc_strdup_upper(ctx,name);
 		if (!chk_name) {
 			DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n"));
 			return False;
@@ -216,8 +228,9 @@
 		 * if we uppercase. We need to treat this differently
 		 * below.
 		 */
-		if (strlen(chk_name) != namelen)
+		if (strlen(chk_name) != namelen) {
 			sizechanged = True;
+		}
 	}
 
 	while (1) {
@@ -239,7 +252,7 @@
 			 * We reached the end of the name - no match.
 			 */
 			DO_PROFILE_INC(statcache_misses);
-			SAFE_FREE(chk_name);
+			TALLOC_FREE(chk_name);
 			return False;
 		}
 
@@ -249,26 +262,26 @@
 		 * Count the number of times we have done this, we'll
 		 * need it when reconstructing the string.
 		 */
-		if (sizechanged)
+
+		if (sizechanged) {
 			num_components++;
+		}
 
 		if ((*chk_name == '\0')
 		    || ISDOT(chk_name) || ISDOTDOT(chk_name)) {
 			DO_PROFILE_INC(statcache_misses);
-			SAFE_FREE(chk_name);
+			TALLOC_FREE(chk_name);
 			return False;
 		}
 	}
 
-	translated_path = (char *)data_val.dptr;
+	translated_path = talloc_strdup(ctx,(char *)data_val.dptr);
+	if (!translated_path) {
+		smb_panic("talloc failed");
+	}
 	translated_path_length = data_val.dsize - 1;
+	SAFE_FREE(data_val.dptr);
 
-	/*
-	 * In stat_cache_add we did not necessarily 0-terminate the translated
-	 * path. Do it here, where we do have a freshly malloc'ed blob.
-	 */
-	translated_path[translated_path_length] = '\0';
-
 	DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] "
 		  "-> [%s]\n", chk_name, translated_path ));
 	DO_PROFILE_INC(statcache_hits);
@@ -276,50 +289,51 @@
 	if (SMB_VFS_STAT(conn, translated_path, pst) != 0) {
 		/* Discard this entry - it doesn't exist in the filesystem. */
 		tdb_delete_bystring(tdb_stat_cache, chk_name);
-		SAFE_FREE(chk_name);
-		SAFE_FREE(data_val.dptr);
+		TALLOC_FREE(chk_name);
+		TALLOC_FREE(translated_path);
 		return False;
 	}
 
 	if (!sizechanged) {
-		memcpy(name, translated_path,
+		memcpy(*pp_name, translated_path,
 		       MIN(namelen, translated_path_length));
-	}
-	else {
+	} else {
 		if (num_components == 0) {
-			name = SMB_STRNDUP(translated_path,
+			name = talloc_strndup(ctx, translated_path,
 					   translated_path_length);
 		} else {
 			char *sp;
 
 			sp = strnrchr_m(name, '/', num_components);
 			if (sp) {
-				asprintf(&name, "%.*s%s",
+				name = talloc_asprintf(ctx,"%.*s%s",
 					 (int)translated_path_length,
 					 translated_path, sp);
 			} else {
-				name = SMB_STRNDUP(translated_path,
-						   translated_path_length);
+				name = talloc_strndup(ctx,
+						translated_path,
+						translated_path_length);
 			}
 		}
 		if (name == NULL) {
 			/*
 			 * TODO: Get us out of here with a real error message
 			 */
-			smb_panic("malloc failed");
+			smb_panic("talloc failed");
 		}
-		SAFE_FREE(*pname);
-		*pname = name;
+		TALLOC_FREE(*pp_name);
+		*pp_name = name;
 	}
 
 
 	/* set pointer for 'where to start' on fixing the rest of the name */
-	*start = &name[translated_path_length];
-	if (**start == '/')
-		++*start;
+	*pp_start = &name[translated_path_length];
+	if (**pp_start == '/') {
+		++*pp_start;
+	}
 
-	*dirpath = translated_path;
-	SAFE_FREE(chk_name);
+	*pp_dirpath = translated_path;
+	TALLOC_FREE(chk_name);
 	return (namelen == translated_path_length);
 }
 
@@ -344,7 +358,7 @@
 
 void stat_cache_delete(const char *name)
 {
-	char *lname = strdup_upper(name);
+	char *lname = talloc_strdup_upper(talloc_tos(), name);
 
 	if (!lname) {
 		return;
@@ -353,7 +367,7 @@
 			lname, name ));
 
 	tdb_delete_bystring(tdb_stat_cache, lname);
-	SAFE_FREE(lname);
+	TALLOC_FREE(lname);
 }
 
 /***************************************************************
Index: smbd/mangle.c
===================================================================
--- smbd/mangle.c	(revision 24984)
+++ smbd/mangle.c	(working copy)
@@ -1,18 +1,18 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    Name mangling interface
    Copyright (C) Andrew Tridgell 2002
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -100,50 +100,51 @@
 	return mangle_fns->is_8_3(fname, check_case, True, p);
 }
 
+BOOL mangle_must_mangle(const char *fname,
+		   const struct share_params *p)
+{
+	if (!lp_manglednames(p)) {
+		return False;
+	}
+	return mangle_fns->must_mangle(fname, p);
+}
+
 /*
-  try to reverse map a 8.3 name to the original filename. This doesn't have to 
+  try to reverse map a 8.3 name to the original filename. This doesn't have to
   always succeed, as the directory handling code in smbd will scan the directory
   looking for a matching name if it doesn't. It should succeed most of the time
   or there will be a huge performance penalty
 */
-BOOL mangle_check_cache(char *s, size_t maxlen,
+BOOL mangle_lookup_name_from_8_3(TALLOC_CTX *ctx,
+			const char *in,
+			char **out, /* talloced on the given context. */
 			const struct share_params *p)
 {
-	return mangle_fns->check_cache(s, maxlen, p);
+	return mangle_fns->lookup_name_from_8_3(ctx, in, out, p);
 }
 
-BOOL mangle_check_cache_alloc(const char *name, char **presult,
-			      const struct share_params *p)
-{
-	pstring tmp;
-	char *result;
-	pstrcpy(tmp, name);
-
-	if (!mangle_check_cache(tmp, sizeof(pstring)-1, p)
-	    || !(result = SMB_STRDUP(tmp))) {
-		return False;
-	}
-	*presult = result;
-	return True;
-}
-
-/* 
-   map a long filename to a 8.3 name. 
+/*
+   mangle a long filename to a 8.3 name.
+   Return True if we did mangle the name (ie. out is filled in).
+   False on error.
+   JRA.
  */
 
-void mangle_map(pstring OutName, BOOL need83, BOOL cache83,
+BOOL name_to_8_3(const char *in,
+		char out[13],
+		BOOL cache83,
 		const struct share_params *p)
 {
 	/* name mangling can be disabled for speed, in which case
 	   we just truncate the string */
 	if (!lp_manglednames(p)) {
-		if (need83) {
-			string_truncate(OutName, 12);
-		}
-		return;
+		safe_strcpy(out,in,12);
+		return True;
 	}
 
-	/* invoke the inane "mangled map" code */
-	mangle_map_filename(OutName, p);
-	mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p);
+	return mangle_fns->name_to_8_3(in,
+				out,
+				cache83,
+				lp_defaultcase(p->service),
+				p);
 }
Index: smbd/trans2.c
===================================================================
--- smbd/trans2.c	(revision 24984)
+++ smbd/trans2.c	(working copy)
@@ -783,7 +783,8 @@
 	int open_ofun;
 	uint32 open_size;
 	char *pname;
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	SMB_OFF_T size=0;
 	int fattr=0,mtime=0;
 	SMB_INO_T inode = 0;
@@ -829,8 +830,8 @@
 		return;
 	}
 
-	srvstr_get_path(params, req->flags2, fname, pname,
-			sizeof(fname), total_params - 28, STR_TERMINATE,
+	srvstr_get_path(params, req->flags2, fname_in, pname,
+			sizeof(fname_in), total_params - 28, STR_TERMINATE,
 			&status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
@@ -843,7 +844,7 @@
 
 	/* XXXX we need to handle passed times, sattr and flags */
 
-	status = unix_convert(conn, fname, False, NULL, &sbuf);
+	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		return;
@@ -1163,6 +1164,7 @@
 	uint32 nt_extmode; /* Used for NT connections instead of mode */
 	BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
 	BOOL check_mangled_names = lp_manglednames(conn->params);
+	char mangled_name[13]; /* mangled 8.3 name. */
 
 	*fname = 0;
 	*out_of_space = False;
@@ -1215,10 +1217,15 @@
 		 * pathreal which is composed from dname.
 		 */
 
-		pstrcpy(fname,dname);      
+		pstrcpy(fname,dname);
 
-		/* This will mangle fname if it's an illegal name. */
-		mangle_map(fname,False,True,conn->params);
+		/* Mangle fname if it's an illegal name. */
+		if (mangle_must_mangle(fname,conn->params)) {
+			if (!name_to_8_3(fname,mangled_name,True,conn->params)) {
+				continue; /* Error - couldn't mangle. */
+			}
+			pstrcpy(fname,mangled_name);
+		}
 
 		if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
 			got_match = mask_match(fname, mask, conn->case_sensitive);
@@ -1226,19 +1233,17 @@
 
 		if(!got_match && check_mangled_names &&
 		   !mangle_is_8_3(fname, False, conn->params)) {
-			pstring mangled_name;
-
 			/*
 			 * It turns out that NT matches wildcards against
 			 * both long *and* short names. This may explain some
 			 * of the wildcard wierdness from old DOS clients
 			 * that some people have been seeing.... JRA.
 			 */
+			/* Force the mangling into 8.3. */
+			if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
+				continue; /* Error - couldn't mangle. */
+			}
 
-			pstrcpy(mangled_name, fname);
-
-			/* Force the mangling into 8.3. */
-			mangle_map( mangled_name, True, False, conn->params);
 			if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
 				got_match = mask_match(mangled_name, mask, conn->case_sensitive);
 			}
@@ -1483,10 +1488,11 @@
 			 * a Win2k client bug. JRA.
 			 */
 			if (!was_8_3 && check_mangled_names) {
-				pstring mangled_name;
-				pstrcpy(mangled_name, fname);
-				mangle_map(mangled_name,True,True,
-					   conn->params);
+				if (!name_to_8_3(fname,mangled_name,True,
+						   conn->params)) {
+					/* Error - mangle failed ! */
+					memset(mangled_name,'\0',12);
+				}
 				mangled_name[12] = 0;
 				len = srvstr_push(base_data, flags2,
 						  p+2, mangled_name, 24,
@@ -1638,10 +1644,11 @@
 			 * a Win2k client bug. JRA.
 			 */
 			if (!was_8_3 && check_mangled_names) {
-				pstring mangled_name;
-				pstrcpy(mangled_name, fname);
-				mangle_map(mangled_name,True,True,
-					   conn->params);
+				if (!name_to_8_3(fname,mangled_name,True,
+						conn->params)) {
+					/* Error - mangle failed ! */
+					memset(mangled_name,'\0',12);
+				}
 				mangled_name[12] = 0;
 				len = srvstr_push(base_data, flags2,
 						  p+2, mangled_name, 24,
@@ -1754,7 +1761,8 @@
 	BOOL close_if_end;
 	BOOL requires_resume_key;
 	int info_level;
-	pstring directory;
+	pstring directory_in;
+	char *directory = NULL;
 	pstring mask;
 	char *p;
 	int last_entry_off=0;
@@ -1784,7 +1792,7 @@
 	requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
 	info_level = SVAL(params,6);
 
-	*directory = *mask = 0;
+	*directory_in = *mask = 0;
 
 	DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
@@ -1819,15 +1827,15 @@
 			return;
 	}
 
-	srvstr_get_path_wcard(params, req->flags2, directory,
-			      params+12, sizeof(directory), total_params - 12,
+	srvstr_get_path_wcard(params, req->flags2, directory_in,
+			      params+12, sizeof(directory_in), total_params - 12,
 			      STR_TERMINATE, &ntstatus, &mask_contains_wcard);
 	if (!NT_STATUS_IS_OK(ntstatus)) {
 		reply_nterror(req, ntstatus);
 		return;
 	}
 
-	ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
+	ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory_in, &mask_contains_wcard);
 	if (!NT_STATUS_IS_OK(ntstatus)) {
 		if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
 			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -1838,7 +1846,7 @@
 		return;
 	}
 
-	ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
+	ntstatus = unix_convert(conn, directory_in, True, &directory, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(ntstatus)) {
 		reply_nterror(req, ntstatus);
 		return;
@@ -1858,7 +1866,11 @@
 		} else {
 			pstrcpy(mask,directory);
 		}
-		pstrcpy(directory,"./");
+		directory = talloc_strdup(talloc_tos(), "./");
+		if (!directory) {
+			reply_nterror(req, NT_STATUS_NO_MEMORY);
+			return;
+		}
 	} else {
 		pstrcpy(mask,p+1);
 		*p = 0;
@@ -2030,14 +2042,18 @@
 	send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
 			    max_data_bytes);
 
-	if ((! *directory) && dptr_path(dptr_num))
-		slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+	if ((! *directory) && dptr_path(dptr_num)) {
+		directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
+		if (!directory) {
+			reply_nterror(req, NT_STATUS_NO_MEMORY);
+		}
+	}
 
 	DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
 		smb_fn_name(CVAL(req->inbuf,smb_com)),
 		mask, directory, dirtype, numentries ) );
 
-	/* 
+	/*
 	 * Force a name mangle here to ensure that the
 	 * mask as an 8.3 name is top of the mangled cache.
 	 * The reasons for this are subtle. Don't remove
@@ -2045,8 +2061,10 @@
 	 * (see PR#13758). JRA.
 	 */
 
-	if(!mangle_is_8_3_wildcards( mask, False, conn->params))
-		mangle_map(mask, True, True, conn->params);
+	if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
+		char mangled_name[13];
+		name_to_8_3(mask, mangled_name, True, conn->params);
+	}
 
 	return;
 }
@@ -2270,14 +2288,20 @@
 
 		long current_pos = 0;
 		/*
-		 * Remember, mangle_map is called by
+		 * Remember, name_to_8_3 is called by
 		 * get_lanman2_dir_entry(), so the resume name
 		 * could be mangled. Ensure we check the unmangled name.
 		 */
 
 		if (mangle_is_mangled(resume_name, conn->params)) {
-			mangle_check_cache(resume_name, sizeof(resume_name)-1,
-					   conn->params);
+			char *new_resume_name = NULL;
+			mangle_lookup_name_from_8_3(talloc_tos(),
+						resume_name,
+						&new_resume_name,
+						conn->params);
+			if (new_resume_name) {
+				pstrcpy(resume_name, new_resume_name);
+			}
 		}
 
 		/*
@@ -3483,7 +3507,8 @@
 	unsigned int data_size = 0;
 	unsigned int param_size = 2;
 	SMB_STRUCT_STAT sbuf;
-	pstring fname, dos_fname;
+	pstring fname_in, dos_fname;
+	char *fname = NULL;
 	char *fullpathname;
 	char *base_name;
 	char *p;
@@ -3535,7 +3560,7 @@
 			 * This is actually for the QUOTA_FAKE_FILE --metze
 			 */
 						
-			pstrcpy(fname, fsp->fsp_name);
+			pstrcpy(fname_in, fsp->fsp_name);
 			/* We know this name is ok, it's already passed the checks. */
 			
 		} else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
@@ -3545,17 +3570,17 @@
 			 * to do this call. JRA.
 			 */
 			/* We know this name is ok, it's already passed the checks. */
-			pstrcpy(fname, fsp->fsp_name);
+			pstrcpy(fname_in, fsp->fsp_name);
 		  
 			if (INFO_LEVEL_IS_UNIX(info_level)) {
 				/* Always do lstat for UNIX calls. */
-				if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
-					DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+				if (SMB_VFS_LSTAT(conn,fname_in,&sbuf)) {
+					DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname_in,strerror(errno)));
 					reply_unixerror(req,ERRDOS,ERRbadpath);
 					return;
 				}
-			} else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
-				DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+			} else if (SMB_VFS_STAT(conn,fname_in,&sbuf)) {
+				DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname_in,strerror(errno)));
 				reply_unixerror(req, ERRDOS, ERRbadpath);
 				return;
 			}
@@ -3570,7 +3595,7 @@
 				return;
 			}
 
-			pstrcpy(fname, fsp->fsp_name);
+			pstrcpy(fname_in, fsp->fsp_name);
 			if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
 				DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
 				reply_unixerror(req, ERRDOS, ERRbadfid);
@@ -3581,6 +3606,12 @@
 			delete_pending = get_delete_on_close_flag(fileid);
 			access_mask = fsp->access_mask;
 		}
+
+		fname = talloc_strdup(talloc_tos(),fname_in);
+		if (!fname) {
+			reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+			return;
+		}
 	} else {
 		NTSTATUS status = NT_STATUS_OK;
 
@@ -3599,8 +3630,8 @@
 			return;
 		}
 
-		srvstr_get_path(params, req->flags2, fname, &params[6],
-				sizeof(fname), total_params - 6,
+		srvstr_get_path(params, req->flags2, fname_in, &params[6],
+				sizeof(fname_in), total_params - 6,
 				STR_TERMINATE, &status);
 		if (!NT_STATUS_IS_OK(status)) {
 			reply_nterror(req, status);
@@ -3609,7 +3640,7 @@
 
 		status = resolve_dfspath(conn,
 					 req->flags2 & FLAGS2_DFS_PATHNAMES,
-					 fname);
+					 fname_in);
 		if (!NT_STATUS_IS_OK(status)) {
 			if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 				reply_botherror(req,
@@ -3620,7 +3651,7 @@
 			return;
 		}
 
-		status = unix_convert(conn, fname, False, NULL, &sbuf);
+		status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 		if (!NT_STATUS_IS_OK(status)) {
 			reply_nterror(req, status);
 			return;
@@ -3962,16 +3993,16 @@
 		case SMB_QUERY_FILE_ALT_NAME_INFO:
 		case SMB_FILE_ALTERNATE_NAME_INFORMATION:
 		{
-			pstring short_name;
-
+			char mangled_name[13];
 			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
-			pstrcpy(short_name,base_name);
-			/* Mangle if not already 8.3 */
-			if(!mangle_is_8_3(short_name, True, conn->params)) {
-				mangle_map(short_name,True,True,conn->params);
+			if (!name_to_8_3(base_name,mangled_name,
+						True,conn->params)) {
+				reply_nterror(
+					req,
+					NT_STATUS_NO_MEMORY);
 			}
 			len = srvstr_push(dstart, req->flags2,
-					  pdata+4, short_name,
+					  pdata+4, mangled_name,
 					  PTR_DIFF(dend, pdata+4),
 					  STR_UNICODE);
 			data_size = 4 + len;
@@ -4395,17 +4426,22 @@
  code.
 ****************************************************************************/
 
-NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
+NTSTATUS hardlink_internals(connection_struct *conn,
+		char *oldname_in,
+		char *newname_in)
 {
 	SMB_STRUCT_STAT sbuf1, sbuf2;
-	pstring last_component_oldname;
-	pstring last_component_newname;
+	char *last_component_oldname = NULL;
+	char *last_component_newname = NULL;
+	char *oldname = NULL;
+	char *newname = NULL;
 	NTSTATUS status = NT_STATUS_OK;
 
 	ZERO_STRUCT(sbuf1);
 	ZERO_STRUCT(sbuf2);
 
-	status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+	status = unix_convert(conn, oldname_in, False, &oldname,
+			&last_component_oldname, &sbuf1);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -4420,7 +4456,8 @@
 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 	}
 
-	status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+	status = unix_convert(conn, newname_in, False, &newname,
+			&last_component_newname, &sbuf2);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
@@ -4882,13 +4919,15 @@
 
 static NTSTATUS smb_file_rename_information(connection_struct *conn,
 					    struct smb_request *req,
-					    const char *pdata, int total_data,
-					    files_struct *fsp, pstring fname)
+					    const char *pdata,
+					    int total_data,
+					    files_struct *fsp,
+					    const char *fname)
 {
 	BOOL overwrite;
 	uint32 root_fid;
 	uint32 len;
-	pstring newname;
+	pstring newname_in;
 	pstring base_name;
 	BOOL dest_has_wcard = False;
 	NTSTATUS status = NT_STATUS_OK;
@@ -4906,8 +4945,8 @@
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12],
-			      sizeof(newname), len, 0, &status,
+	srvstr_get_path_wcard(pdata, req->flags2, newname_in, &pdata[12],
+			      sizeof(newname_in), len, 0, &status,
 			      &dest_has_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
@@ -4915,13 +4954,13 @@
 
 	status = resolve_dfspath_wcard(conn,
 				       req->flags2 & FLAGS2_DFS_PATHNAMES,
-				       newname, &dest_has_wcard);
+				       newname_in, &dest_has_wcard);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
 
 	/* Check the new name has no '/' characters. */
-	if (strchr_m(newname, '/')) {
+	if (strchr_m(newname_in, '/')) {
 		return NT_STATUS_NOT_SUPPORTED;
 	}
 
@@ -4934,16 +4973,19 @@
 		pstrcpy(base_name, "./");
 	}
 	/* Append the new name. */
-	pstrcat(base_name, newname);
+	pstrcat(base_name, newname_in);
 
 	if (fsp) {
 		SMB_STRUCT_STAT sbuf;
-		pstring newname_last_component;
+		char *newname = NULL;
+		char *newname_last_component = NULL;
 
 		ZERO_STRUCT(sbuf);
 
-		status = unix_convert(conn, newname, False,
-				      newname_last_component, &sbuf);
+		status = unix_convert(conn, newname_in, False,
+					&newname,
+					&newname_last_component,
+					&sbuf);
 
 		/* If an error we expect this to be
 		 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
@@ -4961,7 +5003,7 @@
 					      overwrite);
 	} else {
 		DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
-			fname, newname ));
+			fname, base_name ));
 		status = rename_internals(conn, req, fname, base_name, 0,
 					  overwrite, False, dest_has_wcard);
 	}
@@ -6121,7 +6163,8 @@
 	char *pdata = *ppdata;
 	uint16 info_level;
 	SMB_STRUCT_STAT sbuf;
-	pstring fname;
+	pstring fname_in;
+	char *fname = NULL;
 	files_struct *fsp = NULL;
 	NTSTATUS status = NT_STATUS_OK;
 	int data_return_size = 0;
@@ -6148,7 +6191,7 @@
 			 * handle (returned from an NT SMB). NT5.0 seems
 			 * to do this call. JRA.
 			 */
-			pstrcpy(fname, fsp->fsp_name);
+			pstrcpy(fname_in, fsp->fsp_name);
 			if (INFO_LEVEL_IS_UNIX(info_level)) {
 				/* Always do lstat for UNIX calls. */
 				if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
@@ -6177,12 +6220,11 @@
 						    *ppdata, 0,
 						    max_data_bytes);
 				return;
-			}
-			else {
+			} else {
 				reply_unixerror(req, ERRDOS, ERRbadpath);
 				return;
 			}
-	    } else {
+		} else {
 			/*
 			 * Original code - this is an open file.
 			 */
@@ -6190,7 +6232,7 @@
 				return;
 			}
 
-			pstrcpy(fname, fsp->fsp_name);
+			pstrcpy(fname_in, fsp->fsp_name);
 
 			if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
 				DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
@@ -6198,6 +6240,11 @@
 				return;
 			}
 		}
+		fname = talloc_strdup(talloc_tos(),fname_in);
+		if (!fname) {
+			reply_nterror(req, NT_STATUS_NO_MEMORY);
+			return;
+		}
 	} else {
 		/* set path info */
 		if (total_params < 7) {
@@ -6205,9 +6252,9 @@
 			return;
 		}
 
-		info_level = SVAL(params,0);    
-		srvstr_get_path(params, req->flags2, fname, &params[6],
-				sizeof(fname), total_params - 6, STR_TERMINATE,
+		info_level = SVAL(params,0);
+		srvstr_get_path(params, req->flags2, fname_in, &params[6],
+				sizeof(fname_in), total_params - 6, STR_TERMINATE,
 				&status);
 		if (!NT_STATUS_IS_OK(status)) {
 			reply_nterror(req, status);
@@ -6216,7 +6263,7 @@
 
 		status = resolve_dfspath(conn,
 					 req->flags2 & FLAGS2_DFS_PATHNAMES,
-					 fname);
+					 fname_in);
 		if (!NT_STATUS_IS_OK(status)) {
 			if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
 				reply_botherror(req,
@@ -6228,7 +6275,7 @@
 			return;
 		}
 
-		status = unix_convert(conn, fname, False, NULL, &sbuf);
+		status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
 		if (!NT_STATUS_IS_OK(status)) {
 			reply_nterror(req, status);
 			return;
@@ -6550,7 +6597,8 @@
 {
 	char *params = *pparams;
 	char *pdata = *ppdata;
-	pstring directory;
+	pstring directory_in;
+	char *directory = NULL;
 	SMB_STRUCT_STAT sbuf;
 	NTSTATUS status = NT_STATUS_OK;
 	struct ea_list *ea_list = NULL;
@@ -6565,17 +6613,17 @@
 		return;
 	}
 
-	srvstr_get_path(params, req->flags2, directory, &params[4],
-			sizeof(directory), total_params - 4, STR_TERMINATE,
+	srvstr_get_path(params, req->flags2, directory_in, &params[4],
+			sizeof(directory_in), total_params - 4, STR_TERMINATE,
 			&status);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		return;
 	}
 
-	DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
+	DEBUG(3,("call_trans2mkdir : name = %s\n", directory_in));
 
-	status = unix_convert(conn, directory, False, NULL, &sbuf);
+	status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		reply_nterror(req, status);
 		return;
Index: smbd/dir.c
===================================================================
--- smbd/dir.c	(revision 24984)
+++ smbd/dir.c	(working copy)
@@ -380,12 +380,11 @@
  wcard must not be zero.
 ****************************************************************************/
 
-NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
+NTSTATUS dptr_create(connection_struct *conn, const char *path, BOOL old_handle, BOOL expect_close,uint16 spid,
 		const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
 {
 	struct dptr_struct *dptr = NULL;
 	struct smb_Dir *dir_hnd;
-        const char *dir2;
 	NTSTATUS status;
 
 	DEBUG(5,("dptr_create dir=%s\n", path));
@@ -399,17 +398,12 @@
 		return status;
 	}
 
-	/* use a const pointer from here on */
-	dir2 = path;
-	if (!*dir2)
-		dir2 = ".";
-
-	dir_hnd = OpenDir(conn, dir2, wcard, attr);
+	dir_hnd = OpenDir(conn, path, wcard, attr);
 	if (!dir_hnd) {
 		return map_nt_error_from_unix(errno);
 	}
 
-	string_set(&conn->dirpath,dir2);
+	string_set(&conn->dirpath,path);
 
 	if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
 		dptr_idleoldest();
@@ -488,7 +482,7 @@
 
 	dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
 
-	string_set(&dptr->path,dir2);
+	string_set(&dptr->path,path);
 	dptr->conn = conn;
 	dptr->dir_hnd = dir_hnd;
 	dptr->spid = spid;
@@ -758,10 +752,15 @@
 	return True;
 }
 
-static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
+static BOOL mangle_mask_match(connection_struct *conn, const char *filename,
+		char *mask)
 {
-	mangle_map(filename,True,False,conn->params);
-	return mask_match_search(filename,mask,False);
+	char mname[13];
+
+	if (!name_to_8_3(filename,mname,False,conn->params)) {
+		return False;
+	}
+	return mask_match_search(mname,mask,False);
 }
 
 /****************************************************************************
@@ -806,9 +805,14 @@
 		    mask_match_search(filename,mask,False) ||
 		    mangle_mask_match(conn,filename,mask)) {
 
-			if (!mangle_is_8_3(filename, False, conn->params))
-				mangle_map(filename,True,False,
-					   conn->params);
+			if (!mangle_is_8_3(filename, False, conn->params)) {
+				char mname[13];
+				if (!name_to_8_3(filename,mname,False,
+					   conn->params)) {
+					continue;
+				}
+				pstrcpy(filename,mname);
+			}
 
 			pstrcpy(fname,filename);
 			*path = 0;
Index: smbd/filename.c
===================================================================
--- smbd/filename.c	(revision 24984)
+++ smbd/filename.c	(working copy)
@@ -2,7 +2,7 @@
    Unix SMB/CIFS implementation.
    filename handling routines
    Copyright (C) Andrew Tridgell 1992-1998
-   Copyright (C) Jeremy Allison 1999-2004
+   Copyright (C) Jeremy Allison 1999-2007
    Copyright (C) Ying Chen 2000
    Copyright (C) Volker Lendecke 2007
 
@@ -37,11 +37,12 @@
 			const char *name2,
 			const struct share_params *p)
 {
-	pstring tmpname;
+	char mname[13];
 
-	pstrcpy(tmpname, name2);
-	mangle_map(tmpname, True, False, p);
-	return strequal(name1, tmpname);
+	if (!name_to_8_3(name2, mname, False, p)) {
+		return False;
+	}
+	return strequal(name1, mname);
 }
 
 /****************************************************************************
@@ -107,9 +108,10 @@
 ****************************************************************************/
 
 NTSTATUS unix_convert(connection_struct *conn,
-		        pstring orig_path,
+			const char *orig_path,
 			BOOL allow_wcard_last_component,
-			char *saved_last_component,
+			char **pp_conv_path,
+			char **pp_saved_last_component,
 			SMB_STRUCT_STAT *pst)
 {
 	SMB_STRUCT_STAT st;
@@ -119,16 +121,20 @@
 	BOOL component_was_mangled = False;
 	BOOL name_has_wildcard = False;
 	NTSTATUS result;
+	TALLOC_CTX *ctx = talloc_tos();
 
 	SET_STAT_INVALID(*pst);
-
-	if(saved_last_component) {
-		*saved_last_component = 0;
+	*pp_conv_path = NULL;
+	if(pp_saved_last_component) {
+		*pp_saved_last_component = NULL;
 	}
 
 	if (conn->printer) {
 		/* we don't ever use the filenames on a printer share as a
 			filename - so don't convert them */
+		if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) {
+			return NT_STATUS_NO_MEMORY;
+		}
 		return NT_STATUS_OK;
 	}
 
@@ -157,11 +163,13 @@
 	 */
 
 	if (!*orig_path) {
-		if (!(name = SMB_STRDUP("."))) {
+		if (!(name = talloc_strdup(ctx,"."))) {
 			return NT_STATUS_NO_MEMORY;
 		}
 		if (SMB_VFS_STAT(conn,name,&st) == 0) {
 			*pst = st;
+		} else {
+			return map_nt_error_from_unix(errno);
 		}
 		DEBUG(5,("conversion finished \"\" -> %s\n",name));
 		goto done;
@@ -183,17 +191,18 @@
 	 * Ensure saved_last_component is valid even if file exists.
 	 */
 
-	if(saved_last_component) {
+	if(pp_saved_last_component) {
 		end = strrchr_m(orig_path, '/');
 		if (end) {
-			pstrcpy(saved_last_component, end + 1);
+			*pp_saved_last_component = talloc_strdup(ctx, end + 1);
 		} else {
-			pstrcpy(saved_last_component, orig_path);
+			*pp_saved_last_component = talloc_strdup(ctx,
+							orig_path);
 		}
 	}
 
-	if (!(name = SMB_STRDUP(orig_path))) {
-		DEBUG(0, ("strdup failed\n"));
+	if (!(name = talloc_strdup(ctx, orig_path))) {
+		DEBUG(0, ("talloc_strdup failed\n"));
 		return NT_STATUS_NO_MEMORY;
 	}
 
@@ -224,9 +233,9 @@
 	 * building the directories with asprintf and free it.
 	 */
 
-	if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) {
-		DEBUG(0, ("strdup failed\n"));
-		SAFE_FREE(name);
+	if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
+		DEBUG(0, ("talloc_strdup failed\n"));
+		TALLOC_FREE(name);
 		return NT_STATUS_NO_MEMORY;
 	}
 
@@ -264,8 +273,7 @@
 	 */
 
 	if (conn->case_sensitive &&
-			!mangle_is_mangled(name, conn->params) &&
-			!*lp_mangled_map(conn->params)) {
+			!mangle_is_mangled(name, conn->params)) {
 		goto done;
 	}
 
@@ -302,8 +310,14 @@
 			*end = 0;
 		}
 
-		if (saved_last_component != 0) {
-			pstrcpy(saved_last_component, end ? end + 1 : start);
+		if (pp_saved_last_component) {
+			TALLOC_FREE(*pp_saved_last_component);
+			*pp_saved_last_component = talloc_strdup(ctx,
+							end ? end + 1 : start);
+			if (!*pp_saved_last_component) {
+				DEBUG(0, ("talloc failed\n"));
+				return NT_STATUS_NO_MEMORY;
+			}
 		}
 
 		/* The name cannot have a component of "." */
@@ -473,25 +487,27 @@
 				 */
 
 				if (mangle_is_mangled(start, conn->params)
-				    && mangle_check_cache_alloc(start,
-								&unmangled,
-								conn->params)) {
+				    && mangle_lookup_name_from_8_3(ctx,
+					    		start,
+							&unmangled,
+							conn->params)) {
 					char *tmp;
 					size_t start_ofs = start - name;
 
 					if (*dirpath != '\0') {
-						asprintf(&tmp, "%s/%s", dirpath,
-							 unmangled);
-						SAFE_FREE(unmangled);
+						tmp = talloc_asprintf(ctx,
+							"%s/%s", dirpath,
+							unmangled);
+						TALLOC_FREE(unmangled);
 					}
 					else {
 						tmp = unmangled;
 					}
 					if (tmp == NULL) {
-						DEBUG(0, ("malloc failed\n"));
-						result = NT_STATUS_NO_MEMORY;
+						DEBUG(0, ("talloc failed\n"));
+						return NT_STATUS_NO_MEMORY;
 					}
-					SAFE_FREE(name);
+					TALLOC_FREE(name);
 					name = tmp;
 					start = name + start_ofs;
 					end = start + strlen(start);
@@ -511,18 +527,20 @@
 				size_t start_ofs = start - name;
 
 				if (*dirpath != '\0') {
-					asprintf(&tmp, "%s/%s/%s", dirpath,
-						 found_name, end+1);
+					tmp = talloc_asprintf(ctx,
+						"%s/%s/%s", dirpath,
+						found_name, end+1);
 				}
 				else {
-					asprintf(&tmp, "%s/%s", found_name,
-						 end+1);
+					tmp = talloc_asprintf(ctx,
+						"%s/%s", found_name,
+						end+1);
 				}
 				if (tmp == NULL) {
-					DEBUG(0, ("asprintf failed\n"));
-					result = NT_STATUS_NO_MEMORY;
+					DEBUG(0, ("talloc_asprintf failed\n"));
+					return NT_STATUS_NO_MEMORY;
 				}
-				SAFE_FREE(name);
+				TALLOC_FREE(name);
 				name = tmp;
 				start = name + start_ofs;
 				end = start + strlen(found_name);
@@ -532,18 +550,19 @@
 				size_t start_ofs = start - name;
 
 				if (*dirpath != '\0') {
-					asprintf(&tmp, "%s/%s", dirpath,
-						 found_name);
+					tmp = talloc_asprintf(ctx,
+						"%s/%s", dirpath,
+						found_name);
 				}
 				else {
-					tmp = SMB_STRDUP(found_name);
+					tmp = talloc_strdup(ctx,
+						found_name);
 				}
 				if (tmp == NULL) {
-					DEBUG(0, ("malloc failed\n"));
-					result = NT_STATUS_NO_MEMORY;
-					goto fail;
+					DEBUG(0, ("talloc failed\n"));
+					return NT_STATUS_NO_MEMORY;
 				}
-				SAFE_FREE(name);
+				TALLOC_FREE(name);
 				name = tmp;
 				start = name + start_ofs;
 
@@ -560,7 +579,7 @@
 				}
 			}
 
-			SAFE_FREE(found_name);
+			TALLOC_FREE(found_name);
 		} /* end else */
 
 #ifdef DEVELOPER
@@ -577,19 +596,19 @@
 		 */
 
 		if (*dirpath != '\0') {
-			char *tmp;
-
-			if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) {
-				DEBUG(0, ("asprintf failed\n"));
+			char *tmp = talloc_asprintf(ctx,
+					"%s/%s", dirpath, start);
+			if (!tmp) {
+				DEBUG(0, ("talloc_asprintf failed\n"));
 				return NT_STATUS_NO_MEMORY;
 			}
-			SAFE_FREE(dirpath);
+			TALLOC_FREE(dirpath);
 			dirpath = tmp;
 		}
 		else {
-			SAFE_FREE(dirpath);
-			if (!(dirpath = SMB_STRDUP(start))) {
-				DEBUG(0, ("strdup failed\n"));
+			TALLOC_FREE(dirpath);
+			if (!(dirpath = talloc_strdup(ctx,start))) {
+				DEBUG(0, ("talloc_strdup failed\n"));
 				return NT_STATUS_NO_MEMORY;
 			}
 		}
@@ -628,17 +647,19 @@
 	DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
 
  done:
-	pstrcpy(orig_path, name);
-	SAFE_FREE(name);
-	SAFE_FREE(dirpath);
+	*pp_conv_path = name;
+	TALLOC_FREE(dirpath);
 	return NT_STATUS_OK;
  fail:
 	DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
-	pstrcpy(orig_path, dirpath);
-	pstrcat(orig_path, "/");
-	pstrcat(orig_path, start);
-	SAFE_FREE(name);
-	SAFE_FREE(dirpath);
+	*pp_conv_path = talloc_asprintf(ctx,
+			"%s/%s", dirpath, start);
+	if (!*pp_conv_path) {
+		DEBUG(0, ("talloc_asprintf failed\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+	TALLOC_FREE(name);
+	TALLOC_FREE(dirpath);
 	return result;
 }
 
@@ -649,7 +670,7 @@
  a valid one for the user to access.
 ****************************************************************************/
 
-NTSTATUS check_name(connection_struct *conn, const pstring name)
+NTSTATUS check_name(connection_struct *conn, const char *name)
 {
 	if (IS_VETO_PATH(conn, name))  {
 		/* Is it not dot or dot dot. */
@@ -682,8 +703,9 @@
 		BOOL case_sensitive)
 {
 	/* Normal filename handling */
-	if (case_sensitive)
+	if (case_sensitive) {
 		return(strcmp(name1,name2) == 0);
+	}
 
 	return(strequal(name1,name2));
 }
@@ -701,17 +723,19 @@
 	BOOL mangled;
 	char *unmangled_name = NULL;
 	long curpos;
+	TALLOC_CTX *ctx = talloc_tos();
 
 	mangled = mangle_is_mangled(name, conn->params);
 
 	/* handle null paths */
-	if ((path == NULL) || (*path == 0))
+	if ((path == NULL) || (*path == 0)) {
 		path = ".";
+	}
 
 	/*
 	 * The incoming name can be mangled, and if we de-mangle it
 	 * here it will not compare correctly against the filename (name2)
-	 * read from the directory and then mangled by the mangle_map()
+	 * read from the directory and then mangled by the name_to_8_3()
 	 * call. We need to mangle both names or neither.
 	 * (JRA).
 	 *
@@ -724,15 +748,19 @@
 	 */
 
 	if (mangled && !conn->case_sensitive) {
-		mangled = !mangle_check_cache_alloc(name, &unmangled_name,
-						    conn->params);
-		name = unmangled_name;
+		mangled = !mangle_lookup_name_from_8_3(ctx,
+						name,
+						&unmangled_name,
+						conn->params);
+		if (mangled) {
+			name = unmangled_name;
+		}
 	}
 
 	/* open the directory */
 	if (!(cur_dir = OpenDir(conn, path, NULL, 0))) {
 		DEBUG(3,("scan dir didn't open dir [%s]\n",path));
-		SAFE_FREE(unmangled_name);
+		TALLOC_FREE(unmangled_name);
 		return(False);
 	}
 
@@ -741,8 +769,7 @@
 	while ((dname = ReadDirName(cur_dir, &curpos))) {
 
 		/* Is it dot or dot dot. */
-		if ((dname[0] == '.') && (!dname[1] ||
-					(dname[1] == '.' && !dname[2]))) {
+		if (ISDOT(dname) || ISDOTDOT(dname)) {
 			continue;
 		}
 
@@ -760,15 +787,19 @@
 		if ((mangled && mangled_equal(name,dname,conn->params)) ||
 			fname_equal(name, dname, conn->case_sensitive)) {
 			/* we've found the file, change it's name and return */
-			*found_name = SMB_STRDUP(dname);
-			SAFE_FREE(unmangled_name);
+			*found_name = talloc_strdup(ctx,dname);
+			TALLOC_FREE(unmangled_name);
 			CloseDir(cur_dir);
+			if (!*found_name) {
+				errno = ENOMEM;
+				return False;
+			}
 			return(True);
 		}
 	}
 
-	SAFE_FREE(unmangled_name);
+	TALLOC_FREE(unmangled_name);
 	CloseDir(cur_dir);
 	errno = ENOENT;
-	return(False);
+	return False;
 }
Index: printing/nt_printing.c
===================================================================
--- printing/nt_printing.c	(revision 24984)
+++ printing/nt_printing.c	(working copy)
@@ -659,13 +659,18 @@
  Function to allow filename parsing "the old way".
 ********************************************************************/
 
-static void driver_unix_convert(char *name,connection_struct *conn,
-		char *saved_last_component, SMB_STRUCT_STAT *pst)
+static void driver_unix_convert(connection_struct *conn,
+		pstring name,
+		SMB_STRUCT_STAT *pst)
 {
+	char *new_name = NULL;
 	unix_format(name);
 	unix_clean_name(name);
 	trim_string(name,"/","/");
-	unix_convert(conn, name, False, saved_last_component, pst);
+	unix_convert(conn, name, False, &new_name, NULL, pst);
+	if (new_name) {
+		pstrcpy(name, new_name);
+	}
 }
 
 /*******************************************************************
@@ -1288,7 +1293,7 @@
 	/* Get file version info (if available) for previous file (if it exists) */
 	pstrcpy(filepath, old_file);
 
-	driver_unix_convert(filepath,conn,NULL,&stat_buf);
+	driver_unix_convert(conn,filepath,&stat_buf);
 
 	status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
 				FILE_GENERIC_READ,
@@ -1324,7 +1329,7 @@
 
 	/* Get file version info (if available) for new file */
 	pstrcpy(filepath, new_file);
-	driver_unix_convert(filepath,conn,NULL,&stat_buf);
+	driver_unix_convert(conn,filepath,&stat_buf);
 
 	status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
 				FILE_GENERIC_READ,
@@ -1452,7 +1457,7 @@
 	 * deriver the cversion. */
 	slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
 
-	driver_unix_convert(driverpath,conn,NULL,&st);
+	driver_unix_convert(conn,driverpath,&st);
 
 	if ( !vfs_file_exist( conn, driverpath, &st ) ) {
 		*perr = WERR_BADFILE;
@@ -1793,7 +1798,7 @@
 	 */
 	DEBUG(5,("Creating first directory\n"));
 	slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
-	driver_unix_convert(new_dir, conn, NULL, &st);
+	driver_unix_convert(conn,new_dir,&st);
 	create_directory(conn, new_dir);
 
 	/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
@@ -1819,7 +1824,7 @@
 		slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);	
 		slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);	
 		if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-			driver_unix_convert(new_name, conn, NULL, &st);
+			driver_unix_convert(conn,new_name,&st);
 			if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
 						OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
 				DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1835,7 +1840,7 @@
 			slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);	
 			slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);	
 			if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-				driver_unix_convert(new_name, conn, NULL, &st);
+				driver_unix_convert(conn,new_name,&st);
 				if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
 						OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
 					DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1853,7 +1858,7 @@
 			slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);	
 			slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);	
 			if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-				driver_unix_convert(new_name, conn, NULL, &st);
+				driver_unix_convert(conn,new_name,&st);
 				if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
 						OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
 					DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1872,7 +1877,7 @@
 			slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);	
 			slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);	
 			if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-				driver_unix_convert(new_name, conn, NULL, &st);
+				driver_unix_convert(conn,new_name,&st);
 				if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
 						OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
 					DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -1900,7 +1905,7 @@
 				slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);	
 				slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);	
 				if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
-					driver_unix_convert(new_name, conn, NULL, &st);
+					driver_unix_convert(conn,new_name,&st);
 					if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
 							OPENX_FILE_EXISTS_TRUNCATE|
 							OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
@@ -4938,7 +4943,7 @@
 	if ( *info_3->driverpath ) {
 		if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
 			pstrcpy( file, s );
-			driver_unix_convert(file, conn, NULL, &st);
+			driver_unix_convert(conn,file,&st);
 			DEBUG(10,("deleting driverfile [%s]\n", s));
 			unlink_internals(conn, NULL, 0, file, False);
 		}
@@ -4947,7 +4952,7 @@
 	if ( *info_3->configfile ) {
 		if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
 			pstrcpy( file, s );
-			driver_unix_convert(file, conn, NULL, &st);
+			driver_unix_convert(conn,file,&st);
 			DEBUG(10,("deleting configfile [%s]\n", s));
 			unlink_internals(conn, NULL, 0, file, False);
 		}
@@ -4956,7 +4961,7 @@
 	if ( *info_3->datafile ) {
 		if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
 			pstrcpy( file, s );
-			driver_unix_convert(file, conn, NULL, &st);
+			driver_unix_convert(conn,file,&st);
 			DEBUG(10,("deleting datafile [%s]\n", s));
 			unlink_internals(conn, NULL, 0, file, False);
 		}
@@ -4965,7 +4970,7 @@
 	if ( *info_3->helpfile ) {
 		if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
 			pstrcpy( file, s );
-			driver_unix_convert(file, conn, NULL, &st);
+			driver_unix_convert(conn,file,&st);
 			DEBUG(10,("deleting helpfile [%s]\n", s));
 			unlink_internals(conn, NULL, 0, file, False);
 		}
@@ -4981,7 +4986,7 @@
 			
 			if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
 				pstrcpy( file, p );
-				driver_unix_convert(file, conn, NULL, &st);
+				driver_unix_convert(conn,file,&st);
 				DEBUG(10,("deleting dependent file [%s]\n", file));
 				unlink_internals(conn, NULL, 0, file, False);
 			}
Index: param/loadparm.c
===================================================================
--- param/loadparm.c	(revision 24984)
+++ param/loadparm.c	(working copy)
@@ -370,7 +370,6 @@
 	char **szHostsdeny;
 	char *szMagicScript;
 	char *szMagicOutput;
-	char *szMangledMap;
 	char *szVetoFiles;
 	char *szHideFiles;
 	char *szVetoOplockFiles;
@@ -511,7 +510,6 @@
 	NULL,			/* szHostsdeny */
 	NULL,			/* szMagicScript */
 	NULL,			/* szMagicOutput */
-	NULL,			/* szMangledMap */
 	NULL,			/* szVetoFiles */
 	NULL,			/* szHideFiles */
 	NULL,			/* szVetoOplockFiles */
@@ -1122,7 +1120,6 @@
 	{"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
 	{"map readonly", P_ENUM, P_LOCAL, &sDefault.iMap_readonly, NULL, enum_map_readonly, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
 	{"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
-	{"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED }, 
 	{"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED}, 
 	{"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, 
 	{"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
@@ -2068,7 +2065,6 @@
 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
 static FN_LOCAL_STRING(lp_volume, volume)
-FN_LOCAL_PARM_STRING(lp_mangled_map, szMangledMap)
 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
Index: lib/charcnv.c
===================================================================
--- lib/charcnv.c	(revision 24984)
+++ lib/charcnv.c	(working copy)
@@ -804,6 +804,71 @@
 	return SMB_STRDUP(out_buffer);
 }
 
+/**
+ talloc_strdup() a unix string to upper case.
+**/
+
+char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
+{
+	char *out_buffer = talloc_strdup(ctx,s);
+	const unsigned char *p = (const unsigned char *)s;
+	unsigned char *q = (unsigned char *)out_buffer;
+
+	if (!q) {
+		return NULL;
+	}
+
+	/* this is quite a common operation, so we want it to be
+	   fast. We optimise for the ascii case, knowing that all our
+	   supported multi-byte character sets are ascii-compatible
+	   (ie. they match for the first 128 chars) */
+
+	while (1) {
+		if (*p & 0x80)
+			break;
+		*q++ = toupper_ascii(*p);
+		if (!*p)
+			break;
+		p++;
+	}
+
+	if (*p) {
+		/* MB case. */
+		size_t size;
+		smb_ucs2_t *ubuf = NULL;
+
+		/* We're not using the ascii buffer above. */
+		TALLOC_FREE(out_buffer);
+
+		size = convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE,
+				s, strlen(s),
+				(void *)&ubuf,
+				True);
+		if (size == (size_t)-1) {
+			return NULL;
+		}
+
+		strupper_w(ubuf);
+
+		size = convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX,
+				ubuf, size,
+				(void *)&out_buffer,
+				True);
+
+		/* Don't need the intermediate buffer
+ 		 * anymore.
+ 		 */
+
+		TALLOC_FREE(ubuf);
+
+		if (size == (size_t)-1) {
+			return NULL;
+		}
+	}
+
+	return out_buffer;
+}
+
 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
 {
 	size_t size;
Index: rpc_server/srv_srvsvc_nt.c
===================================================================
--- rpc_server/srv_srvsvc_nt.c	(revision 24984)
+++ rpc_server/srv_srvsvc_nt.c	(working copy)
@@ -2047,7 +2047,7 @@
 	connection_struct *conn = NULL;
 	BOOL became_user = False; 
 	WERROR status = WERR_OK;
-	pstring tmp_file;
+	char *tmp_file = NULL;
 
 	ZERO_STRUCT(st);
 
@@ -2072,26 +2072,29 @@
 	}
 	became_user = True;
 
-	pstrcpy(tmp_file, r->in.file);
-	nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
+	if (!r->in.file) {
+		status = WERR_INVALID_PARAM;
+		goto error_exit;
+	}
+	nt_status = unix_convert(conn, r->in.file, False, &tmp_file, NULL, &st);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", r->in.file));
 		status = WERR_ACCESS_DENIED;
 		goto error_exit;
 	}
 
-	nt_status = check_name(conn, r->in.file);
+	nt_status = check_name(conn, tmp_file);
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", r->in.file));
+		DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", tmp_file));
 		status = WERR_ACCESS_DENIED;
 		goto error_exit;
 	}
 
-	nt_status = open_file_stat(conn, NULL, r->in.file, &st, &fsp);
+	nt_status = open_file_stat(conn, NULL, tmp_file, &st, &fsp);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		/* Perhaps it is a directory */
 		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
-			nt_status = open_directory(conn, NULL, r->in.file, &st,
+			nt_status = open_directory(conn, NULL, tmp_file, &st,
 					READ_CONTROL_ACCESS,
 					FILE_SHARE_READ|FILE_SHARE_WRITE,
 					FILE_OPEN,
@@ -2100,7 +2103,7 @@
 					NULL, &fsp);
 
 		if (!NT_STATUS_IS_OK(nt_status)) {
-			DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", r->in.file));
+			DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", tmp_file));
 			status = WERR_ACCESS_DENIED;
 			goto error_exit;
 		}
@@ -2109,7 +2112,7 @@
 	sd_size = SMB_VFS_GET_NT_ACL(fsp, fsp->fsp_name, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
 
 	if (sd_size == 0) {
-		DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", r->in.file));
+		DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", tmp_file));
 		status = WERR_ACCESS_DENIED;
 		goto error_exit;
 	}
@@ -2152,7 +2155,7 @@
 	connection_struct *conn = NULL;
 	BOOL became_user = False;
 	WERROR status = WERR_OK;
-	pstring tmp_file;
+	char *tmp_file = NULL;
 
 	ZERO_STRUCT(st);
 
@@ -2176,28 +2179,31 @@
 	}
 	became_user = True;
 
-	pstrcpy(tmp_file, r->in.file);
-	nt_status = unix_convert(conn, tmp_file, False, NULL, &st);
+	if (!r->in.file) {
+		status = WERR_INVALID_PARAM;
+		goto error_exit;
+	}
+	nt_status = unix_convert(conn, r->in.file, False, &tmp_file, NULL, &st);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", r->in.file));
 		status = WERR_ACCESS_DENIED;
 		goto error_exit;
 	}
 
-	nt_status = check_name(conn, r->in.file);
+	nt_status = check_name(conn, tmp_file);
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", r->in.file));
+		DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", tmp_file));
 		status = WERR_ACCESS_DENIED;
 		goto error_exit;
 	}
 
 
-	nt_status = open_file_stat(conn, NULL, r->in.file, &st, &fsp);
+	nt_status = open_file_stat(conn, NULL, tmp_file, &st, &fsp);
 
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		/* Perhaps it is a directory */
 		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY))
-			nt_status = open_directory(conn, NULL, r->in.file, &st,
+			nt_status = open_directory(conn, NULL, tmp_file, &st,
 						FILE_READ_ATTRIBUTES,
 						FILE_SHARE_READ|FILE_SHARE_WRITE,
 						FILE_OPEN,
@@ -2206,7 +2212,7 @@
 						NULL, &fsp);
 
 		if (!NT_STATUS_IS_OK(nt_status)) {
-			DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", r->in.file));
+			DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", tmp_file));
 			status = WERR_ACCESS_DENIED;
 			goto error_exit;
 		}
@@ -2215,7 +2221,7 @@
 	nt_status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, r->in.securityinformation, r->in.sd_buf.sd);
 
 	if (!NT_STATUS_IS_OK(nt_status)) {
-		DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", r->in.file));
+		DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", tmp_file));
 		status = WERR_ACCESS_DENIED;
 		goto error_exit;
 	}
Index: include/mangle.h
===================================================================
--- include/mangle.h	(revision 24984)
+++ include/mangle.h	(working copy)
@@ -7,12 +7,17 @@
 struct mangle_fns {
 	void (*reset)(void);
 	BOOL (*is_mangled)(const char *s, const struct share_params *p);
+	BOOL (*must_mangle)(const char *s, const struct share_params *p);
 	BOOL (*is_8_3)(const char *fname, BOOL check_case, BOOL allow_wildcards,
 		       const struct share_params *p);
-	BOOL (*check_cache)(char *s, size_t maxlen,
-			    const struct share_params *p);
-	void (*name_map)(char *OutName, BOOL need83, BOOL cache83,
-			 int default_case,
-			 const struct share_params *p);
+	BOOL (*lookup_name_from_8_3)(TALLOC_CTX *ctx,
+				const char *in,
+				char **out, /* talloced on the given context. */
+				const struct share_params *p);
+	BOOL (*name_to_8_3)(const char *in,
+			char out[13],
+			BOOL cache83,
+			int default_case,
+			const struct share_params *p);
 };
 #endif /* _MANGLE_H_ */


More information about the samba-technical mailing list