1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-26 18:50:30 +03:00

r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based

interface. More development will come on top of this. Remove the
"mangled map" parameter.
Jeremy.
(This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736)
This commit is contained in:
Jeremy Allison 2007-09-07 20:57:01 +00:00 committed by Gerald (Jerry) Carter
parent c5d8fd3772
commit 132ee3990a
16 changed files with 1075 additions and 690 deletions

View 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

View 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_ */

View 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;

View 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)

View 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);
}

View 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;
}

View 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;

View 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;
}

View 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);
return mangle_fns->lookup_name_from_8_3(ctx, in, out, p);
}
BOOL mangle_check_cache_alloc(const char *name, char **presult,
const struct share_params *p)
{
pstring tmp;
char *result;
pstrcpy(tmp, name);
if (!mangle_check_cache(tmp, sizeof(pstring)-1, p)
|| !(result = SMB_STRDUP(tmp))) {
return False;
}
*presult = result;
return True;
}
/*
map a long filename to a 8.3 name.
/*
mangle a long filename to a 8.3 name.
Return True if we did mangle the name (ie. out is filled in).
False on error.
JRA.
*/
void mangle_map(pstring OutName, BOOL need83, BOOL cache83,
BOOL name_to_8_3(const char *in,
char out[13],
BOOL cache83,
const struct share_params *p)
{
/* name mangling can be disabled for speed, in which case
we just truncate the string */
if (!lp_manglednames(p)) {
if (need83) {
string_truncate(OutName, 12);
}
return;
safe_strcpy(out,in,12);
return True;
}
/* invoke the inane "mangled map" code */
mangle_map_filename(OutName, p);
mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p);
return mangle_fns->name_to_8_3(in,
out,
cache83,
lp_defaultcase(p->service),
p);
}

View 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(tmp != NULL) {
cache_mangled_name(OutName, tmp);
SAFE_FREE(tmp);
}
/* 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;
}
DEBUG(5,("name_map() ==> [%s]\n", OutName));
SAFE_FREE(OutName_ucs2);
SAFE_FREE(in_ucs2);
if (!to_8_3(in, out, default_case)) {
return False;
}
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 */

View 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)

View 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;

View 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. */

File diff suppressed because it is too large Load Diff

View 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);
}
/***************************************************************

View 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;