diff options
author | Gerald Carter <jerry@samba.org> | 2004-10-25 19:25:54 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2004-10-25 19:25:54 +0000 |
commit | 317ab676bf28d3922dc0fba02e908a766035872f (patch) | |
tree | d9ea00a371f92740e58b95991b4b56723454304d /source/smbd/trans2.c | |
parent | 943c0aaaeb5a24a9501a164e9a765384e8e8a2ff (diff) | |
download | samba-317ab676bf28d3922dc0fba02e908a766035872f.tar.gz samba-317ab676bf28d3922dc0fba02e908a766035872f.tar.xz samba-317ab676bf28d3922dc0fba02e908a766035872f.zip |
r3220: merging current 3.0 code to release branch
Diffstat (limited to 'source/smbd/trans2.c')
-rw-r--r-- | source/smbd/trans2.c | 128 |
1 files changed, 74 insertions, 54 deletions
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index f3176940c2f..9b1f2aa2105 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -31,20 +31,43 @@ extern uint32 global_client_caps; extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) +#define DIR_ENTRY_SAFETY_MARGIN 4096 + +/******************************************************************** + Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary. + Only do this for Windows clients. +********************************************************************/ + +SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val) +{ + /* Only roundup for Windows clients. */ + enum remote_arch_types ra_type = get_remote_arch(); + if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { + val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE); + } + return val; +} + +/******************************************************************** + Given a stat buffer return the allocated size on disk, taking into + account sparse files. +********************************************************************/ -/* given a stat buffer return the allocated size on disk, taking into - account sparse files */ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) { SMB_BIG_UINT ret; + #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks; #else ret = (SMB_BIG_UINT)get_file_size(*sbuf); #endif + if (!ret && fsp && fsp->initial_allocation_size) ret = fsp->initial_allocation_size; - ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE); + + ret = smb_roundup(ret); + return ret; } @@ -734,32 +757,6 @@ static uint32 unix_filetype(mode_t mode) } /**************************************************************************** - Return the major devicenumber for UNIX extensions. -****************************************************************************/ - -static uint32 unix_dev_major(SMB_DEV_T dev) -{ -#if defined(HAVE_DEVICE_MAJOR_FN) - return (uint32)major(dev); -#else - return (uint32)(dev >> 8); -#endif -} - -/**************************************************************************** - Return the minor devicenumber for UNIX extensions. -****************************************************************************/ - -static uint32 unix_dev_minor(SMB_DEV_T dev) -{ -#if defined(HAVE_DEVICE_MINOR_FN) - return (uint32)minor(dev); -#else - return (uint32)(dev & 0xff); -#endif -} - -/**************************************************************************** Map wire perms onto standard UNIX permissions. Obey share restrictions. ****************************************************************************/ @@ -1360,7 +1357,12 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, info_level, max_data_bytes)); - + + if (!maxentries) { + /* W2K3 seems to treat zero as 1. */ + maxentries = 1; + } + switch (info_level) { case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: @@ -1409,12 +1411,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); - pdata = Realloc(*ppdata, max_data_bytes + 1024); + pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if( pdata == NULL ) return(ERROR_DOS(ERRDOS,ERRnomem)); *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); + memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = Realloc(*pparams, 10); @@ -1586,6 +1588,11 @@ resume_key = %d resume name = %s continue=%d level = %d\n", dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, requires_resume_key, resume_key, resume_name, continue_bit, info_level)); + if (!maxentries) { + /* W2K3 seems to treat zero as 1. */ + maxentries = 1; + } + switch (info_level) { case SMB_INFO_STANDARD: case SMB_INFO_QUERY_EA_SIZE: @@ -1602,12 +1609,12 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return ERROR_DOS(ERRDOS,ERRunknownlevel); } - pdata = Realloc( *ppdata, max_data_bytes + 1024); + pdata = Realloc( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(pdata == NULL) return ERROR_DOS(ERRDOS,ERRnomem); *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); + memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = Realloc(*pparams, 6*SIZEOFWORD); @@ -1818,12 +1825,12 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf return ERROR_DOS(ERRSRV,ERRinvdevice); } - pdata = Realloc(*ppdata, max_data_bytes + 1024); + pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if ( pdata == NULL ) return ERROR_DOS(ERRDOS,ERRnomem); *ppdata = pdata; - memset((char *)pdata,'\0',max_data_bytes + 1024); + memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); switch (info_level) { case SMB_INFO_ALLOCATION: @@ -2389,7 +2396,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, return ERROR_DOS(ERRDOS,ERRnomem); *pparams = params; memset((char *)params,'\0',2); - data_size = max_data_bytes + 1024; + data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; pdata = Realloc(*ppdata, data_size); if ( pdata == NULL ) return ERROR_DOS(ERRDOS,ERRnomem); @@ -2804,25 +2811,38 @@ static int call_trans2qfilepathinfo(connection_struct *conn, open_file_shared. JRA. ****************************************************************************/ -NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close) +NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode) { - /* - * Only allow delete on close for writable shares. - */ + if (delete_on_close) { + /* + * Only allow delete on close for writable files. + */ - if (delete_on_close && !CAN_WRITE(fsp->conn)) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n", + if (dosmode & aRONLY) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n", fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } - /* - * Only allow delete on close for files/directories opened with delete intent. - */ + return NT_STATUS_CANNOT_DELETE; + } + + /* + * Only allow delete on close for writable shares. + */ + + if (!CAN_WRITE(fsp->conn)) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; + } + + /* + * Only allow delete on close for files/directories opened with delete intent. + */ - if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) { - DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n", + if (!(fsp->desired_access & DELETE_ACCESS)) { + DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n", fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_ACCESS_DENIED; + } } if(fsp->is_directory) { @@ -2859,7 +2879,7 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close) return NT_STATUS_ACCESS_DENIED; if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n", + DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n", fsp->fsp_name )); unlock_share_entry_fsp(fsp); return NT_STATUS_ACCESS_DENIED; @@ -3189,7 +3209,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, fname, (double)allocation_size )); if (allocation_size) - allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); + allocation_size = smb_roundup(allocation_size); if(allocation_size != get_file_size(sbuf)) { SMB_STRUCT_STAT new_sbuf; @@ -3279,7 +3299,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadfid)); - status = set_delete_on_close_internal(fsp, delete_on_close); + status = set_delete_on_close_internal(fsp, delete_on_close, dosmode); if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) return ERROR_NT(status); |