r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based
authorJeremy Allison <jra@samba.org>
Fri, 7 Sep 2007 20:57:01 +0000 (20:57 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:30:32 +0000 (12:30 -0500)
interface. More development will come on top of this. Remove the
"mangled map" parameter.
Jeremy.
(This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736)

16 files changed:
source3/Makefile.in
source3/include/mangle.h
source3/lib/charcnv.c
source3/param/loadparm.c
source3/printing/nt_printing.c
source3/rpc_server/srv_srvsvc_nt.c
source3/smbd/dir.c
source3/smbd/filename.c
source3/smbd/mangle.c
source3/smbd/mangle_hash.c
source3/smbd/mangle_hash2.c
source3/smbd/msdfs.c
source3/smbd/nttrans.c
source3/smbd/reply.c
source3/smbd/statcache.c
source3/smbd/trans2.c

index c96bb0f069ab968ccd9dbfcf45dcff52392d2864..f2f628250969043c48b9e40c593f926e1c803e95 100644 (file)
@@ -511,7 +511,7 @@ AUTH_OBJ = auth/auth.o @AUTH_STATIC@ auth/auth_util.o auth/token_util.o \
           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 3d19ef9ed4f41ba66479461426d18a322d0d750f..382bf1c6305af64016f8324b83e0ce81b4c6e1cb 100644 (file)
@@ -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_ */
index 349fbff8506d4c13fbc009171211c827fd349966..dd03a5623308b00b74516b2f7d474dcf09d86b16 100644 (file)
@@ -804,6 +804,71 @@ char *strdup_upper(const char *s)
        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 3dd94645fd0f9adc030b181976623b1047add373..9e089cf8a2377695c3e5dce82eca1636b0669e78 100644 (file)
@@ -370,7 +370,6 @@ typedef struct {
        char **szHostsdeny;
        char *szMagicScript;
        char *szMagicOutput;
-       char *szMangledMap;
        char *szVetoFiles;
        char *szHideFiles;
        char *szVetoOplockFiles;
@@ -511,7 +510,6 @@ static service sDefault = {
        NULL,                   /* szHostsdeny */
        NULL,                   /* szMagicScript */
        NULL,                   /* szMagicOutput */
-       NULL,                   /* szMangledMap */
        NULL,                   /* szVetoFiles */
        NULL,                   /* szHideFiles */
        NULL,                   /* szVetoOplockFiles */
@@ -1122,7 +1120,6 @@ static struct parm_struct parm_table[] = {
        {"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_STRING(lp_fstype, fstype)
 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 944b695a9dddc0ee16aa18e7b5de2768bcfc71f0..24729c715b7acdf0bca4f30e7cf386eb211b3e43 100644 (file)
@@ -659,13 +659,18 @@ BOOL nt_printing_init(struct messaging_context *msg_ctx)
  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 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        /* 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 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
 
        /* 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 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
         * 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 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
         */
        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 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                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 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        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 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        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 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        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 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                                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 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
        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 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
        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 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
        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 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
        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 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct
                        
                        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 22eaac51a75075f9fa40b5260d7a435efb918ee1..4be519a9a3f2de77fddf8ff79f48b8254d151a30 100644 (file)
@@ -2047,7 +2047,7 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecur
        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 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecur
        }
        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 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecur
                                        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 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecur
        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 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecur
        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 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecur
        }
        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 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecur
                                                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 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecur
        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 eec8fa12ef8b994bd92895239ec2953f16e106bc..e602008b8fc5af0c3c3c2adae8d25f459867e179 100644 (file)
@@ -380,12 +380,11 @@ static void dptr_close_oldest(BOOL old)
  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 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
                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 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
 
        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 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
        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 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn
                    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 5f9563b83c8701479d54e71da98f225cff8dddff..5871fd143f7108504876d87c18731870d2201a34 100644 (file)
@@ -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 @@ static BOOL mangled_equal(const char *name1,
                        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 @@ for nlinks = 0, which can never be true for any file).
 ****************************************************************************/
 
 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 @@ NTSTATUS unix_convert(connection_struct *conn,
        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 @@ NTSTATUS unix_convert(connection_struct *conn,
         */
 
        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 @@ NTSTATUS unix_convert(connection_struct *conn,
         * 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 @@ NTSTATUS unix_convert(connection_struct *conn,
         * 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 @@ NTSTATUS unix_convert(connection_struct *conn,
         */
 
        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 @@ NTSTATUS unix_convert(connection_struct *conn,
                        *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 @@ NTSTATUS unix_convert(connection_struct *conn,
                                 */
 
                                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 @@ NTSTATUS unix_convert(connection_struct *conn,
                                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 @@ NTSTATUS unix_convert(connection_struct *conn,
                                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 @@ NTSTATUS unix_convert(connection_struct *conn,
                                }
                        }
 
-                       SAFE_FREE(found_name);
+                       TALLOC_FREE(found_name);
                } /* end else */
 
 #ifdef DEVELOPER
@@ -577,19 +596,19 @@ NTSTATUS unix_convert(connection_struct *conn,
                 */
 
                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,23 @@ NTSTATUS unix_convert(connection_struct *conn,
        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);
+       if (*dirpath != '\0') {
+               *pp_conv_path = talloc_asprintf(ctx,
+                               "%s/%s", dirpath, start);
+       } else {
+               *pp_conv_path = talloc_strdup(ctx, 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 +674,7 @@ NTSTATUS unix_convert(connection_struct *conn,
  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 +707,9 @@ static BOOL fname_equal(const char *name1, const char *name2,
                BOOL case_sensitive)
 {
        /* Normal filename handling */
-       if (case_sensitive)
+       if (case_sensitive) {
                return(strcmp(name1,name2) == 0);
+       }
 
        return(strequal(name1,name2));
 }
@@ -701,17 +727,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
        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 +752,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
         */
 
        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 +773,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
        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 +791,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
                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 fce86903f2427b99ef6f04ed7b7e2683a68ce2d3..61490c444eb8262ae55f93d64eb6ca8c3e1f20c8 100644 (file)
@@ -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 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case,
        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);
-}
-
-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;
+       return mangle_fns->lookup_name_from_8_3(ctx, in, out, p);
 }
 
-/* 
-   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 4c02d9685fb7463a0efd5ce1a9626111bfb668be..d63a980cfbcb467defec0eaa827916d4d34980da 100644 (file)
@@ -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 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards)
 
        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 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards,
 
        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 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards,
 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 @@ done:
  *
  * ************************************************************************** **
  */
+
 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 void init_chartest( void )
  *
  * ************************************************************************** **
  */
+
 static BOOL is_mangled(const char *s, const struct share_params *p)
 {
        char *magic;
@@ -406,7 +407,8 @@ static void mangle_reset( void )
   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 void cache_mangled_name( const char mangled_name[13], char *raw_name )
  * ************************************************************************** **
  */
 
-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 @@ static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
 
        /* 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 @@ static void to_8_3(char *s, int default_case)
        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 @@ static void to_8_3(char *s, int default_case)
                        extension[extlen] = 0;
                }
        }
-  
+
        p = s;
 
        while( *p && baselen < 5 ) {
@@ -567,79 +582,88 @@ static void to_8_3(char *s, int default_case)
                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;
-
-       /* 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; 
-
-               /* mangle it into 8.3 */
-               if (cache83)
-                       tmp = SMB_STRDUP(OutName);
-
-               to_8_3(OutName, default_case);
+       /* 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;
+       }
 
-               if(tmp != NULL) {
-                       cache_mangled_name(OutName, tmp);
-                       SAFE_FREE(tmp);
-               }
+       SAFE_FREE(in_ucs2);
+       if (!to_8_3(in, out, default_case)) {
+               return False;
        }
 
-       DEBUG(5,("name_map() ==> [%s]\n", OutName));
-       SAFE_FREE(OutName_ucs2);
+       cache_mangled_name(out, in);
+
+       DEBUG(5,("hash_name_to_8_3(%s) ==> [%s]\n", in, out));
+       return True;
 }
 
 /*
@@ -649,9 +673,10 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83,
 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 c3db112051a86d75270b255c7d27760673528796..73f81fe9aeceb945d2b0214f314287e3e5d87ead 100644 (file)
@@ -368,18 +368,23 @@ static void mangle_reset(void)
 
 /*
   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 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
        /* 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 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
        }
 
        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 @@ static BOOL is_legal_name(const char *name)
        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,20 +538,14 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
        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 caller doesn't strictly need 8.3 then just check for illegal 
-                  filenames */
-               if (!need83 && is_legal_name(name)) {
-                       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;
                }
        }
 
@@ -548,7 +562,9 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
                                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 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
                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 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
                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 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
                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 @@ static void init_tables(void)
                        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 @@ static void init_tables(void)
        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 void init_tables(void)
 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 @@ static BOOL posix_is_mangled(const char *s, const struct share_params *p)
        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 16f3cd4370c40585ce5019a2da445626d958c24b..10652874c513817cab6601962bf63b5693580c68 100644 (file)
@@ -369,7 +369,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,
        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 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,
         * 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 b5af173d45ed3f74cff3f3198019b67182da3a36..735c147b8d24e0242956afd3c6169aa6e91efb48 100644 (file)
@@ -489,7 +489,8 @@ static void reply_ntcreate_and_X_quota(connection_struct *conn,
 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 @@ void reply_ntcreate_and_X(connection_struct *conn,
 
                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 @@ void reply_ntcreate_and_X(connection_struct *conn,
                         * 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 @@ void reply_ntcreate_and_X(connection_struct *conn,
                 * 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 @@ void reply_ntcreate_and_X(connection_struct *conn,
                        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 @@ void reply_ntcreate_and_X(connection_struct *conn,
                 * 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 @@ void reply_ntcreate_and_X(connection_struct *conn,
                                 * 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 @@ void reply_ntcreate_and_X(connection_struct *conn,
         * 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 @@ void reply_ntcreate_and_X(connection_struct *conn,
        /*
         * 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 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata,
                }
                offset += next_offset;
        }
-                                                                                                                             
+
        return ea_list_head;
 }
 
@@ -1215,7 +1216,8 @@ static void call_nt_transact_create(connection_struct *conn,
                                    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 @@ static void call_nt_transact_create(connection_struct *conn,
                }
 
                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 @@ static void call_nt_transact_create(connection_struct *conn,
                         * 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 @@ static void call_nt_transact_create(connection_struct *conn,
                 * 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 @@ static void call_nt_transact_create(connection_struct *conn,
                                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 @@ static void call_nt_transact_create(connection_struct *conn,
                 * 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 @@ static void call_nt_transact_create(connection_struct *conn,
        /*
         * Ordinary file or directory.
         */
-               
+
        /*
         * Check if POSIX semantics are wanted.
         */
@@ -1421,9 +1423,9 @@ static void call_nt_transact_create(connection_struct *conn,
                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 @@ static void call_nt_transact_create(connection_struct *conn,
                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 @@ void reply_ntcancel(connection_struct *conn, struct smb_request *req)
 
 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 @@ static NTSTATUS copy_internals(connection_struct *conn,
                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 @@ static NTSTATUS copy_internals(connection_struct *conn,
                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 @@ static NTSTATUS copy_internals(connection_struct *conn,
                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 2694176ca75c3f70f02382649d3886364ac8a45d..dec0e26c414a2e91c7395c9d999e53d6d1ae505e 100644 (file)
@@ -285,11 +285,10 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
 }
 
 /****************************************************************************
- Check if we have a correct fsp pointing to a file. Replacement for the
- CHECK_FSP macro.
+ Check if we have a correct fsp pointing to a file. Basic check for open fsp.
 ****************************************************************************/
 
-BOOL check_fsp(connection_struct *conn, struct smb_request *req,
+BOOL check_fsp_open(connection_struct *conn, struct smb_request *req,
               files_struct *fsp, struct current_user *user)
 {
        if (!(fsp) || !(conn)) {
@@ -300,6 +299,20 @@ BOOL check_fsp(connection_struct *conn, struct smb_request *req,
                reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                return False;
        }
+       return True;
+}
+
+/****************************************************************************
+ Check if we have a correct fsp pointing to a file. Replacement for the
+ CHECK_FSP macro.
+****************************************************************************/
+
+BOOL check_fsp(connection_struct *conn, struct smb_request *req,
+              files_struct *fsp, struct current_user *user)
+{
+       if (!check_fsp_open(conn, req, fsp, user)) {
+               return False;
+       }
        if ((fsp)->is_directory) {
                reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
                return False;
@@ -755,7 +768,9 @@ void reply_ioctl(connection_struct *conn, struct smb_request *req)
        SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
        SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
        SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
-       p = smb_buf(req->outbuf) + 1;          /* Allow for alignment */
+       p = smb_buf(req->outbuf);
+       memset(p, '\0', replysize+1); /* valgrind-safe. */
+       p += 1;          /* Allow for alignment */
 
        switch (ioctl_code) {
                case IOCTL_QUERY_JOB_INFO:                  
@@ -775,8 +790,7 @@ void reply_ioctl(connection_struct *conn, struct smb_request *req)
                                srvstr_push((char *)req->outbuf, req->flags2,
                                            p+18, lp_servicename(SNUM(conn)),
                                            13, STR_TERMINATE|STR_ASCII);
-                       }
-                       else {
+                       } else {
                                memset(p+18, 0, 13);
                        }
                        break;
@@ -809,14 +823,15 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
 
 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 +840,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
                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 +851,9 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
                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 +914,8 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
 
 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 +926,8 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
        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 +935,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
        }
 
        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 +950,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
   
        /* 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 +958,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
                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 +1013,8 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
 
 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 +1029,8 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
        }
 
        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 +1038,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
        }
 
        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 +1051,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
                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 +1164,7 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
 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 +1198,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                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 +1242,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
        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 +1259,43 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                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 +1305,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                        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 +1316,6 @@ void reply_search(connection_struct *conn, struct smb_request *req)
                 * 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 +1416,18 @@ void reply_search(connection_struct *conn, struct smb_request *req)
        /* 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 +1496,8 @@ void reply_fclose(connection_struct *conn, struct smb_request *req)
 
 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 +1525,8 @@ void reply_open(connection_struct *conn, struct smb_request *req)
        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 +1535,7 @@ void reply_open(connection_struct *conn, struct smb_request *req)
        }
 
        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 +1548,7 @@ void reply_open(connection_struct *conn, struct smb_request *req)
                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 +1631,8 @@ void reply_open(connection_struct *conn, struct smb_request *req)
 
 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 +1688,8 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
        }
 
        /* 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 +1698,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
        }
 
        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 +1710,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
                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 +1876,8 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
 
 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 +1906,8 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
                        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 +1916,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
        }
 
        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 +1928,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
                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 +2005,8 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
 
 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 +2026,22 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)
        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 +2054,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)
                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 +2298,23 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
 ****************************************************************************/
 
 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 +2324,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                pstrcpy(directory,name);
                pstrcpy(mask,p+1);
        }
-       
+
        /*
         * We should only check the mangled cache
         * here if unix_convert failed. This means
@@ -2300,10 +2333,18 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
         * for a possible mangle. This patch from
         * Tine Smukavec <valentin.smukavec@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 +2367,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                struct smb_Dir *dir_hnd = NULL;
                long offset = 0;
                const char *dname;
-               
+
                if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
                        return NT_STATUS_OBJECT_NAME_INVALID;
                }
@@ -2798,6 +2839,7 @@ void reply_lockread(connection_struct *conn, struct smb_request *req)
        NTSTATUS status;
        files_struct *fsp;
        struct byte_range_lock *br_lck = NULL;
+       char *p = NULL;
 
        START_PROFILE(SMBlockread);
 
@@ -2879,7 +2921,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
 
        SSVAL(req->outbuf,smb_vwv0,nread);
        SSVAL(req->outbuf,smb_vwv5,nread+3);
-       SSVAL(smb_buf(req->outbuf),1,nread);
+       p = smb_buf(req->outbuf);
+       SCVAL(p,0,0); /* pad byte. */
+       SSVAL(p,1,nread);
        
        DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
                 fsp->fnum, (int)numtoread, (int)nread));
@@ -4600,14 +4644,15 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req)
 
 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 +4662,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
 
        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 +4675,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
                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 +4898,14 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
 
 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 +4915,7 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
 
        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 +4928,8 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
                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);
@@ -4914,87 +4961,129 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
 
 /*******************************************************************
  Resolve wildcards in a filename rename.
- Note that name is in UNIX charset and thus potentially can be more
- than fstring buffer (255 bytes) especially in default UTF-8 case.
- Therefore, we use pstring inside and all calls should ensure that
- name2 is at least pstring-long (they do already)
 ********************************************************************/
 
-static BOOL resolve_wildcards(const char *name1, char *name2)
+static BOOL resolve_wildcards(TALLOC_CTX *ctx,
+                               const char *name1,
+                               const char *name2,
+                               char **pp_newname)
 {
-       pstring root1,root2;
-       pstring ext1,ext2;
+       char *name2_copy = NULL;
+       char *root1 = NULL;
+       char *root2 = NULL;
+       char *ext1 = NULL;
+       char *ext2 = NULL;
        char *p,*p2, *pname1, *pname2;
-       int available_space, actual_space;
        
+       name2_copy = talloc_strdup(ctx, name2);
+       if (!name2_copy) {
+               return False;
+       }
+
        pname1 = strrchr_m(name1,'/');
-       pname2 = strrchr_m(name2,'/');
+       pname2 = strrchr_m(name2_copy,'/');
 
-       if (!pname1 || !pname2)
-               return(False);
+       if (!pname1 || !pname2) {
+               return False;
+       }
   
-       pstrcpy(root1,pname1);
-       pstrcpy(root2,pname2);
+       /* Truncate the copy of name2 at the last '/' */
+       *pname2 = '\0';
+
+       /* Now go past the '/' */
+       pname1++;
+       pname2++;
+
+       root1 = talloc_strdup(ctx, pname1);
+       root2 = talloc_strdup(ctx, pname2);
+
+       if (!root1 || !root2) {
+               return False;
+       }
+
        p = strrchr_m(root1,'.');
        if (p) {
                *p = 0;
-               pstrcpy(ext1,p+1);
+               ext1 = talloc_strdup(ctx, p+1);
        } else {
-               pstrcpy(ext1,"");    
+               ext1 = talloc_strdup(ctx, "");
        }
        p = strrchr_m(root2,'.');
        if (p) {
                *p = 0;
-               pstrcpy(ext2,p+1);
+               ext2 = talloc_strdup(ctx, p+1);
        } else {
-               pstrcpy(ext2,"");    
+               ext2 = talloc_strdup(ctx, "");
+       }
+
+       if (!ext1 || !ext2) {
+               return False;
        }
 
        p = root1;
        p2 = root2;
        while (*p2) {
                if (*p2 == '?') {
+                       /* Hmmm. Should this be mb-aware ? */
                        *p2 = *p;
                        p2++;
                } else if (*p2 == '*') {
-                       pstrcpy(p2, p);
+                       *p2 = '\0';
+                       root2 = talloc_asprintf(ctx, "%s%s",
+                                               root2,
+                                               p);
+                       if (!root2) {
+                               return False;
+                       }
                        break;
                } else {
                        p2++;
                }
-               if (*p)
+               if (*p) {
                        p++;
+               }
        }
 
        p = ext1;
        p2 = ext2;
        while (*p2) {
                if (*p2 == '?') {
+                       /* Hmmm. Should this be mb-aware ? */
                        *p2 = *p;
                        p2++;
                } else if (*p2 == '*') {
-                       pstrcpy(p2, p);
+                       *p2 = '\0';
+                       ext2 = talloc_asprintf(ctx, "%s%s",
+                                               ext2,
+                                               p);
+                       if (!ext2) {
+                               return False;
+                       }
                        break;
                } else {
                        p2++;
                }
-               if (*p)
+               if (*p) {
                        p++;
+               }
        }
 
-       available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
-       
-       if (ext2[0]) {
-               actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
-               if (actual_space >= available_space - 1) {
-                       DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
-                               actual_space - available_space));
-               }
+       if (*ext2) {
+               *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
+                               name2_copy,
+                               root2,
+                               ext2);
        } else {
-               pstrcpy_base(pname2, root2, name2);
+               *pp_newname = talloc_asprintf(ctx, "%s/%s",
+                               name2_copy,
+                               root2);
        }
 
-       return(True);
+       if (!*pp_newname) {
+               return False;
+       }
+
+       return True;
 }
 
 /****************************************************************************
@@ -5110,11 +5199,14 @@ static void notify_rename(connection_struct *conn, BOOL is_dir,
  Rename an open file - given an fsp.
 ****************************************************************************/
 
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
-                             pstring newname,
-                             const char *newname_last_component,
-                             uint32 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn,
+                       files_struct *fsp,
+                       char *newname,
+                       const char *newname_last_component,
+                       uint32 attrs,
+                       BOOL replace_if_exists)
 {
+       TALLOC_CTX *ctx = talloc_tos();
        SMB_STRUCT_STAT sbuf, sbuf1;
        NTSTATUS status = NT_STATUS_OK;
        struct share_mode_lock *lck = NULL;
@@ -5126,14 +5218,15 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-  
+
        /* Ensure newname contains a '/' */
        if(strrchr_m(newname,'/') == 0) {
-               pstring tmpstr;
-               
-               pstrcpy(tmpstr, "./");
-               pstrcat(tmpstr, newname);
-               pstrcpy(newname, tmpstr);
+               newname = talloc_asprintf(ctx,
+                                       "./%s",
+                                       newname);
+               if (!newname) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        /*
@@ -5147,7 +5240,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
        if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
                        strequal(newname, fsp->fsp_name)) {
                char *p;
-               pstring newname_modified_last_component;
+               char *newname_modified_last_component = NULL;
 
                /*
                 * Get the last component of the modified name.
@@ -5155,15 +5248,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
                 * character above.
                 */
                p = strrchr_m(newname,'/');
-               pstrcpy(newname_modified_last_component,p+1);
-                       
-               if(strcsequal(newname_modified_last_component, 
+               newname_modified_last_component = talloc_strdup(ctx,
+                                               p+1);
+               if (!newname_modified_last_component) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if(strcsequal(newname_modified_last_component,
                              newname_last_component) == False) {
                        /*
                         * Replace the modified last component with
                         * the original.
                         */
-                       pstrcpy(p+1, newname_last_component);
+                       *p = '\0'; /* Truncate at the '/' */
+                       newname = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       newname,
+                                       newname_last_component);
                }
        }
 
@@ -5263,7 +5364,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
                        }
                }
                TALLOC_FREE(lck);
-               return NT_STATUS_OK;    
+               return NT_STATUS_OK;
        }
 
        TALLOC_FREE(lck);
@@ -5273,7 +5374,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
        } else {
                status = map_nt_error_from_unix(errno);
        }
-               
+
        DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
                nt_errstr(status), fsp->fsp_name,newname));
 
@@ -5286,8 +5387,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
 ****************************************************************************/
 
 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 +5396,10 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 {
        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 +5414,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
        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 +5456,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
         */
 
        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 +5477,17 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                /* 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, "
@@ -5385,11 +5498,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
                /* The dest name still may have wildcards. */
                if (dest_has_wild) {
-                       if (!resolve_wildcards(directory,newname)) {
+                       char *mod_newname = NULL;
+                       if (!resolve_wildcards(talloc_tos(),
+                                       directory,newname,&mod_newname)) {
                                DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
                                          directory,newname));
                                return NT_STATUS_NO_MEMORY;
                        }
+                       newname = mod_newname;
                }
                                
                ZERO_STRUCT(sbuf1);
@@ -5452,6 +5568,7 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                files_struct *fsp;
                pstring fname;
                BOOL sysdir_entry = False;
+               char *mod_destname = NULL;
 
                pstrcpy(fname,dname);
                                
@@ -5483,11 +5600,13 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
                pstrcpy(destname,newname);
                        
-               if (!resolve_wildcards(fname,destname)) {
+               if (!resolve_wildcards(talloc_tos(),
+                               fname,destname,&mod_destname)) {
                        DEBUG(6, ("resolve_wildcards %s %s failed\n", 
                                  fname, destname));
                        continue;
                }
+               pstrcpy(destname,mod_destname);
                                
                ZERO_STRUCT(sbuf1);
                SMB_VFS_STAT(conn, fname, &sbuf1);
@@ -5756,9 +5875,12 @@ NTSTATUS copy_file(connection_struct *conn,
 
 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 +5909,16 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
        *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 +5926,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                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 +5938,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
 
        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 +5953,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
 
        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 +5966,14 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                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,18 +6022,28 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
         */
 
        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) {
                pstrcat(directory,"/");
                pstrcat(directory,mask);
                if (dest_has_wild) {
-                       if (!resolve_wildcards(directory,newname)) {
+                       char *mod_newname = NULL;
+                       if (!resolve_wildcards(talloc_tos(),
+                                       directory,newname,&mod_newname)) {
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                END_PROFILE(SMBcopy);
                                return;
                        }
+                       newname = mod_newname;
                }
 
                status = check_name(conn, directory);
@@ -5965,6 +6097,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                error = ERRbadfile;
 
                while ((dname = ReadDirName(dir_hnd, &offset))) {
+                       char *mod_destname = NULL;
                        pstring fname;
                        pstrcpy(fname,dname);
     
@@ -5979,9 +6112,11 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
                        error = ERRnoaccess;
                        slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
                        pstrcpy(destname,newname);
-                       if (!resolve_wildcards(fname,destname)) {
+                       if (!resolve_wildcards(talloc_tos(),
+                                       fname,destname,&mod_destname)) {
                                continue;
                        }
+                       pstrcpy(destname,mod_destname);
 
                        status = check_name(conn, fname);
                        if (!NT_STATUS_IS_OK(status)) {
index d2f09930a0b833b389bd196c43c23c49e4ba0758..a066091b527b24ea72cd0ee748251416529aad66 100644 (file)
@@ -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@samba.org> 2003
    Copyright (C) Volker Lendecke 2007
 
@@ -40,7 +40,8 @@ static TDB_CONTEXT *tdb_stat_cache;
  *
  */
 
-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 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
        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 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
         * 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 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
        }
 
        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 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
                                  (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 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
                original_path_length = translated_path_length;
        }
 
-       /*
-        * New entry or replace old entry.
-        */
+       /* 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.
+        */
+
        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 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
                        translated_path));
        }
 
-       SAFE_FREE(original_path);
+       translated_path[translated_path_length] = saved_char;
+       TALLOC_FREE(original_path);
 }
 
 /**
@@ -157,8 +161,10 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
  * @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 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
  *
  */
 
-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 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
        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 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
        }
 
        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 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
                 * 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 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
                         * 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,25 +262,25 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
                 * 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;
-
-       /*
-        * 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';
+       SAFE_FREE(data_val.dptr);
 
        DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] "
                  "-> [%s]\n", chk_name, translated_path ));
@@ -276,50 +289,51 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
        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 send_stat_cache_delete_message(const char *name)
 
 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 @@ void stat_cache_delete(const char *name)
                        lname, name ));
 
        tdb_delete_bystring(tdb_stat_cache, lname);
-       SAFE_FREE(lname);
+       TALLOC_FREE(lname);
 }
 
 /***************************************************************
index ed4d4554d4c1b0be8671b833801d92fc94a499a1..59f384e8b0bb8c542cc4a5e25556ec70a0e0ae6b 100644 (file)
@@ -783,7 +783,8 @@ static void call_trans2open(connection_struct *conn,
        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 @@ static void call_trans2open(connection_struct *conn,
                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 @@ static void call_trans2open(connection_struct *conn,
 
        /* 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 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
        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 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                 * 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 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
 
                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.
                         */
-
-                       pstrcpy(mangled_name, fname);
-
                        /* Force the mangling into 8.3. */
-                       mangle_map( mangled_name, True, False, conn->params);
+                       if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
+                               continue; /* Error - couldn't mangle. */
+                       }
+
                        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 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                         * 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 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
                         * 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 @@ static void call_trans2findfirst(connection_struct *conn,
        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 @@ static void call_trans2findfirst(connection_struct *conn,
        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 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                        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,11 +1846,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                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;
        }
+
        ntstatus = check_name(conn, directory);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                reply_nterror(req, ntstatus);
@@ -1858,7 +1867,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                } 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 +2043,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        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 +2062,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
         * (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 +2289,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                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 +3508,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        unsigned int data_size = 0;
        unsigned int param_size = 2;
        SMB_STRUCT_STAT sbuf;
-       pstring fname, dos_fname;
+       pstring dos_fname;
+       char *fname = NULL;
        char *fullpathname;
        char *base_name;
        char *p;
@@ -3530,23 +3556,31 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        return;
                }
 
-               if(fsp && (fsp->fake_file_handle)) {
+               /* Initial check for valid fsp ptr. */
+               if (!check_fsp_open(conn, req, fsp, &current_user)) {
+                       return;
+               }
+
+               fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+               if (!fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
+
+               if(fsp->fake_file_handle) {
                        /*
                         * This is actually for the QUOTA_FAKE_FILE --metze
                         */
-                                               
-                       pstrcpy(fname, 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)) {
                        /*
                         * This is actually a QFILEINFO on a directory
                         * handle (returned from an NT SMB). NT5.0 seems
                         * to do this call. JRA.
                         */
-                       /* We know this name is ok, it's already passed the checks. */
-                       pstrcpy(fname, fsp->fsp_name);
-                 
+
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
                                if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
@@ -3570,7 +3604,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                                return;
                        }
 
-                       pstrcpy(fname, 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,7 +3614,9 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        delete_pending = get_delete_on_close_flag(fileid);
                        access_mask = fsp->access_mask;
                }
+
        } else {
+               pstring fname_in;
                NTSTATUS status = NT_STATUS_OK;
 
                /* qpathinfo */
@@ -3599,8 +3634,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        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 +3644,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
 
                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 +3655,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                        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 +3997,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                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 +4430,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
  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 +4460,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                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 +4923,15 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
 
 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 +4949,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                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 +4958,13 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
 
        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 +4977,19 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                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 +5007,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                                              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 +6167,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
        char *pdata = *ppdata;
        uint16 info_level;
        SMB_STRUCT_STAT sbuf;
-       pstring fname;
+       char *fname = NULL;
        files_struct *fsp = NULL;
        NTSTATUS status = NT_STATUS_OK;
        int data_return_size = 0;
@@ -6140,15 +6186,24 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                }
 
                fsp = file_fsp(SVAL(params,0));
-               info_level = SVAL(params,2);    
+               /* Basic check for non-null fsp. */
+               if (!check_fsp_open(conn, req, fsp, &current_user)) {
+                       return;
+               }
+               info_level = SVAL(params,2);
 
-               if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
+               fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+               if (!fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
+
+               if(fsp->is_directory || fsp->fh->fd == -1) {
                        /*
                         * This is actually a SETFILEINFO on a directory
                         * handle (returned from an NT SMB). NT5.0 seems
                         * to do this call. JRA.
                         */
-                       pstrcpy(fname, fsp->fsp_name);
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
                                if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
@@ -6163,7 +6218,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                        return;
                                }
                        }
-               } else if (fsp && fsp->print_file) {
+               } else if (fsp->print_file) {
                        /*
                         * Doing a DELETE_ON_CLOSE should cancel a print job.
                         */
@@ -6171,18 +6226,17 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
 
                                DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
-       
+
                                SSVAL(params,0,0);
                                send_trans2_replies(req, params, 2,
                                                    *ppdata, 0,
                                                    max_data_bytes);
                                return;
-                       }
-                       else {
+                       } else {
                                reply_unixerror(req, ERRDOS, ERRbadpath);
                                return;
                        }
-           } else {
+               } else {
                        /*
                         * Original code - this is an open file.
                         */
@@ -6190,8 +6244,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                return;
                        }
 
-                       pstrcpy(fname, 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)));
                                reply_unixerror(req, ERRDOS, ERRbadfid);
@@ -6199,15 +6251,17 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        }
                }
        } else {
+               pstring fname_in;
+
                /* set path info */
                if (total_params < 7) {
                        reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                        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 +6270,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
 
                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 +6282,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        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 +6604,8 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
 {
        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 +6620,17 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                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;