2007-09-12 03:57:59 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Main SMB reply routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
2001-09-16 10:35:35 +04:00
Copyright ( C ) Andrew Bartlett 2001
2007-01-13 02:47:16 +03:00
Copyright ( C ) Jeremy Allison 1992 - 2007.
2007-08-02 22:28:41 +04:00
Copyright ( C ) Volker Lendecke 2007
2001-09-16 10:35:35 +04:00
1996-05-04 11:50:46 +04:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2007-09-12 03:57:59 +04:00
1996-05-04 11:50:46 +04:00
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 .
2007-09-12 03:57:59 +04:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 11:50:46 +04:00
*/
/*
This file handles most of the reply_ calls that the server
makes to handle specific protocols
*/
# include "includes.h"
/* look in server.c for some explanation of these variables */
2004-11-25 03:07:01 +03:00
extern enum protocol_types Protocol ;
1997-02-28 23:39:36 +03:00
extern int max_recv ;
1999-12-13 16:27:58 +03:00
unsigned int smb_echo_count = 0 ;
2004-11-24 06:42:01 +03:00
extern uint32 global_client_caps ;
1996-05-04 11:50:46 +04:00
2005-04-06 20:28:04 +04:00
extern struct current_user current_user ;
2007-10-19 04:40:25 +04:00
extern bool global_encrypted_passwords_negotiated ;
2001-09-16 10:35:35 +04:00
2005-03-25 01:32:52 +03:00
/****************************************************************************
Ensure we check the path in * exactly * the same way as W2K for a findfirst / findnext
path or anything including wildcards .
We ' re assuming here that ' / ' is not the second byte in any multibyte char
set ( a safe assumption ) . ' \\ ' * may * be the second byte in a multibyte char
set .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-12 20:55:24 +03:00
/* Custom version for processing POSIX paths. */
# define IS_PATH_SEP(c,posix_only) ((c) == ' / ' || (!(posix_only) && (c) == '\\'))
2007-06-16 22:07:44 +04:00
static NTSTATUS check_path_syntax_internal ( char * path ,
2007-10-19 04:40:25 +04:00
bool posix_path ,
bool * p_last_component_contains_wcard )
2005-03-25 01:32:52 +03:00
{
2007-06-16 22:07:44 +04:00
char * d = path ;
const char * s = path ;
2005-03-25 01:32:52 +03:00
NTSTATUS ret = NT_STATUS_OK ;
2007-10-19 04:40:25 +04:00
bool start_of_name_component = True ;
2005-03-25 01:32:52 +03:00
2007-01-13 23:26:53 +03:00
* p_last_component_contains_wcard = False ;
2005-10-31 23:11:58 +03:00
2005-03-25 01:32:52 +03:00
while ( * s ) {
2007-03-12 20:55:24 +03:00
if ( IS_PATH_SEP ( * s , posix_path ) ) {
2005-03-25 01:32:52 +03:00
/*
2007-01-14 14:25:42 +03:00
* Safe to assume is not the second part of a mb char
* as this is handled below .
2005-03-25 01:32:52 +03:00
*/
/* Eat multiple '/' or '\\' */
2007-03-12 20:55:24 +03:00
while ( IS_PATH_SEP ( * s , posix_path ) ) {
2005-03-25 01:32:52 +03:00
s + + ;
}
2007-06-16 22:07:44 +04:00
if ( ( d ! = path ) & & ( * s ! = ' \0 ' ) ) {
2005-03-25 01:32:52 +03:00
/* We only care about non-leading or trailing '/' or '\\' */
* d + + = ' / ' ;
}
start_of_name_component = True ;
2007-01-13 02:47:16 +03:00
/* New component. */
2007-01-13 23:26:53 +03:00
* p_last_component_contains_wcard = False ;
2005-03-25 01:32:52 +03:00
continue ;
}
if ( start_of_name_component ) {
2007-03-12 20:55:24 +03:00
if ( ( s [ 0 ] = = ' . ' ) & & ( s [ 1 ] = = ' . ' ) & & ( IS_PATH_SEP ( s [ 2 ] , posix_path ) | | s [ 2 ] = = ' \0 ' ) ) {
2005-03-25 01:32:52 +03:00
/* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
/*
* No mb char starts with ' . ' so we ' re safe checking the directory separator here .
*/
/* If we just added a '/' - delete it */
2007-06-16 22:07:44 +04:00
if ( ( d > path ) & & ( * ( d - 1 ) = = ' / ' ) ) {
2005-03-25 01:32:52 +03:00
* ( d - 1 ) = ' \0 ' ;
d - - ;
}
/* Are we at the start ? Can't go back further if so. */
2007-06-16 22:07:44 +04:00
if ( d < = path ) {
2005-03-25 01:32:52 +03:00
ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD ;
break ;
}
/* Go back one level... */
/* We know this is safe as '/' cannot be part of a mb sequence. */
/* NOTE - if this assumption is invalid we are not in good shape... */
/* Decrement d first as d points to the *next* char to write into. */
2007-06-16 22:07:44 +04:00
for ( d - - ; d > path ; d - - ) {
2005-03-25 01:32:52 +03:00
if ( * d = = ' / ' )
break ;
}
s + = 2 ; /* Else go past the .. */
/* We're still at the start of a name component, just the previous one. */
continue ;
2007-03-12 20:55:24 +03:00
} else if ( ( s [ 0 ] = = ' . ' ) & & ( ( s [ 1 ] = = ' \0 ' ) | | IS_PATH_SEP ( s [ 1 ] , posix_path ) ) ) {
if ( posix_path ) {
2007-01-13 02:47:16 +03:00
/* Eat the '.' */
s + + ;
continue ;
}
2004-09-04 00:05:29 +04:00
}
2007-01-13 02:47:16 +03:00
2005-03-25 01:32:52 +03:00
}
if ( ! ( * s & 0x80 ) ) {
2007-03-12 20:55:24 +03:00
if ( ! posix_path ) {
2007-01-13 02:47:16 +03:00
if ( * s < = 0x1f ) {
return NT_STATUS_OBJECT_NAME_INVALID ;
}
2005-10-31 23:11:58 +03:00
switch ( * s ) {
case ' * ' :
case ' ? ' :
case ' < ' :
case ' > ' :
case ' " ' :
2007-01-13 23:26:53 +03:00
* p_last_component_contains_wcard = True ;
2005-10-31 23:11:58 +03:00
break ;
default :
break ;
}
}
2005-03-25 01:32:52 +03:00
* d + + = * s + + ;
2004-09-04 00:05:29 +04:00
} else {
2006-09-21 21:00:07 +04:00
size_t siz ;
/* Get the size of the next MB character. */
next_codepoint ( s , & siz ) ;
switch ( siz ) {
case 5 :
* d + + = * s + + ;
/*fall through*/
2005-03-25 01:32:52 +03:00
case 4 :
* d + + = * s + + ;
2006-04-10 19:33:04 +04:00
/*fall through*/
2005-03-25 01:32:52 +03:00
case 3 :
* d + + = * s + + ;
2006-04-10 19:33:04 +04:00
/*fall through*/
2005-03-25 01:32:52 +03:00
case 2 :
* d + + = * s + + ;
2006-04-10 19:33:04 +04:00
/*fall through*/
2005-03-25 01:32:52 +03:00
case 1 :
* d + + = * s + + ;
break ;
default :
2007-01-13 02:47:16 +03:00
DEBUG ( 0 , ( " check_path_syntax_internal: character length assumptions invalid ! \n " ) ) ;
2005-03-25 01:32:52 +03:00
* d = ' \0 ' ;
return NT_STATUS_INVALID_PARAMETER ;
2004-09-04 00:05:29 +04:00
}
}
2005-03-25 01:32:52 +03:00
start_of_name_component = False ;
}
2004-03-03 23:55:59 +03:00
* d = ' \0 ' ;
return ret ;
2003-08-13 07:28:06 +04:00
}
2005-05-06 17:26:54 +04:00
/****************************************************************************
2007-01-13 02:47:16 +03:00
Ensure we check the path in * exactly * the same way as W2K for regular pathnames .
No wildcards allowed .
2005-05-06 17:26:54 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-16 22:07:44 +04:00
NTSTATUS check_path_syntax ( char * path )
2005-05-06 17:26:54 +04:00
{
2007-10-19 04:40:25 +04:00
bool ignore ;
2007-06-16 22:07:44 +04:00
return check_path_syntax_internal ( path , False , & ignore ) ;
2007-01-13 02:47:16 +03:00
}
2005-05-06 17:26:54 +04:00
2007-01-13 02:47:16 +03:00
/****************************************************************************
Ensure we check the path in * exactly * the same way as W2K for regular pathnames .
Wildcards allowed - p_contains_wcard returns true if the last component contained
a wildcard .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-06 17:26:54 +04:00
2007-10-19 04:40:25 +04:00
NTSTATUS check_path_syntax_wcard ( char * path , bool * p_contains_wcard )
2007-01-13 02:47:16 +03:00
{
2007-06-16 22:07:44 +04:00
return check_path_syntax_internal ( path , False , p_contains_wcard ) ;
2007-01-13 02:47:16 +03:00
}
2005-05-06 17:26:54 +04:00
2007-01-13 02:47:16 +03:00
/****************************************************************************
Check the path for a POSIX client .
We ' re assuming here that ' / ' is not the second byte in any multibyte char
set ( a safe assumption ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-06 17:26:54 +04:00
2007-06-16 22:19:42 +04:00
NTSTATUS check_path_syntax_posix ( char * path )
2007-01-13 02:47:16 +03:00
{
2007-10-19 04:40:25 +04:00
bool ignore ;
2007-06-16 22:07:44 +04:00
return check_path_syntax_internal ( path , True , & ignore ) ;
2005-05-06 17:26:54 +04:00
}
2005-10-31 23:11:58 +03:00
/****************************************************************************
Pull a string and check the path allowing a wilcard - provide for error return .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-12 03:57:59 +04:00
size_t srvstr_get_path_wcard ( TALLOC_CTX * ctx ,
const char * inbuf ,
uint16 smb_flags2 ,
char * * pp_dest ,
const char * src ,
size_t src_len ,
int flags ,
NTSTATUS * err ,
2007-10-19 04:40:25 +04:00
bool * contains_wcard )
2005-10-31 23:11:58 +03:00
{
size_t ret ;
2007-09-12 03:57:59 +04:00
* pp_dest = NULL ;
2005-10-31 23:11:58 +03:00
if ( src_len = = 0 ) {
2007-09-12 03:57:59 +04:00
ret = srvstr_pull_buf_talloc ( ctx ,
inbuf ,
smb_flags2 ,
pp_dest ,
src ,
flags ) ;
2005-10-31 23:11:58 +03:00
} else {
2007-09-12 03:57:59 +04:00
ret = srvstr_pull_talloc ( ctx ,
inbuf ,
smb_flags2 ,
pp_dest ,
src ,
src_len ,
flags ) ;
}
if ( ! * pp_dest ) {
* err = NT_STATUS_INVALID_PARAMETER ;
return ret ;
2005-10-31 23:11:58 +03:00
}
* contains_wcard = False ;
2007-07-06 20:39:58 +04:00
if ( smb_flags2 & FLAGS2_DFS_PATHNAMES ) {
2007-09-12 03:57:59 +04:00
/*
2007-03-12 20:55:24 +03:00
* For a DFS path the function parse_dfs_path ( )
* will do the path processing , just make a copy .
*/
* err = NT_STATUS_OK ;
return ret ;
}
2005-10-31 23:11:58 +03:00
if ( lp_posix_pathnames ( ) ) {
2007-09-12 03:57:59 +04:00
* err = check_path_syntax_posix ( * pp_dest ) ;
2005-10-31 23:11:58 +03:00
} else {
2007-09-12 03:57:59 +04:00
* err = check_path_syntax_wcard ( * pp_dest , contains_wcard ) ;
2005-10-31 23:11:58 +03:00
}
2006-07-11 22:01:26 +04:00
2005-10-31 23:11:58 +03:00
return ret ;
}
2003-10-09 03:21:36 +04:00
/****************************************************************************
Pull a string and check the path - provide for error return .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-12 03:57:59 +04:00
size_t srvstr_get_path ( TALLOC_CTX * ctx ,
const char * inbuf ,
uint16 smb_flags2 ,
char * * pp_dest ,
const char * src ,
size_t src_len ,
int flags ,
NTSTATUS * err )
2003-10-09 03:21:36 +04:00
{
2004-03-09 18:29:16 +03:00
size_t ret ;
2007-09-12 03:57:59 +04:00
* pp_dest = NULL ;
2004-03-03 23:55:59 +03:00
if ( src_len = = 0 ) {
2007-09-12 03:57:59 +04:00
ret = srvstr_pull_buf_talloc ( ctx ,
inbuf ,
smb_flags2 ,
pp_dest ,
src ,
flags ) ;
2004-03-03 23:55:59 +03:00
} else {
2007-09-12 03:57:59 +04:00
ret = srvstr_pull_talloc ( ctx ,
inbuf ,
smb_flags2 ,
pp_dest ,
src ,
src_len ,
flags ) ;
}
if ( ! * pp_dest ) {
* err = NT_STATUS_INVALID_PARAMETER ;
return ret ;
2004-03-03 23:55:59 +03:00
}
2007-03-12 20:55:24 +03:00
2007-07-05 20:36:15 +04:00
if ( smb_flags2 & FLAGS2_DFS_PATHNAMES ) {
2007-09-12 03:57:59 +04:00
/*
2007-03-12 20:55:24 +03:00
* For a DFS path the function parse_dfs_path ( )
* will do the path processing , just make a copy .
*/
* err = NT_STATUS_OK ;
return ret ;
}
2005-06-23 01:20:41 +04:00
if ( lp_posix_pathnames ( ) ) {
2007-09-12 03:57:59 +04:00
* err = check_path_syntax_posix ( * pp_dest ) ;
2005-03-25 01:32:52 +03:00
} else {
2007-09-12 03:57:59 +04:00
* err = check_path_syntax ( * pp_dest ) ;
2005-03-25 01:32:52 +03:00
}
2006-07-11 22:01:26 +04:00
2003-10-09 03:21:36 +04:00
return ret ;
}
2007-08-02 23:50:56 +04:00
/****************************************************************************
2007-09-08 00:57:01 +04:00
Check if we have a correct fsp pointing to a file . Basic check for open fsp .
2007-08-02 23:50:56 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 05:45:26 +04:00
2007-10-19 04:40:25 +04:00
bool check_fsp_open ( connection_struct * conn , struct smb_request * req ,
2007-08-02 23:50:56 +04:00
files_struct * fsp , struct current_user * user )
{
if ( ! ( fsp ) | | ! ( conn ) ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return False ;
}
2007-08-10 13:53:42 +04:00
if ( ( ( conn ) ! = ( fsp ) - > conn ) | | user - > vuid ! = ( fsp ) - > vuid ) {
2007-08-02 23:50:56 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return False ;
}
2007-09-08 00:57:01 +04:00
return True ;
}
/****************************************************************************
Check if we have a correct fsp pointing to a file . Replacement for the
CHECK_FSP macro .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool check_fsp ( connection_struct * conn , struct smb_request * req ,
2007-09-08 00:57:01 +04:00
files_struct * fsp , struct current_user * user )
{
if ( ! check_fsp_open ( conn , req , fsp , user ) ) {
return False ;
}
2007-08-02 23:50:56 +04:00
if ( ( fsp ) - > is_directory ) {
reply_nterror ( req , NT_STATUS_INVALID_DEVICE_REQUEST ) ;
return False ;
}
if ( ( fsp ) - > fh - > fd = = - 1 ) {
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return False ;
}
( fsp ) - > num_smb_operations + + ;
return True ;
}
2007-08-13 23:58:28 +04:00
/****************************************************************************
Check if we have a correct fsp . Replacement for the FSP_BELONGS_CONN macro
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool fsp_belongs_conn ( connection_struct * conn , struct smb_request * req ,
2007-08-13 23:58:28 +04:00
files_struct * fsp , struct current_user * user )
{
if ( ( fsp ) & & ( conn ) & & ( ( conn ) = = ( fsp ) - > conn )
& & ( current_user . vuid = = ( fsp ) - > vuid ) ) {
return True ;
}
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return False ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2007-07-23 13:36:09 +04:00
Reply to a ( netbios - level ) special message .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-07-23 13:36:09 +04:00
void reply_special ( char * inbuf )
1996-05-04 11:50:46 +04:00
{
1997-09-18 11:05:43 +04:00
int msg_type = CVAL ( inbuf , 0 ) ;
int msg_flags = CVAL ( inbuf , 1 ) ;
2004-03-13 03:28:53 +03:00
fstring name1 , name2 ;
1997-10-28 09:07:07 +03:00
char name_type = 0 ;
2007-07-23 13:36:09 +04:00
/*
* We only really use 4 bytes of the outbuf , but for the smb_setlen
* calculation & friends ( send_smb uses that ) we need the full smb
* header .
*/
char outbuf [ smb_size ] ;
1997-09-18 11:05:43 +04:00
2007-10-19 04:40:25 +04:00
static bool already_got_session = False ;
2002-08-17 19:27:10 +04:00
1997-09-18 11:05:43 +04:00
* name1 = * name2 = 0 ;
2007-07-23 13:36:09 +04:00
memset ( outbuf , ' \0 ' , sizeof ( outbuf ) ) ;
1998-08-04 05:01:26 +04:00
2007-10-11 00:34:30 +04:00
smb_setlen ( outbuf , 0 ) ;
1997-09-18 11:05:43 +04:00
switch ( msg_type ) {
1997-10-28 09:07:07 +03:00
case 0x81 : /* session request */
2002-08-17 19:27:10 +04:00
if ( already_got_session ) {
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " multiple session request not permitted " ) ;
2002-08-17 19:27:10 +04:00
}
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , 0 , 0x82 ) ;
SCVAL ( outbuf , 3 , 0 ) ;
1997-10-28 09:07:07 +03:00
if ( name_len ( inbuf + 4 ) > 50 | |
name_len ( inbuf + 4 + name_len ( inbuf + 4 ) ) > 50 ) {
DEBUG ( 0 , ( " Invalid name length in session request \n " ) ) ;
2007-07-23 13:36:09 +04:00
return ;
1997-10-28 09:07:07 +03:00
}
name_extract ( inbuf , 4 , name1 ) ;
2003-07-27 07:29:40 +04:00
name_type = name_extract ( inbuf , 4 + name_len ( inbuf + 4 ) , name2 ) ;
1997-09-18 11:05:43 +04:00
DEBUG ( 2 , ( " netbios connect: name1=%s name2=%s \n " ,
name1 , name2 ) ) ;
1997-09-26 22:55:29 +04:00
2003-03-18 12:52:55 +03:00
set_local_machine_name ( name1 , True ) ;
set_remote_machine_name ( name2 , True ) ;
1997-09-26 22:55:29 +04:00
2003-07-27 07:29:40 +04:00
DEBUG ( 2 , ( " netbios connect: local=%s remote=%s, name type = %x \n " ,
get_local_machine_name ( ) , get_remote_machine_name ( ) ,
name_type ) ) ;
2001-06-24 00:01:23 +04:00
1997-10-28 09:07:07 +03:00
if ( name_type = = ' R ' ) {
/* We are being asked for a pathworks session ---
no thanks ! */
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , 0 , 0x83 ) ;
1997-10-28 09:07:07 +03:00
break ;
}
1997-09-26 22:55:29 +04:00
2001-01-24 01:13:41 +03:00
/* only add the client's machine name to the list
of possibly valid usernames if we are operating
in share mode security */
if ( lp_security ( ) = = SEC_SHARE ) {
2002-08-17 19:27:10 +04:00
add_session_user ( get_remote_machine_name ( ) ) ;
2001-01-24 01:13:41 +03:00
}
1997-09-26 22:55:29 +04:00
1997-10-28 09:07:07 +03:00
reload_services ( True ) ;
reopen_logs ( ) ;
1997-09-26 22:55:29 +04:00
2002-08-17 19:27:10 +04:00
already_got_session = True ;
1997-10-28 09:07:07 +03:00
break ;
1997-09-18 11:05:43 +04:00
case 0x89 : /* session keepalive request
( some old clients produce this ? ) */
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , 0 , SMBkeepalive ) ;
SCVAL ( outbuf , 3 , 0 ) ;
1997-09-18 11:05:43 +04:00
break ;
case 0x82 : /* positive session response */
case 0x83 : /* negative session response */
case 0x84 : /* retarget session response */
DEBUG ( 0 , ( " Unexpected session response \n " ) ) ;
break ;
2001-10-21 03:34:40 +04:00
case SMBkeepalive : /* session keepalive */
1997-09-18 11:05:43 +04:00
default :
2007-07-23 13:36:09 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
1997-09-18 11:05:43 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 5 , ( " init msg_type=0x%x msg_flags=0x%x \n " ,
msg_type , msg_flags ) ) ;
2007-07-23 13:36:09 +04:00
send_smb ( smbd_server_fd ( ) , outbuf ) ;
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a tcon .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-15 14:29:47 +04:00
void reply_tcon ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-08-17 19:27:10 +04:00
const char * service ;
2007-07-13 05:22:09 +04:00
char * service_buf = NULL ;
char * password = NULL ;
char * dev = NULL ;
1998-08-14 21:38:29 +04:00
int pwlen = 0 ;
2001-09-24 03:07:53 +04:00
NTSTATUS nt_status ;
2001-03-13 09:55:47 +03:00
char * p ;
2001-10-31 13:46:25 +03:00
DATA_BLOB password_blob ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-07-13 05:22:09 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBtcon ) ;
1998-08-14 21:38:29 +04:00
2007-08-17 05:55:58 +04:00
if ( smb_buflen ( req - > inbuf ) < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBtcon ) ;
return ;
}
2007-08-15 14:29:47 +04:00
p = smb_buf ( req - > inbuf ) + 1 ;
2007-09-11 22:31:29 +04:00
p + = srvstr_pull_buf_talloc ( ctx , req - > inbuf , req - > flags2 ,
2007-08-15 14:29:47 +04:00
& service_buf , p , STR_TERMINATE ) + 1 ;
2007-09-11 22:31:29 +04:00
pwlen = srvstr_pull_buf_talloc ( ctx , req - > inbuf , req - > flags2 ,
2007-08-15 14:29:47 +04:00
& password , p , STR_TERMINATE ) + 1 ;
2001-10-31 13:46:25 +03:00
p + = pwlen ;
2007-09-11 22:31:29 +04:00
p + = srvstr_pull_buf_talloc ( ctx , req - > inbuf , req - > flags2 ,
2007-08-15 14:29:47 +04:00
& dev , p , STR_TERMINATE ) + 1 ;
1998-08-14 21:38:29 +04:00
2007-07-13 05:22:09 +04:00
if ( service_buf = = NULL | | password = = NULL | | dev = = NULL ) {
2007-08-15 14:29:47 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
2007-07-13 05:22:09 +04:00
}
2002-08-17 19:27:10 +04:00
p = strrchr_m ( service_buf , ' \\ ' ) ;
2001-03-13 09:55:47 +03:00
if ( p ) {
2002-08-17 19:27:10 +04:00
service = p + 1 ;
} else {
service = service_buf ;
2001-03-13 09:55:47 +03:00
}
2001-10-31 13:46:25 +03:00
password_blob = data_blob ( password , pwlen + 1 ) ;
2007-08-15 14:29:47 +04:00
conn = make_connection ( service , password_blob , dev , req - > vuid , & nt_status ) ;
2001-10-31 15:28:40 +03:00
2001-11-01 08:02:41 +03:00
data_blob_clear_free ( & password_blob ) ;
2007-07-13 05:22:09 +04:00
1998-08-14 21:38:29 +04:00
if ( ! conn ) {
2007-08-15 14:29:47 +04:00
reply_nterror ( req , nt_status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
2007-07-13 05:22:09 +04:00
2007-08-15 14:29:47 +04:00
reply_outbuf ( req , 2 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , max_recv ) ;
SSVAL ( req - > outbuf , smb_vwv1 , conn - > cnum ) ;
SSVAL ( req - > outbuf , smb_tid , conn - > cnum ) ;
2007-07-13 05:22:09 +04:00
2007-08-25 23:47:57 +04:00
DEBUG ( 3 , ( " tcon service=%s cnum=%d \n " ,
2001-09-15 16:55:59 +04:00
service , conn - > cnum ) ) ;
2007-07-13 05:22:09 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a tcon and X .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-06-22 04:57:59 +04:00
2007-07-23 15:38:29 +04:00
void reply_tcon_and_X ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-07-13 05:22:09 +04:00
char * service = NULL ;
2001-10-31 13:46:25 +03:00
DATA_BLOB password ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-03-28 01:27:53 +03:00
/* what the cleint thinks the device is */
2007-07-13 05:22:09 +04:00
char * client_devicetype = NULL ;
2003-03-28 01:27:53 +03:00
/* what the server tells the client the share represents */
const char * server_devicetype ;
2001-09-24 03:07:53 +04:00
NTSTATUS nt_status ;
2007-07-23 15:38:29 +04:00
int passlen ;
2007-07-13 05:22:09 +04:00
char * path = NULL ;
2001-03-10 14:38:27 +03:00
char * p , * q ;
2007-07-23 15:38:29 +04:00
uint16 tcon_flags ;
2001-10-31 13:46:25 +03:00
2007-07-13 05:22:09 +04:00
START_PROFILE ( SMBtconX ) ;
1998-06-10 23:45:13 +04:00
2007-07-23 15:38:29 +04:00
if ( req - > wct < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
passlen = SVAL ( req - > inbuf , smb_vwv3 ) ;
tcon_flags = SVAL ( req - > inbuf , smb_vwv2 ) ;
1998-08-14 21:38:29 +04:00
/* we might have to close an old one */
2007-07-23 15:38:29 +04:00
if ( ( tcon_flags & 0x1 ) & & conn ) {
close_cnum ( conn , req - > vuid ) ;
1998-08-14 21:38:29 +04:00
}
1998-06-10 23:45:13 +04:00
2007-07-23 15:38:29 +04:00
if ( ( passlen > MAX_PASS_LEN ) | | ( passlen > = smb_buflen ( req - > inbuf ) ) ) {
reply_doserror ( req , ERRDOS , ERRbuftoosmall ) ;
END_PROFILE ( SMBtconX ) ;
return ;
1998-08-14 21:38:29 +04:00
}
2007-07-13 05:22:09 +04:00
2001-10-31 13:46:25 +03:00
if ( global_encrypted_passwords_negotiated ) {
2007-07-23 15:38:29 +04:00
password = data_blob ( smb_buf ( req - > inbuf ) , passlen ) ;
2007-04-17 06:14:28 +04:00
if ( lp_security ( ) = = SEC_SHARE ) {
/*
* Security = share always has a pad byte
* after the password .
*/
2007-07-23 15:38:29 +04:00
p = smb_buf ( req - > inbuf ) + passlen + 1 ;
2007-04-17 06:14:28 +04:00
} else {
2007-07-23 15:38:29 +04:00
p = smb_buf ( req - > inbuf ) + passlen ;
2007-04-17 06:14:28 +04:00
}
2001-10-31 13:46:25 +03:00
} else {
2007-07-23 15:38:29 +04:00
password = data_blob ( smb_buf ( req - > inbuf ) , passlen + 1 ) ;
2001-10-31 13:46:25 +03:00
/* Ensure correct termination */
2007-04-17 06:14:28 +04:00
password . data [ passlen ] = 0 ;
2007-07-23 15:38:29 +04:00
p = smb_buf ( req - > inbuf ) + passlen + 1 ;
2001-10-31 13:46:25 +03:00
}
2007-07-23 15:38:29 +04:00
p + = srvstr_pull_buf_talloc ( ctx , req - > inbuf , req - > flags2 , & path , p ,
2007-07-13 05:22:09 +04:00
STR_TERMINATE ) ;
if ( path = = NULL ) {
2007-07-23 15:38:29 +04:00
data_blob_clear_free ( & password ) ;
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2007-07-13 05:22:09 +04:00
}
1996-05-04 11:50:46 +04:00
2001-08-22 17:08:01 +04:00
/*
* the service name can be either : \ \ server \ share
* or share directly like on the DELL PowerVault 705
*/
2007-07-13 05:22:09 +04:00
if ( * path = = ' \\ ' ) {
2001-08-22 17:08:01 +04:00
q = strchr_m ( path + 2 , ' \\ ' ) ;
if ( ! q ) {
2007-07-23 15:38:29 +04:00
data_blob_clear_free ( & password ) ;
reply_doserror ( req , ERRDOS , ERRnosuchshare ) ;
2001-08-22 17:08:01 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2001-08-22 17:08:01 +04:00
}
2007-07-13 05:22:09 +04:00
service = q + 1 ;
} else {
service = path ;
}
2007-07-23 15:38:29 +04:00
p + = srvstr_pull_talloc ( ctx , req - > inbuf , req - > flags2 ,
& client_devicetype , p ,
MIN ( 6 , smb_bufrem ( req - > inbuf , p ) ) , STR_ASCII ) ;
2007-07-13 05:22:09 +04:00
if ( client_devicetype = = NULL ) {
2007-07-23 15:38:29 +04:00
data_blob_clear_free ( & password ) ;
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1999-12-13 16:27:58 +03:00
2003-03-28 01:27:53 +03:00
DEBUG ( 4 , ( " Client requested device type [%s] for share [%s] \n " , client_devicetype , service ) ) ;
1998-12-01 01:42:13 +03:00
2007-07-23 15:38:29 +04:00
conn = make_connection ( service , password , client_devicetype ,
req - > vuid , & nt_status ) ;
2007-07-13 05:22:09 +04:00
2001-10-31 15:28:40 +03:00
data_blob_clear_free ( & password ) ;
2001-11-01 08:02:41 +03:00
2000-10-06 07:21:49 +04:00
if ( ! conn ) {
2007-07-23 15:38:29 +04:00
reply_nterror ( req , nt_status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1997-08-31 18:14:22 +04:00
2003-03-28 01:27:53 +03:00
if ( IS_IPC ( conn ) )
server_devicetype = " IPC " ;
else if ( IS_PRINT ( conn ) )
2003-04-12 03:28:15 +04:00
server_devicetype = " LPT1: " ;
2007-07-13 05:22:09 +04:00
else
2003-03-28 01:27:53 +03:00
server_devicetype = " A: " ;
1998-08-14 21:38:29 +04:00
if ( Protocol < PROTOCOL_NT1 ) {
2007-07-23 15:38:29 +04:00
reply_outbuf ( req , 2 , 0 ) ;
if ( message_push_string ( & req - > outbuf , server_devicetype ,
STR_TERMINATE | STR_ASCII ) = = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
1998-08-14 21:38:29 +04:00
} else {
2001-03-13 06:45:09 +03:00
/* NT sets the fstype of IPC$ to the null string */
2003-04-23 15:11:02 +04:00
const char * fstype = IS_IPC ( conn ) ? " " : lp_fstype ( SNUM ( conn ) ) ;
2007-07-13 05:22:09 +04:00
2007-04-07 09:49:24 +04:00
if ( tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE ) {
/* Return permissions. */
uint32 perm1 = 0 ;
uint32 perm2 = 0 ;
2007-07-23 15:38:29 +04:00
reply_outbuf ( req , 7 , 0 ) ;
2007-04-07 09:49:24 +04:00
if ( IS_IPC ( conn ) ) {
perm1 = FILE_ALL_ACCESS ;
perm2 = FILE_ALL_ACCESS ;
} else {
perm1 = CAN_WRITE ( conn ) ?
SHARE_ALL_ACCESS :
SHARE_READ_ONLY ;
}
2007-07-23 15:38:29 +04:00
SIVAL ( req - > outbuf , smb_vwv3 , perm1 ) ;
SIVAL ( req - > outbuf , smb_vwv5 , perm2 ) ;
2007-04-07 09:49:24 +04:00
} else {
2007-07-23 15:38:29 +04:00
reply_outbuf ( req , 3 , 0 ) ;
2007-04-07 09:49:24 +04:00
}
1997-08-31 18:14:22 +04:00
2007-07-23 15:38:29 +04:00
if ( ( message_push_string ( & req - > outbuf , server_devicetype ,
STR_TERMINATE | STR_ASCII ) = = - 1 )
| | ( message_push_string ( & req - > outbuf , fstype ,
STR_TERMINATE ) = = - 1 ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
2007-07-13 05:22:09 +04:00
1998-09-20 19:48:10 +04:00
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
2007-07-23 15:38:29 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , SMB_SUPPORT_SEARCH_BITS |
( lp_csc_policy ( SNUM ( conn ) ) < < 2 ) ) ;
2007-07-13 05:22:09 +04:00
2007-07-23 15:38:29 +04:00
init_dfsroot ( conn , req - > inbuf , req - > outbuf ) ;
1998-08-14 21:38:29 +04:00
}
2000-03-09 01:14:30 +03:00
2007-07-13 05:22:09 +04:00
2001-09-15 16:55:59 +04:00
DEBUG ( 3 , ( " tconX service=%s \n " ,
service ) ) ;
2007-07-13 05:22:09 +04:00
1998-08-14 21:38:29 +04:00
/* set the incoming and outgoing tid to the just created one */
2007-07-23 15:38:29 +04:00
SSVAL ( req - > inbuf , smb_tid , conn - > cnum ) ;
SSVAL ( req - > outbuf , smb_tid , conn - > cnum ) ;
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2007-07-23 15:38:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an unknown type .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
1996-05-04 11:50:46 +04:00
int reply_unknown ( char * inbuf , char * outbuf )
{
1998-08-14 21:38:29 +04:00
int type ;
type = CVAL ( inbuf , smb_com ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 0 , ( " unknown command type (%s): type=%d (0x%X) \n " ,
smb_fn_name ( type ) , type , type ) ) ;
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRSRV , ERRunknownsmb ) ) ;
1996-05-04 11:50:46 +04:00
}
2007-07-23 13:36:09 +04:00
void reply_unknown_new ( struct smb_request * req , uint8 type )
{
DEBUG ( 0 , ( " unknown command type (%s): type=%d (0x%X) \n " ,
smb_fn_name ( type ) , type , type ) ) ;
reply_doserror ( req , ERRSRV , ERRunknownsmb ) ;
return ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an ioctl .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-15 01:13:05 +04:00
void reply_ioctl ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-15 01:13:05 +04:00
uint16 device ;
uint16 function ;
uint32 ioctl_code ;
int replysize ;
1999-12-13 16:27:58 +03:00
char * p ;
2007-08-15 01:13:05 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBioctl ) ;
1999-12-13 16:27:58 +03:00
2007-08-15 01:13:05 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBioctl ) ;
return ;
}
device = SVAL ( req - > inbuf , smb_vwv1 ) ;
function = SVAL ( req - > inbuf , smb_vwv2 ) ;
ioctl_code = ( device < < 16 ) + function ;
1999-12-13 16:27:58 +03:00
DEBUG ( 4 , ( " Received IOCTL (code 0x%x) \n " , ioctl_code ) ) ;
2002-09-25 19:19:00 +04:00
switch ( ioctl_code ) {
1999-12-13 16:27:58 +03:00
case IOCTL_QUERY_JOB_INFO :
2007-08-15 01:13:05 +04:00
replysize = 32 ;
break ;
1999-12-13 16:27:58 +03:00
default :
2007-08-15 01:13:05 +04:00
reply_doserror ( req , ERRSRV , ERRnosupport ) ;
END_PROFILE ( SMBioctl ) ;
return ;
1999-12-13 16:27:58 +03:00
}
2007-08-15 01:13:05 +04:00
reply_outbuf ( req , 8 , replysize + 1 ) ;
SSVAL ( req - > outbuf , smb_vwv1 , replysize ) ; /* Total data bytes returned */
SSVAL ( req - > outbuf , smb_vwv5 , replysize ) ; /* Data bytes this buffer */
SSVAL ( req - > outbuf , smb_vwv6 , 52 ) ; /* Offset to data */
2007-09-08 00:57:01 +04:00
p = smb_buf ( req - > outbuf ) ;
memset ( p , ' \0 ' , replysize + 1 ) ; /* valgrind-safe. */
p + = 1 ; /* Allow for alignment */
1999-12-13 16:27:58 +03:00
2002-09-25 19:19:00 +04:00
switch ( ioctl_code ) {
case IOCTL_QUERY_JOB_INFO :
{
2007-08-15 01:13:05 +04:00
files_struct * fsp = file_fsp ( SVAL ( req - > inbuf ,
smb_vwv0 ) ) ;
2003-09-09 00:27:28 +04:00
if ( ! fsp ) {
2007-08-15 01:13:05 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
2003-09-09 00:27:28 +04:00
END_PROFILE ( SMBioctl ) ;
2007-08-15 01:13:05 +04:00
return ;
2003-09-09 00:27:28 +04:00
}
2002-12-05 07:00:16 +03:00
SSVAL ( p , 0 , fsp - > rap_print_jobid ) ; /* Job number */
2007-08-15 01:13:05 +04:00
srvstr_push ( ( char * ) req - > outbuf , req - > flags2 , p + 2 ,
2007-08-02 21:37:38 +04:00
global_myname ( ) , 15 ,
STR_TERMINATE | STR_ASCII ) ;
2004-05-22 09:01:25 +04:00
if ( conn ) {
2007-08-15 01:13:05 +04:00
srvstr_push ( ( char * ) req - > outbuf , req - > flags2 ,
2007-08-02 21:37:38 +04:00
p + 18 , lp_servicename ( SNUM ( conn ) ) ,
13 , STR_TERMINATE | STR_ASCII ) ;
2007-09-08 00:57:01 +04:00
} else {
2007-08-15 01:13:05 +04:00
memset ( p + 18 , 0 , 13 ) ;
}
2002-09-25 19:19:00 +04:00
break ;
}
1999-12-13 16:27:58 +03:00
}
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBioctl ) ;
2007-08-15 01:13:05 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2007-01-14 01:10:18 +03:00
Strange checkpath NTSTATUS mapping .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-01-14 01:10:18 +03:00
static NTSTATUS map_checkpath_error ( const char * inbuf , NTSTATUS status )
{
/* Strange DOS error code semantics only for checkpath... */
if ( ! ( SVAL ( inbuf , smb_flg2 ) & FLAGS2_32_BIT_ERROR_CODES ) ) {
if ( NT_STATUS_EQUAL ( NT_STATUS_OBJECT_NAME_INVALID , status ) ) {
/* We need to map to ERRbadpath */
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
}
}
return status ;
}
2007-09-12 03:57:59 +04:00
2007-01-14 01:10:18 +03:00
/****************************************************************************
Reply to a checkpath .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-23 16:03:58 +04:00
void reply_checkpath ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * name = NULL ;
2002-09-25 19:19:00 +04:00
SMB_STRUCT_STAT sbuf ;
2003-08-13 07:28:06 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-08-13 07:28:06 +04:00
2007-01-14 01:10:18 +03:00
START_PROFILE ( SMBcheckpath ) ;
2001-03-13 06:45:09 +03:00
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & name ,
smb_buf ( req - > inbuf ) + 1 , 0 ,
2007-07-23 16:03:58 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-23 16:03:58 +04:00
status = map_checkpath_error ( ( char * ) req - > inbuf , status ) ;
reply_nterror ( req , status ) ;
2007-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2003-08-13 07:28:06 +04:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
name ,
2007-09-11 22:31:29 +04:00
& name ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2007-03-12 20:55:24 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2007-03-12 20:55:24 +03:00
}
goto path_err ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
2007-09-12 03:57:59 +04:00
DEBUG ( 3 , ( " reply_checkpath %s mode=%d \n " , name , ( int ) SVAL ( req - > inbuf , smb_vwv0 ) ) ) ;
2007-01-14 01:10:18 +03:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , name , False , & name , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-17 05:09:37 +03:00
goto path_err ;
2004-06-11 21:54:23 +04:00
}
1996-05-04 11:50:46 +04:00
2007-01-17 05:09:37 +03:00
status = check_name ( conn , name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " reply_checkpath: check_name of %s failed (%s) \n " , name , nt_errstr ( status ) ) ) ;
goto path_err ;
}
if ( ! VALID_STAT ( sbuf ) & & ( SMB_VFS_STAT ( conn , name , & sbuf ) ! = 0 ) ) {
DEBUG ( 3 , ( " reply_checkpath: stat of %s failed (%s) \n " , name , strerror ( errno ) ) ) ;
status = map_nt_error_from_unix ( errno ) ;
goto path_err ;
}
1997-10-04 00:36:06 +04:00
2007-01-17 05:09:37 +03:00
if ( ! S_ISDIR ( sbuf . st_mode ) ) {
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_NOT_A_DIRECTORY ,
ERRDOS , ERRbadpath ) ;
2007-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
1998-08-01 02:39:15 +04:00
2007-07-23 16:03:58 +04:00
reply_outbuf ( req , 0 , 0 ) ;
1998-08-01 02:39:15 +04:00
2007-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2007-01-17 05:09:37 +03:00
path_err :
END_PROFILE ( SMBcheckpath ) ;
/* We special case this - as when a Windows machine
is parsing a path is steps through the components
one at a time - if a component fails it expects
ERRbadpath , not ERRbadfile .
*/
2007-07-23 16:03:58 +04:00
status = map_checkpath_error ( ( char * ) req - > inbuf , status ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
2007-01-17 05:09:37 +03:00
/*
* Windows returns different error codes if
* the parent directory is valid but not the
* last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
* for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
* if the path is invalid .
*/
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpath ) ;
return ;
2007-01-17 05:09:37 +03:00
}
2007-07-23 16:03:58 +04:00
reply_nterror ( req , status ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a getatr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 19:09:49 +04:00
void reply_getatr ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
SMB_STRUCT_STAT sbuf ;
int mode = 0 ;
SMB_OFF_T size = 0 ;
time_t mtime = 0 ;
char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-10-09 03:21:36 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBgetatr ) ;
2007-08-14 19:09:49 +04:00
p = smb_buf ( req - > inbuf ) + 1 ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname , p ,
0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBgetatr ) ;
2007-08-14 19:09:49 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 19:09:49 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBgetatr ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBgetatr ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird ! */
2007-09-11 22:31:29 +04:00
if ( * fname = = ' \0 ' ) {
2002-12-04 02:57:45 +03:00
mode = aHIDDEN | aDIR ;
2007-01-14 01:22:32 +03:00
if ( ! CAN_WRITE ( conn ) ) {
2002-12-04 02:57:45 +03:00
mode | = aRONLY ;
2007-01-14 01:22:32 +03:00
}
2002-12-04 02:57:45 +03:00
size = 0 ;
mtime = 0 ;
} else {
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBgetatr ) ;
2007-08-14 19:09:49 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
2007-01-17 05:09:37 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " reply_getatr: check_name of %s failed (%s) \n " , fname , nt_errstr ( status ) ) ) ;
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
2007-01-14 01:22:32 +03:00
END_PROFILE ( SMBgetatr ) ;
2007-08-14 19:09:49 +04:00
return ;
2007-01-17 05:09:37 +03:00
}
if ( ! VALID_STAT ( sbuf ) & & ( SMB_VFS_STAT ( conn , fname , & sbuf ) ! = 0 ) ) {
DEBUG ( 3 , ( " reply_getatr: stat of %s failed (%s) \n " , fname , strerror ( errno ) ) ) ;
2007-08-14 19:09:49 +04:00
reply_unixerror ( req , ERRDOS , ERRbadfile ) ;
END_PROFILE ( SMBgetatr ) ;
return ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 05:09:37 +03:00
mode = dos_mode ( conn , fname , & sbuf ) ;
size = sbuf . st_size ;
mtime = sbuf . st_mtime ;
if ( mode & aDIR ) {
size = 0 ;
}
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 19:09:49 +04:00
reply_outbuf ( req , 10 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , mode ) ;
2005-11-05 07:21:55 +03:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-08-14 19:09:49 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv1 , mtime & ~ 1 ) ;
2005-11-05 07:21:55 +03:00
} else {
2007-08-14 19:09:49 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv1 , mtime ) ;
2005-11-05 07:21:55 +03:00
}
2007-08-14 19:09:49 +04:00
SIVAL ( req - > outbuf , smb_vwv3 , ( uint32 ) size ) ;
1996-05-04 11:50:46 +04:00
2005-11-05 07:21:55 +03:00
if ( Protocol > = PROTOCOL_NT1 ) {
2007-08-14 19:09:49 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 ) | FLAGS2_IS_LONG_NAME ) ;
2005-11-05 07:21:55 +03:00
}
1996-05-04 11:50:46 +04:00
2007-01-14 01:22:32 +03:00
DEBUG ( 3 , ( " reply_getatr: name=%s mode=%d size=%u \n " , fname , mode , ( unsigned int ) size ) ) ;
2007-09-12 03:57:59 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBgetatr ) ;
2007-08-14 19:09:49 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a setatr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 19:26:54 +04:00
void reply_setatr ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
int mode ;
time_t mtime ;
SMB_STRUCT_STAT sbuf ;
char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
p = smb_buf ( req - > inbuf ) + 1 ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname , p ,
0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 19:26:54 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBsetatr ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBsetatr ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-09-12 03:57:59 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
2002-12-04 02:57:45 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-01-05 01:01:36 +03:00
if ( fname [ 0 ] = = ' . ' & & fname [ 1 ] = = ' \0 ' ) {
2007-01-03 15:01:17 +03:00
/*
* Not sure here is the right place to catch this
* condition . Might be moved to somewhere else later - - vl
*/
2007-08-14 19:26:54 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-01-03 15:01:17 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
2007-01-03 15:01:17 +03:00
}
2007-08-14 19:26:54 +04:00
mode = SVAL ( req - > inbuf , smb_vwv0 ) ;
mtime = srv_make_unix_date3 ( req - > inbuf + smb_vwv1 ) ;
2007-09-14 02:08:59 +04:00
2003-08-15 03:15:02 +04:00
if ( mode ! = FILE_ATTRIBUTE_NORMAL ) {
if ( VALID_STAT_OF_DIR ( sbuf ) )
mode | = aDIR ;
else
mode & = ~ aDIR ;
2007-11-01 01:45:45 +03:00
if ( file_set_dosmode ( conn , fname , mode , & sbuf , NULL , false ) ! = 0 ) {
2007-08-14 19:26:54 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
2007-01-08 16:21:43 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
2007-01-08 16:21:43 +03:00
}
2003-08-15 03:15:02 +04:00
}
2002-12-04 02:57:45 +03:00
2007-03-06 02:40:03 +03:00
if ( ! set_filetime ( conn , fname , convert_time_t_to_timespec ( mtime ) ) ) {
2007-08-14 19:26:54 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 19:26:54 +04:00
reply_outbuf ( req , 0 , 0 ) ;
1997-08-21 00:32:23 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " setatr name=%s mode=%d \n " , fname , mode ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a dskattr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-07-30 14:30:19 +04:00
void reply_dskattr ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-07-15 14:35:28 +04:00
SMB_BIG_UINT dfree , dsize , bsize ;
START_PROFILE ( SMBdskattr ) ;
2005-11-01 01:30:05 +03:00
if ( get_dfree_info ( conn , " . " , True , & bsize , & dfree , & dsize ) = = ( SMB_BIG_UINT ) - 1 ) {
2007-07-30 14:30:19 +04:00
reply_unixerror ( req , ERRHRD , ERRgeneral ) ;
2005-03-16 04:41:21 +03:00
END_PROFILE ( SMBdskattr ) ;
2007-07-30 14:30:19 +04:00
return ;
2005-03-16 04:41:21 +03:00
}
2007-07-30 14:30:19 +04:00
reply_outbuf ( req , 5 , 0 ) ;
2002-07-15 14:35:28 +04:00
if ( Protocol < = PROTOCOL_LANMAN2 ) {
double total_space , free_space ;
/* we need to scale this to a number that DOS6 can handle. We
use floating point so we can handle large drives on systems
that don ' t have 64 bit integers
1998-08-01 02:39:15 +04:00
2002-07-15 14:35:28 +04:00
we end up displaying a maximum of 2 G to DOS systems
*/
total_space = dsize * ( double ) bsize ;
free_space = dfree * ( double ) bsize ;
1998-08-01 02:39:15 +04:00
2002-07-15 14:35:28 +04:00
dsize = ( total_space + 63 * 512 ) / ( 64 * 512 ) ;
dfree = ( free_space + 63 * 512 ) / ( 64 * 512 ) ;
if ( dsize > 0xFFFF ) dsize = 0xFFFF ;
if ( dfree > 0xFFFF ) dfree = 0xFFFF ;
2007-07-30 14:30:19 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , dsize ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 64 ) ; /* this must be 64 for dos systems */
SSVAL ( req - > outbuf , smb_vwv2 , 512 ) ; /* and this must be 512 */
SSVAL ( req - > outbuf , smb_vwv3 , dfree ) ;
2002-07-15 14:35:28 +04:00
} else {
2007-07-30 14:30:19 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , dsize ) ;
SSVAL ( req - > outbuf , smb_vwv1 , bsize / 512 ) ;
SSVAL ( req - > outbuf , smb_vwv2 , 512 ) ;
SSVAL ( req - > outbuf , smb_vwv3 , dfree ) ;
2002-07-15 14:35:28 +04:00
}
DEBUG ( 3 , ( " dskattr dfree=%d \n " , ( unsigned int ) dfree ) ) ;
END_PROFILE ( SMBdskattr ) ;
2007-07-30 14:30:19 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a search .
Can be called from SMBsearch , SMBffirst or SMBfunique .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-15 01:32:52 +04:00
void reply_search ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-13 01:48:20 +04:00
char * mask = NULL ;
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2007-09-13 01:48:20 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
SMB_OFF_T size ;
2005-06-25 07:03:44 +04:00
uint32 mode ;
2002-12-04 02:57:45 +03:00
time_t date ;
2005-06-25 07:03:44 +04:00
uint32 dirtype ;
2003-10-30 00:28:00 +03:00
unsigned int numentries = 0 ;
unsigned int maxentries = 0 ;
2007-10-19 04:40:25 +04:00
bool finished = False ;
2002-12-04 02:57:45 +03:00
char * p ;
int status_len ;
2007-09-11 22:31:29 +04:00
char * path = NULL ;
2002-12-04 02:57:45 +03:00
char status [ 21 ] ;
int dptr_num = - 1 ;
2007-10-19 04:40:25 +04:00
bool check_descend = False ;
bool expect_close = False ;
2003-10-09 03:21:36 +04:00
NTSTATUS nt_status ;
2007-10-19 04:40:25 +04:00
bool mask_contains_wcard = False ;
bool allow_long_path_components = ( req - > flags2 & FLAGS2_LONG_PATH_COMPONENTS ) ? True : False ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-03-29 04:36:30 +04:00
2006-05-05 11:15:45 +04:00
START_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
2005-06-23 01:20:41 +04:00
if ( lp_posix_pathnames ( ) ) {
2007-08-15 01:32:52 +04:00
reply_unknown_new ( req , CVAL ( req - > inbuf , smb_com ) ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
return ;
2005-06-23 01:20:41 +04:00
}
2002-12-04 02:57:45 +03:00
/* If we were called as SMBffirst then we must expect close. */
2007-08-15 01:32:52 +04:00
if ( CVAL ( req - > inbuf , smb_com ) = = SMBffirst ) {
2002-12-04 02:57:45 +03:00
expect_close = True ;
2007-01-17 00:04:30 +03:00
}
2007-08-15 01:32:52 +04:00
reply_outbuf ( req , 1 , 3 ) ;
maxentries = SVAL ( req - > inbuf , smb_vwv0 ) ;
dirtype = SVAL ( req - > inbuf , smb_vwv1 ) ;
p = smb_buf ( req - > inbuf ) + 1 ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx ,
( char * ) req - > inbuf ,
req - > flags2 ,
& path ,
p ,
0 ,
STR_TERMINATE ,
& nt_status ,
& mask_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , nt_status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2005-03-16 02:17:03 +03:00
2007-09-11 22:31:29 +04:00
nt_status = resolve_dfspath_wcard ( ctx , conn ,
2007-08-15 01:32:52 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
path ,
2007-09-11 22:31:29 +04:00
& path ,
& mask_contains_wcard ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-15 01:32:52 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBsearch ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-15 01:32:52 +04:00
reply_nterror ( req , nt_status ) ;
END_PROFILE ( SMBsearch ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
p + + ;
status_len = SVAL ( p , 0 ) ;
p + = 2 ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
/* dirtype &= ~aDIR; */
if ( status_len = = 0 ) {
SMB_STRUCT_STAT sbuf ;
2007-09-14 02:08:59 +04:00
nt_status = unix_convert ( ctx , conn , path , True ,
& directory , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , nt_status ) ;
2007-01-13 02:47:16 +03:00
END_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
return ;
2007-01-13 02:47:16 +03:00
}
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
nt_status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , nt_status ) ;
2007-01-17 00:04:30 +03:00
END_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
return ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
p = strrchr_m ( directory , ' / ' ) ;
2007-01-17 00:04:30 +03:00
if ( ! p ) {
2007-09-13 01:48:20 +04:00
mask = directory ;
directory = talloc_strdup ( ctx , " . " ) ;
2007-09-08 00:57:01 +04:00
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
2007-01-17 00:04:30 +03:00
} else {
2002-12-04 02:57:45 +03:00
* p = 0 ;
2007-09-13 01:48:20 +04:00
mask = p + 1 ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
2007-03-09 05:16:03 +03:00
if ( * directory = = ' \0 ' ) {
2007-09-13 01:48:20 +04:00
directory = talloc_strdup ( ctx , " . " ) ;
2007-09-08 00:57:01 +04:00
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
memset ( ( char * ) status , ' \0 ' , 21 ) ;
SCVAL ( status , 0 , ( dirtype & 0x1F ) ) ;
2007-09-08 00:57:01 +04:00
nt_status = dptr_create ( conn ,
directory ,
True ,
expect_close ,
req - > smbpid ,
mask ,
mask_contains_wcard ,
dirtype ,
& conn - > dirptr ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
reply_nterror ( req , nt_status ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
dptr_num = dptr_dnum ( conn - > dirptr ) ;
2002-12-04 02:57:45 +03:00
} else {
int status_dirtype ;
memcpy ( status , p , 21 ) ;
status_dirtype = CVAL ( status , 0 ) & 0x1F ;
2007-01-17 00:04:30 +03:00
if ( status_dirtype ! = ( dirtype & 0x1F ) ) {
2002-12-04 02:57:45 +03:00
dirtype = status_dirtype ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
2007-09-08 00:57:01 +04:00
conn - > dirptr = dptr_fetch ( status + 12 , & dptr_num ) ;
2007-01-17 00:04:30 +03:00
if ( ! conn - > dirptr ) {
2002-12-04 02:57:45 +03:00
goto SearchEmpty ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
string_set ( & conn - > dirpath , dptr_path ( dptr_num ) ) ;
2007-09-13 01:48:20 +04:00
mask = dptr_wcard ( dptr_num ) ;
if ( ! mask ) {
goto SearchEmpty ;
}
2007-03-09 05:40:49 +03:00
/*
* For a ' continue ' search we have no string . So
* check from the initial saved string .
*/
mask_contains_wcard = ms_has_wild ( mask ) ;
2007-01-17 00:04:30 +03:00
dirtype = dptr_attr ( dptr_num ) ;
}
DEBUG ( 4 , ( " dptr_num is %d \n " , dptr_num ) ) ;
2007-08-15 01:32:52 +04:00
if ( ( dirtype & 0x1F ) = = aVOLID ) {
char buf [ DIR_STRUCT_SIZE ] ;
memcpy ( buf , status , 21 ) ;
2007-09-13 01:48:20 +04:00
if ( ! make_dir_struct ( ctx , buf , " ??????????? " , volume_label ( SNUM ( conn ) ) ,
0 , aVOLID , 0 , ! allow_long_path_components ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
2007-08-15 01:32:52 +04:00
dptr_fill ( buf + 12 , dptr_num ) ;
if ( dptr_zero ( buf + 12 ) & & ( status_len = = 0 ) ) {
2007-01-17 00:04:30 +03:00
numentries = 1 ;
2002-12-05 01:48:13 +03:00
} else {
2007-01-17 00:04:30 +03:00
numentries = 0 ;
2002-12-04 02:57:45 +03:00
}
2007-08-15 01:32:52 +04:00
if ( message_push_blob ( & req - > outbuf ,
data_blob_const ( buf , sizeof ( buf ) ) )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
2007-01-17 00:04:30 +03:00
} else {
unsigned int i ;
2007-08-15 01:32:52 +04:00
maxentries = MIN (
maxentries ,
( ( BUFFER_SIZE -
( ( uint8 * ) smb_buf ( req - > outbuf ) + 3 - req - > outbuf ) )
/ DIR_STRUCT_SIZE ) ) ;
2002-12-04 02:57:45 +03:00
2007-01-17 00:04:30 +03:00
DEBUG ( 8 , ( " dirpath=<%s> dontdescend=<%s> \n " ,
conn - > dirpath , lp_dontdescend ( SNUM ( conn ) ) ) ) ;
if ( in_list ( conn - > dirpath , lp_dontdescend ( SNUM ( conn ) ) , True ) ) {
check_descend = True ;
}
2002-12-04 02:57:45 +03:00
2007-01-17 00:04:30 +03:00
for ( i = numentries ; ( i < maxentries ) & & ! finished ; i + + ) {
2007-09-13 01:48:20 +04:00
finished = ! get_dir_entry ( ctx , conn , mask , dirtype , & fname ,
& size , & mode , & date , check_descend ) ;
2007-01-17 00:04:30 +03:00
if ( ! finished ) {
2007-08-15 01:32:52 +04:00
char buf [ DIR_STRUCT_SIZE ] ;
memcpy ( buf , status , 21 ) ;
2007-09-13 01:48:20 +04:00
if ( ! make_dir_struct ( ctx ,
buf ,
mask ,
fname ,
size ,
mode ,
date ,
! allow_long_path_components ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
2007-08-15 01:32:52 +04:00
if ( ! dptr_fill ( buf + 12 , dptr_num ) ) {
2007-01-17 00:04:30 +03:00
break ;
2002-12-04 02:57:45 +03:00
}
2007-08-15 01:32:52 +04:00
if ( message_push_blob ( & req - > outbuf ,
data_blob_const ( buf , sizeof ( buf ) ) )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsearch ) ;
return ;
}
2007-01-17 00:04:30 +03:00
numentries + + ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
SearchEmpty :
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
/* If we were called as SMBffirst with smb_search_id == NULL
and no entries were found then return error and close dirptr
( X / Open spec ) */
2007-01-17 00:04:30 +03:00
if ( numentries = = 0 ) {
2002-12-04 02:57:45 +03:00
dptr_close ( & dptr_num ) ;
2007-01-17 00:04:30 +03:00
} else if ( expect_close & & status_len = = 0 ) {
2005-01-29 02:17:12 +03:00
/* Close the dptr - we know it's gone */
2003-08-19 05:02:41 +04:00
dptr_close ( & dptr_num ) ;
2002-12-04 02:57:45 +03:00
}
/* If we were called as SMBfunique, then we can close the dirptr now ! */
2007-08-15 01:32:52 +04:00
if ( dptr_num > = 0 & & CVAL ( req - > inbuf , smb_com ) = = SMBfunique ) {
2002-12-04 02:57:45 +03:00
dptr_close ( & dptr_num ) ;
2005-01-29 02:17:12 +03:00
}
2005-10-31 23:11:58 +03:00
if ( ( numentries = = 0 ) & & ! mask_contains_wcard ) {
2007-08-15 01:32:52 +04:00
reply_botherror ( req , STATUS_NO_MORE_FILES , ERRDOS , ERRnofiles ) ;
END_PROFILE ( SMBsearch ) ;
return ;
2005-01-29 02:17:12 +03:00
}
2002-12-04 02:57:45 +03:00
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , numentries ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 3 + numentries * DIR_STRUCT_SIZE ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 5 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , numentries * DIR_STRUCT_SIZE ) ;
2002-12-04 02:57:45 +03:00
2005-03-29 04:36:30 +04:00
/* The replies here are never long name. */
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 ) & ( ~ FLAGS2_IS_LONG_NAME ) ) ;
2005-03-29 04:36:30 +04:00
if ( ! allow_long_path_components ) {
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 )
& ( ~ FLAGS2_LONG_PATH_COMPONENTS ) ) ;
2005-03-29 04:36:30 +04:00
}
2005-03-25 22:52:01 +03:00
/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
( SVAL ( req - > outbuf , smb_flg2 ) & ( ~ FLAGS2_UNICODE_STRINGS ) ) ) ;
2002-12-04 02:57:45 +03:00
2007-09-08 00:57:01 +04:00
if ( ! directory ) {
directory = dptr_path ( dptr_num ) ;
}
DEBUG ( 4 , ( " %s mask=%s path=%s dtype=%d nument=%u of %u \n " ,
2007-08-15 01:32:52 +04:00
smb_fn_name ( CVAL ( req - > inbuf , smb_com ) ) ,
2007-09-08 00:57:01 +04:00
mask ,
directory ? directory : " ./ " ,
dirtype ,
numentries ,
maxentries ) ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a fclose ( stop directory search ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-15 01:32:52 +04:00
void reply_fclose ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int status_len ;
char status [ 21 ] ;
int dptr_num = - 2 ;
char * p ;
2007-09-12 03:57:59 +04:00
char * path = NULL ;
2003-10-09 03:21:36 +04:00
NTSTATUS err ;
2007-10-19 04:40:25 +04:00
bool path_contains_wcard = False ;
2007-09-12 03:57:59 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2001-03-10 14:57:38 +03:00
2006-05-05 11:15:45 +04:00
START_PROFILE ( SMBfclose ) ;
2005-06-23 01:20:41 +04:00
if ( lp_posix_pathnames ( ) ) {
2007-08-15 01:32:52 +04:00
reply_unknown_new ( req , CVAL ( req - > inbuf , smb_com ) ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2005-06-23 01:20:41 +04:00
}
2007-08-15 01:32:52 +04:00
p = smb_buf ( req - > inbuf ) + 1 ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx ,
( char * ) req - > inbuf ,
req - > flags2 ,
& path ,
p ,
0 ,
STR_TERMINATE ,
& err ,
& path_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( err ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , err ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
p + + ;
status_len = SVAL ( p , 0 ) ;
p + = 2 ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( status_len = = 0 ) {
2007-08-15 01:32:52 +04:00
reply_doserror ( req , ERRSRV , ERRsrverror ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
memcpy ( status , p , 21 ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( dptr_fetch ( status + 12 , & dptr_num ) ) {
/* Close the dptr - we know it's gone */
dptr_close ( & dptr_num ) ;
}
1996-05-04 11:50:46 +04:00
2007-08-15 01:32:52 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , 0 ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " search close \n " ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an open .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-23 04:58:28 +04:00
2007-08-14 18:31:55 +04:00
void reply_open ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2005-07-08 08:51:27 +04:00
uint32 fattr = 0 ;
2002-12-04 02:57:45 +03:00
SMB_OFF_T size = 0 ;
time_t mtime = 0 ;
2005-07-08 08:51:27 +04:00
int info ;
2002-12-04 02:57:45 +03:00
SMB_STRUCT_STAT sbuf ;
files_struct * fsp ;
2007-08-14 17:57:36 +04:00
int oplock_request ;
2005-07-08 08:51:27 +04:00
int deny_mode ;
2007-08-14 17:57:36 +04:00
uint32 dos_attr ;
2005-07-08 08:51:27 +04:00
uint32 access_mask ;
uint32 share_mode ;
uint32 create_disposition ;
uint32 create_options = 0 ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-07-05 20:26:27 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopen ) ;
2007-07-05 20:26:27 +04:00
2007-08-14 18:31:55 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBopen ) ;
return ;
2007-08-14 17:57:36 +04:00
}
2007-09-11 22:31:29 +04:00
2007-08-14 18:31:55 +04:00
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
deny_mode = SVAL ( req - > inbuf , smb_vwv0 ) ;
dos_attr = SVAL ( req - > inbuf , smb_vwv1 ) ;
1996-05-04 11:50:46 +04:00
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname ,
smb_buf ( req - > inbuf ) + 1 , 0 ,
2007-08-14 18:31:55 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:31:55 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2000-03-09 01:14:30 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 18:31:55 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBopen ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 18:31:55 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBopen ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:31:55 +04:00
reply_nterror ( req , status ) ;
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
2007-09-14 02:08:59 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:31:55 +04:00
reply_nterror ( req , status ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2005-07-08 08:51:27 +04:00
if ( ! map_open_params_to_ntcreate ( fname , deny_mode , OPENX_FILE_EXISTS_OPEN ,
& access_mask , & share_mode , & create_disposition , & create_options ) ) {
2007-08-14 18:31:55 +04:00
reply_nterror ( req , NT_STATUS_DOS ( ERRDOS , ERRbadaccess ) ) ;
2005-07-08 08:51:27 +04:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 18:31:55 +04:00
status = open_file_ntcreate ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
access_mask ,
share_mode ,
create_disposition ,
create_options ,
dos_attr ,
oplock_request ,
2006-07-11 22:01:26 +04:00
& info , & fsp ) ;
2002-12-04 02:57:45 +03:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:31:55 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2007-10-11 00:34:30 +04:00
END_PROFILE ( SMBopen ) ;
2007-08-16 04:37:07 +04:00
return ;
}
2007-08-16 21:42:34 +04:00
reply_openerror ( req , status ) ;
2007-08-25 23:47:57 +04:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
size = sbuf . st_size ;
2005-07-08 08:51:27 +04:00
fattr = dos_mode ( conn , fname , & sbuf ) ;
2002-12-04 02:57:45 +03:00
mtime = sbuf . st_mtime ;
2005-07-08 08:51:27 +04:00
if ( fattr & aDIR ) {
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " attempt to open a directory %s \n " , fname ) ) ;
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-08-14 18:31:55 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 18:31:55 +04:00
reply_outbuf ( req , 7 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
SSVAL ( req - > outbuf , smb_vwv1 , fattr ) ;
2005-07-08 08:51:27 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-08-14 18:31:55 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv2 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2007-08-14 18:31:55 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv2 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 18:31:55 +04:00
SIVAL ( req - > outbuf , smb_vwv4 , ( uint32 ) size ) ;
SSVAL ( req - > outbuf , smb_vwv6 , deny_mode ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 18:31:55 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 18:31:55 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an open and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-07-23 13:54:36 +04:00
void reply_open_and_X ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2007-07-23 13:54:36 +04:00
uint16 open_flags ;
int deny_mode ;
uint32 smb_attr ;
2002-12-04 02:57:45 +03:00
/* Breakout the oplock request bits so we can set the
reply bits separately . */
2007-07-23 13:54:36 +04:00
int ex_oplock_request ;
int core_oplock_request ;
int oplock_request ;
1996-05-04 11:50:46 +04:00
#if 0
2007-07-23 13:54:36 +04:00
int smb_sattr = SVAL ( req - > inbuf , smb_vwv4 ) ;
uint32 smb_time = make_unix_date3 ( req - > inbuf + smb_vwv6 ) ;
1996-05-04 11:50:46 +04:00
# endif
2007-07-23 13:54:36 +04:00
int smb_ofun ;
2005-07-08 08:51:27 +04:00
uint32 fattr = 0 ;
int mtime = 0 ;
2002-12-04 02:57:45 +03:00
SMB_STRUCT_STAT sbuf ;
int smb_action = 0 ;
files_struct * fsp ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-07-23 13:54:36 +04:00
SMB_BIG_UINT allocation_size ;
2005-04-05 05:20:32 +04:00
ssize_t retval = - 1 ;
2005-07-08 08:51:27 +04:00
uint32 access_mask ;
uint32 share_mode ;
uint32 create_disposition ;
uint32 create_options = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-04-05 05:20:32 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
if ( req - > wct < 15 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBopenX ) ;
return ;
}
open_flags = SVAL ( req - > inbuf , smb_vwv2 ) ;
deny_mode = SVAL ( req - > inbuf , smb_vwv3 ) ;
smb_attr = SVAL ( req - > inbuf , smb_vwv5 ) ;
ex_oplock_request = EXTENDED_OPLOCK_REQUEST ( req - > inbuf ) ;
core_oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
oplock_request = ex_oplock_request | core_oplock_request ;
smb_ofun = SVAL ( req - > inbuf , smb_vwv8 ) ;
allocation_size = ( SMB_BIG_UINT ) IVAL ( req - > inbuf , smb_vwv9 ) ;
2007-07-05 20:26:27 +04:00
2002-12-04 02:57:45 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
if ( lp_nt_pipe_support ( ) ) {
2007-07-23 13:54:36 +04:00
reply_open_pipe_and_X ( conn , req ) ;
2002-12-04 02:57:45 +03:00
} else {
2007-07-23 13:54:36 +04:00
reply_doserror ( req , ERRSRV , ERRaccess ) ;
2002-12-04 02:57:45 +03:00
}
2007-07-23 13:54:36 +04:00
END_PROFILE ( SMBopenX ) ;
return ;
2002-12-04 02:57:45 +03:00
}
1996-08-15 19:11:34 +04:00
2002-12-04 02:57:45 +03:00
/* XXXX we need to handle passed times, sattr and flags */
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname ,
smb_buf ( req - > inbuf ) , 0 , STR_TERMINATE ,
2007-07-23 13:54:36 +04:00
& status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-23 13:54:36 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2000-03-09 01:14:30 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBopenX ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-23 13:54:36 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-07-23 13:54:36 +04:00
reply_nterror ( req , status ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-23 13:54:36 +04:00
reply_nterror ( req , status ) ;
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
2005-04-02 04:13:27 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-23 13:54:36 +04:00
reply_nterror ( req , status ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2005-07-08 08:51:27 +04:00
if ( ! map_open_params_to_ntcreate ( fname , deny_mode , smb_ofun ,
& access_mask ,
& share_mode ,
& create_disposition ,
& create_options ) ) {
2007-07-23 13:54:36 +04:00
reply_nterror ( req , NT_STATUS_DOS ( ERRDOS , ERRbadaccess ) ) ;
2005-07-08 08:51:27 +04:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
2005-04-02 04:13:27 +04:00
}
2007-07-23 13:54:36 +04:00
status = open_file_ntcreate ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
access_mask ,
share_mode ,
create_disposition ,
create_options ,
smb_attr ,
oplock_request ,
2006-07-11 22:01:26 +04:00
& smb_action , & fsp ) ;
2007-08-16 21:42:34 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2007-08-15 17:44:34 +04:00
return ;
}
2007-08-16 21:42:34 +04:00
reply_openerror ( req , status ) ;
2007-07-23 13:54:36 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2005-04-05 05:20:32 +04:00
/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
if the file is truncated or created . */
if ( ( ( smb_action = = FILE_WAS_CREATED ) | | ( smb_action = = FILE_WAS_OVERWRITTEN ) ) & & allocation_size ) {
fsp - > initial_allocation_size = smb_roundup ( fsp - > conn , allocation_size ) ;
if ( vfs_allocate_file_space ( fsp , fsp - > initial_allocation_size ) = = - 1 ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-07-23 13:54:36 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
2005-04-05 05:20:32 +04:00
}
retval = vfs_set_filelen ( fsp , ( SMB_OFF_T ) allocation_size ) ;
if ( retval < 0 ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-07-23 13:54:36 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
2005-04-01 04:21:55 +04:00
}
2007-01-03 09:19:11 +03:00
sbuf . st_size = get_allocation_size ( conn , fsp , & sbuf ) ;
2005-04-01 04:21:55 +04:00
}
2005-07-08 08:51:27 +04:00
fattr = dos_mode ( conn , fname , & sbuf ) ;
2002-12-04 02:57:45 +03:00
mtime = sbuf . st_mtime ;
2005-07-08 08:51:27 +04:00
if ( fattr & aDIR ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-07-23 13:54:36 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
/* If the caller set the extended oplock request bit
and we granted one ( by whatever means ) - set the
correct bit for extended oplock reply .
*/
2005-07-08 08:51:27 +04:00
if ( ex_oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2002-12-04 02:57:45 +03:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( ex_oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2002-12-04 02:57:45 +03:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
/* If the caller set the core oplock request bit
and we granted one ( by whatever means ) - set the
correct bit for core oplock reply .
*/
2007-07-23 13:54:36 +04:00
if ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
reply_outbuf ( req , 19 , 0 ) ;
} else {
reply_outbuf ( req , 15 , 0 ) ;
}
2005-07-08 08:51:27 +04:00
if ( core_oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-07-23 13:54:36 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( core_oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-07-23 13:54:36 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2007-07-23 13:54:36 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , fsp - > fnum ) ;
SSVAL ( req - > outbuf , smb_vwv3 , fattr ) ;
2005-07-08 08:51:27 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-07-23 13:54:36 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2007-07-23 13:54:36 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2007-07-23 13:54:36 +04:00
SIVAL ( req - > outbuf , smb_vwv6 , ( uint32 ) sbuf . st_size ) ;
SSVAL ( req - > outbuf , smb_vwv8 , GET_OPENX_MODE ( deny_mode ) ) ;
SSVAL ( req - > outbuf , smb_vwv11 , smb_action ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
2007-07-23 13:54:36 +04:00
SIVAL ( req - > outbuf , smb_vwv15 , STD_RIGHT_ALL_ACCESS ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopenX ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2007-07-23 13:54:36 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a SMBulogoffX .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-07-30 23:53:57 +04:00
void reply_ulogoffX ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-07-30 23:53:57 +04:00
user_struct * vuser ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBulogoffX ) ;
1996-05-04 11:50:46 +04:00
2007-07-30 23:53:57 +04:00
vuser = get_valid_user_struct ( req - > vuid ) ;
if ( vuser = = NULL ) {
DEBUG ( 3 , ( " ulogoff, vuser id %d does not map to user. \n " ,
req - > vuid ) ) ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
/* in user level security we are supposed to close any files
open by this user */
2007-07-30 23:53:57 +04:00
if ( ( vuser ! = NULL ) & & ( lp_security ( ) ! = SEC_SHARE ) ) {
file_close_user ( req - > vuid ) ;
}
1996-10-05 14:41:13 +04:00
2007-07-30 23:53:57 +04:00
invalidate_vuid ( req - > vuid ) ;
1996-10-26 00:30:22 +04:00
2007-07-30 23:53:57 +04:00
reply_outbuf ( req , 2 , 0 ) ;
1996-05-04 11:50:46 +04:00
2007-07-30 23:53:57 +04:00
DEBUG ( 3 , ( " ulogoffX vuid=%d \n " , req - > vuid ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBulogoffX ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a mknew or a create .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 00:29:24 +04:00
void reply_mknew ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
int com ;
2007-08-14 00:29:24 +04:00
uint32 fattr = 0 ;
2007-03-06 02:40:03 +03:00
struct timespec ts [ 2 ] ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 00:29:24 +04:00
int oplock_request = 0 ;
2002-12-04 02:57:45 +03:00
SMB_STRUCT_STAT sbuf ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2005-07-08 08:51:27 +04:00
uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE ;
uint32 share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE ;
uint32 create_disposition ;
uint32 create_options = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-07-08 08:51:27 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcreate ) ;
2007-07-05 20:26:27 +04:00
2007-08-14 00:29:24 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBcreate ) ;
return ;
}
2002-12-04 02:57:45 +03:00
2007-08-14 00:29:24 +04:00
fattr = SVAL ( req - > inbuf , smb_vwv0 ) ;
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
com = SVAL ( req - > inbuf , smb_com ) ;
2007-01-03 09:19:11 +03:00
2007-08-14 00:29:24 +04:00
ts [ 1 ] = convert_time_t_to_timespec (
srv_make_unix_date3 ( req - > inbuf + smb_vwv1 ) ) ;
/* mtime. */
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname ,
smb_buf ( req - > inbuf ) + 1 , 0 ,
2007-08-25 23:47:57 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 00:29:24 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBcreate ) ;
2007-08-14 00:29:24 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBcreate ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 00:29:24 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 00:29:24 +04:00
reply_nterror ( req , status ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2002-12-04 02:57:45 +03:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 00:29:24 +04:00
reply_nterror ( req , status ) ;
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBcreate ) ;
2007-08-14 00:29:24 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
2002-12-04 02:57:45 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 00:29:24 +04:00
reply_nterror ( req , status ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBcreate ) ;
2007-08-14 00:29:24 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2005-07-08 08:51:27 +04:00
if ( fattr & aVOLID ) {
2007-08-14 00:29:24 +04:00
DEBUG ( 0 , ( " Attempt to create file (%s) with volid set - "
" please report this \n " , fname ) ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
if ( com = = SMBmknew ) {
/* We should fail if file exists. */
2005-07-08 08:51:27 +04:00
create_disposition = FILE_CREATE ;
2002-12-04 02:57:45 +03:00
} else {
2005-07-08 08:51:27 +04:00
/* Create if file doesn't exist, truncate if it does. */
2005-09-10 04:47:31 +04:00
create_disposition = FILE_OVERWRITE_IF ;
2005-07-08 08:51:27 +04:00
}
/* Open file using ntcreate. */
2007-08-14 00:29:24 +04:00
status = open_file_ntcreate ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
access_mask ,
share_mode ,
create_disposition ,
create_options ,
fattr ,
oplock_request ,
2006-07-11 22:01:26 +04:00
NULL , & fsp ) ;
2007-08-14 00:29:24 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcreate ) ;
2007-08-14 00:29:24 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2007-08-14 00:29:24 +04:00
return ;
2004-06-08 20:14:31 +04:00
}
2007-10-11 00:34:30 +04:00
reply_openerror ( req , status ) ;
2007-08-14 00:29:24 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 00:29:24 +04:00
2007-03-06 02:40:03 +03:00
ts [ 0 ] = get_atimespec ( & sbuf ) ; /* atime. */
file_ntimes ( conn , fname , ts ) ;
2007-01-03 09:19:11 +03:00
2007-08-14 00:29:24 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
1996-10-05 14:41:13 +04:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 00:29:24 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 00:29:24 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 00:29:24 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 00:29:24 +04:00
2005-07-08 08:51:27 +04:00
DEBUG ( 2 , ( " reply_mknew: file %s \n " , fname ) ) ;
2007-08-14 00:29:24 +04:00
DEBUG ( 3 , ( " reply_mknew %s fd=%d dmode=0x%x \n " ,
fname , fsp - > fh - > fd , ( unsigned int ) fattr ) ) ;
1998-08-01 02:39:15 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcreate ) ;
2007-08-14 00:29:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a create temporary file .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 19:42:39 +04:00
void reply_ctemp ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2007-08-14 19:42:39 +04:00
uint32 fattr ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 19:42:39 +04:00
int oplock_request ;
2002-12-04 02:57:45 +03:00
int tmpfd ;
SMB_STRUCT_STAT sbuf ;
2007-08-14 19:42:39 +04:00
char * s ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBctemp ) ;
return ;
}
2007-07-05 20:26:27 +04:00
2007-08-14 19:42:39 +04:00
fattr = SVAL ( req - > inbuf , smb_vwv0 ) ;
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname ,
smb_buf ( req - > inbuf ) + 1 , 0 , STR_TERMINATE ,
2007-08-14 19:42:39 +04:00
& status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:42:39 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2007-09-12 03:57:59 +04:00
if ( * fname ) {
fname = talloc_asprintf ( ctx ,
" %s/TMXXXXXX " ,
fname ) ;
2004-04-03 02:11:08 +04:00
} else {
2007-09-12 03:57:59 +04:00
fname = talloc_strdup ( ctx , " TMXXXXXX " ) ;
}
if ( ! fname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBctemp ) ;
return ;
2004-04-03 02:11:08 +04:00
}
2002-12-04 02:57:45 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 19:42:39 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBctemp ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 19:42:39 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBctemp ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2002-12-04 02:57:45 +03:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:42:39 +04:00
reply_nterror ( req , status ) ;
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
2007-09-11 22:31:29 +04:00
status = check_name ( conn , CONST_DISCARD ( char * , fname ) ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:42:39 +04:00
reply_nterror ( req , status ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
tmpfd = smb_mkstemp ( fname ) ;
if ( tmpfd = = - 1 ) {
2007-08-14 19:42:39 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2003-05-14 14:59:01 +04:00
SMB_VFS_STAT ( conn , fname , & sbuf ) ;
2002-12-04 02:57:45 +03:00
/* We should fail if file does not exist. */
2007-08-14 19:42:39 +04:00
status = open_file_ntcreate ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
FILE_GENERIC_READ | FILE_GENERIC_WRITE ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN ,
0 ,
fattr ,
oplock_request ,
2006-07-11 22:01:26 +04:00
NULL , & fsp ) ;
2002-12-04 02:57:45 +03:00
/* close fd from smb_mkstemp() */
close ( tmpfd ) ;
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:42:39 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2007-08-25 23:47:57 +04:00
END_PROFILE ( SMBctemp ) ;
2007-08-16 04:37:07 +04:00
return ;
}
2007-08-16 21:42:34 +04:00
reply_openerror ( req , status ) ;
2007-08-25 23:47:57 +04:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 19:42:39 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
2002-12-04 02:57:45 +03:00
/* the returned filename is relative to the directory */
s = strrchr_m ( fname , ' / ' ) ;
2005-07-08 08:51:27 +04:00
if ( ! s ) {
2002-12-04 02:57:45 +03:00
s = fname ;
2005-07-08 08:51:27 +04:00
} else {
2002-12-04 02:57:45 +03:00
s + + ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2004-04-03 02:11:08 +04:00
#if 0
/* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
thing in the byte section . JRA */
2002-12-04 02:57:45 +03:00
SSVALS ( p , 0 , - 1 ) ; /* what is this? not in spec */
2004-04-03 02:11:08 +04:00
# endif
2007-08-14 19:42:39 +04:00
if ( message_push_string ( & req - > outbuf , s , STR_ASCII | STR_TERMINATE )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBctemp ) ;
return ;
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 19:42:39 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 19:42:39 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
DEBUG ( 2 , ( " reply_ctemp: created temp file %s \n " , fname ) ) ;
DEBUG ( 3 , ( " reply_ctemp %s fd=%d umode=0%o \n " , fname , fsp - > fh - > fd ,
( unsigned int ) sbuf . st_mode ) ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2002-03-23 05:57:44 +03:00
/*******************************************************************
Check if a user is allowed to rename a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-16 14:02:51 +04:00
static NTSTATUS can_rename ( connection_struct * conn , files_struct * fsp ,
uint16 dirtype , SMB_STRUCT_STAT * pst )
2002-03-23 05:57:44 +03:00
{
2005-07-08 08:51:27 +04:00
uint32 fmode ;
2002-03-23 05:57:44 +03:00
2005-07-08 08:51:27 +04:00
if ( ! CAN_WRITE ( conn ) ) {
2002-03-23 05:57:44 +03:00
return NT_STATUS_MEDIA_WRITE_PROTECTED ;
2005-07-08 08:51:27 +04:00
}
2004-06-26 01:33:21 +04:00
2007-06-16 14:02:51 +04:00
fmode = dos_mode ( conn , fsp - > fsp_name , pst ) ;
2005-07-08 08:51:27 +04:00
if ( ( fmode & ~ dirtype ) & ( aHIDDEN | aSYSTEM ) ) {
2004-06-26 01:33:21 +04:00
return NT_STATUS_NO_SUCH_FILE ;
2005-07-08 08:51:27 +04:00
}
2004-06-26 01:33:21 +04:00
2005-07-08 08:51:27 +04:00
if ( S_ISDIR ( pst - > st_mode ) ) {
2002-03-23 05:57:44 +03:00
return NT_STATUS_OK ;
2005-07-08 08:51:27 +04:00
}
2002-03-23 05:57:44 +03:00
2007-06-16 14:02:51 +04:00
if ( fsp - > access_mask & DELETE_ACCESS ) {
return NT_STATUS_OK ;
2002-03-23 05:57:44 +03:00
}
2007-06-16 14:02:51 +04:00
return NT_STATUS_ACCESS_DENIED ;
2002-03-23 05:57:44 +03:00
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2007-06-13 13:55:13 +04:00
* unlink a file with all relevant access checks
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-17 06:19:17 +03:00
2007-09-13 01:48:20 +04:00
static NTSTATUS do_unlink ( connection_struct * conn ,
struct smb_request * req ,
const char * fname ,
uint32 dirtype )
1996-05-04 11:50:46 +04:00
{
2001-09-21 18:27:43 +04:00
SMB_STRUCT_STAT sbuf ;
2005-07-08 08:51:27 +04:00
uint32 fattr ;
2002-03-23 05:57:44 +03:00
files_struct * fsp ;
2007-01-13 02:47:16 +03:00
uint32 dirtype_orig = dirtype ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
1996-05-04 11:50:46 +04:00
2007-06-13 23:01:41 +04:00
DEBUG ( 10 , ( " do_unlink: %s, dirtype = %d \n " , fname , dirtype ) ) ;
2003-08-13 04:31:23 +04:00
2005-07-08 08:51:27 +04:00
if ( ! CAN_WRITE ( conn ) ) {
2001-11-17 06:19:17 +03:00
return NT_STATUS_MEDIA_WRITE_PROTECTED ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2004-02-25 03:48:35 +03:00
if ( SMB_VFS_LSTAT ( conn , fname , & sbuf ) ! = 0 ) {
return map_nt_error_from_unix ( errno ) ;
}
2001-09-21 18:27:43 +04:00
2005-07-08 08:51:27 +04:00
fattr = dos_mode ( conn , fname , & sbuf ) ;
2003-08-13 04:31:23 +04:00
2007-01-13 02:47:16 +03:00
if ( dirtype & FILE_ATTRIBUTE_NORMAL ) {
dirtype = aDIR | aARCH | aRONLY ;
}
dirtype & = ( aDIR | aARCH | aRONLY | aHIDDEN | aSYSTEM ) ;
if ( ! dirtype ) {
return NT_STATUS_NO_SUCH_FILE ;
}
if ( ! dir_check_ftype ( conn , fattr , dirtype ) ) {
if ( fattr & aDIR ) {
return NT_STATUS_FILE_IS_A_DIRECTORY ;
}
return NT_STATUS_NO_SUCH_FILE ;
}
if ( dirtype_orig & 0x8000 ) {
/* These will never be set for POSIX. */
return NT_STATUS_NO_SUCH_FILE ;
}
#if 0
if ( ( fattr & dirtype ) & FILE_ATTRIBUTE_DIRECTORY ) {
return NT_STATUS_FILE_IS_A_DIRECTORY ;
}
if ( ( fattr & ~ dirtype ) & ( FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ) ) {
return NT_STATUS_NO_SUCH_FILE ;
}
if ( dirtype & 0xFF00 ) {
/* These will never be set for POSIX. */
return NT_STATUS_NO_SUCH_FILE ;
}
dirtype & = 0xFF ;
if ( ! dirtype ) {
return NT_STATUS_NO_SUCH_FILE ;
}
2003-08-13 04:31:23 +04:00
/* Can't delete a directory. */
2005-07-08 08:51:27 +04:00
if ( fattr & aDIR ) {
2001-11-17 06:19:17 +03:00
return NT_STATUS_FILE_IS_A_DIRECTORY ;
2005-07-08 08:51:27 +04:00
}
2007-01-13 02:47:16 +03:00
# endif
2005-07-08 08:51:27 +04:00
2003-08-16 06:34:03 +04:00
#if 0 /* JRATEST */
2003-08-13 04:31:23 +04:00
else if ( dirtype & aDIR ) /* Asked for a directory and it isn't. */
return NT_STATUS_OBJECT_NAME_INVALID ;
2003-08-16 06:34:03 +04:00
# endif /* JRATEST */
2003-08-13 04:31:23 +04:00
2006-01-16 08:47:39 +03:00
/* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
On a Windows share , a file with read - only dosmode can be opened with
DELETE_ACCESS . But on a Samba share ( delete readonly = no ) , it
fails with NT_STATUS_CANNOT_DELETE error .
This semantic causes a problem that a user can not
rename a file with read - only dosmode on a Samba share
from a Windows command prompt ( i . e . cmd . exe , but can rename
from Windows Explorer ) .
*/
2007-01-02 18:07:27 +03:00
if ( ! lp_delete_readonly ( SNUM ( conn ) ) ) {
2005-07-08 08:51:27 +04:00
if ( fattr & aRONLY ) {
2001-11-17 06:19:17 +03:00
return NT_STATUS_CANNOT_DELETE ;
2005-07-08 08:51:27 +04:00
}
2001-09-21 18:27:43 +04:00
}
2007-01-02 18:07:27 +03:00
/* On open checks the open itself will check the share mode, so
don ' t do it here as we ' ll get it wrong . */
2007-07-05 20:26:27 +04:00
status = open_file_ntcreate ( conn , req , fname , & sbuf ,
2007-01-02 18:07:27 +03:00
DELETE_ACCESS ,
FILE_SHARE_NONE ,
FILE_OPEN ,
0 ,
FILE_ATTRIBUTE_NORMAL ,
2007-07-05 20:26:27 +04:00
req ! = NULL ? 0 : INTERNAL_OPEN_ONLY ,
2007-01-02 18:07:27 +03:00
NULL , & fsp ) ;
2007-06-13 13:55:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " open_file_ntcreate failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
2002-03-23 05:57:44 +03:00
}
2007-06-13 13:55:13 +04:00
/* The set is across all open files on this dev/inode pair. */
if ( ! set_delete_on_close ( fsp , True , & current_user . ut ) ) {
close_file ( fsp , NORMAL_CLOSE ) ;
return NT_STATUS_ACCESS_DENIED ;
}
return close_file ( fsp , NORMAL_CLOSE ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2000-11-15 00:56:32 +03:00
The guts of the unlink command , split out so it may be called by the NT SMB
code .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-07-05 20:26:27 +04:00
NTSTATUS unlink_internals ( connection_struct * conn , struct smb_request * req ,
2007-10-19 04:40:25 +04:00
uint32 dirtype , const char * name_in , bool has_wild )
1996-05-04 11:50:46 +04:00
{
2007-09-13 01:48:20 +04:00
const char * directory = NULL ;
char * mask = NULL ;
2007-09-08 00:57:01 +04:00
char * name = NULL ;
2007-09-13 01:48:20 +04:00
char * p = NULL ;
2001-08-27 12:19:43 +04:00
int count = 0 ;
2007-01-13 02:47:16 +03:00
NTSTATUS status = NT_STATUS_OK ;
2001-08-27 12:19:43 +04:00
SMB_STRUCT_STAT sbuf ;
2007-09-13 01:48:20 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-09-08 00:57:01 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , name_in , has_wild , & name , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-09-08 00:57:01 +04:00
2001-08-27 12:19:43 +04:00
p = strrchr_m ( name , ' / ' ) ;
if ( ! p ) {
2007-09-13 01:48:20 +04:00
directory = talloc_strdup ( ctx , " . " ) ;
if ( ! directory ) {
return NT_STATUS_NO_MEMORY ;
}
mask = name ;
2001-08-27 12:19:43 +04:00
} else {
* p = 0 ;
2007-09-13 01:48:20 +04:00
directory = name ;
mask = p + 1 ;
2001-08-27 12:19:43 +04:00
}
2007-09-08 00:57:01 +04:00
2001-08-27 12:19:43 +04:00
/*
* We should only check the mangled cache
* here if unix_convert failed . This means
* that the path in ' mask ' doesn ' t exist
* on the file system and so we need to look
* for a possible mangle . This patch from
* Tine Smukavec < valentin . smukavec @ hermes . si > .
*/
2007-09-08 00:57:01 +04:00
if ( ! VALID_STAT ( sbuf ) & & mangle_is_mangled ( mask , conn - > params ) ) {
char * new_mask = NULL ;
2007-09-13 01:48:20 +04:00
mangle_lookup_name_from_8_3 ( ctx ,
2007-09-08 00:57:01 +04:00
mask ,
& new_mask ,
conn - > params ) ;
if ( new_mask ) {
2007-09-13 01:48:20 +04:00
mask = new_mask ;
2007-09-08 00:57:01 +04:00
}
}
2001-08-27 12:19:43 +04:00
if ( ! has_wild ) {
2007-09-13 01:48:20 +04:00
directory = talloc_asprintf ( ctx ,
" %s/%s " ,
directory ,
mask ) ;
if ( ! directory ) {
return NT_STATUS_NO_MEMORY ;
}
2007-01-13 02:47:16 +03:00
if ( dirtype = = 0 ) {
dirtype = FILE_ATTRIBUTE_NORMAL ;
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-07-05 20:26:27 +04:00
status = do_unlink ( conn , req , directory , dirtype ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-13 02:47:16 +03:00
return status ;
2007-01-17 05:09:37 +03:00
}
2001-09-21 18:27:43 +04:00
2007-06-13 13:55:13 +04:00
count + + ;
2001-08-27 12:19:43 +04:00
} else {
2005-02-01 03:28:20 +03:00
struct smb_Dir * dir_hnd = NULL ;
2007-01-17 05:09:37 +03:00
long offset = 0 ;
2003-03-18 01:56:13 +03:00
const char * dname ;
2007-09-08 00:57:01 +04:00
2007-01-13 02:47:16 +03:00
if ( ( dirtype & SAMBA_ATTRIBUTES_MASK ) = = aDIR ) {
return NT_STATUS_OBJECT_NAME_INVALID ;
2007-01-09 21:48:38 +03:00
}
2007-01-17 05:09:37 +03:00
if ( strequal ( mask , " ????????.??? " ) ) {
2007-09-13 01:48:20 +04:00
mask [ 0 ] = ' * ' ;
mask [ 1 ] = ' \0 ' ;
2007-01-17 05:09:37 +03:00
}
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2005-06-25 07:03:44 +04:00
2007-01-17 05:09:37 +03:00
dir_hnd = OpenDir ( conn , directory , mask , dirtype ) ;
if ( dir_hnd = = NULL ) {
return map_nt_error_from_unix ( errno ) ;
}
2007-09-13 01:48:20 +04:00
2001-08-27 12:19:43 +04:00
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
the pattern matches against the long name , otherwise the short name
We don ' t implement this yet XXXX
*/
2007-09-13 01:48:20 +04:00
2007-01-17 05:09:37 +03:00
status = NT_STATUS_NO_SUCH_FILE ;
2007-01-09 18:50:40 +03:00
2007-01-17 05:09:37 +03:00
while ( ( dname = ReadDirName ( dir_hnd , & offset ) ) ) {
SMB_STRUCT_STAT st ;
2007-09-13 01:48:20 +04:00
char * fname = NULL ;
2007-01-09 18:50:40 +03:00
2007-01-17 05:09:37 +03:00
if ( ! is_visible_file ( conn , directory , dname , & st , True ) ) {
continue ;
}
2007-01-09 12:03:33 +03:00
2007-01-17 05:09:37 +03:00
/* Quick check for "." and ".." */
2007-09-13 01:48:20 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
continue ;
2007-01-17 05:09:37 +03:00
}
2004-02-24 04:46:24 +03:00
2007-09-13 01:48:20 +04:00
if ( ! mask_match ( dname , mask , conn - > case_sensitive ) ) {
2007-01-17 05:09:37 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
fname = talloc_asprintf ( ctx , " %s/%s " ,
directory ,
dname ) ;
if ( ! fname ) {
return NT_STATUS_NO_MEMORY ;
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-12 21:19:48 +03:00
CloseDir ( dir_hnd ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
return status ;
}
2007-07-05 20:26:27 +04:00
status = do_unlink ( conn , req , fname , dirtype ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( fname ) ;
2007-01-17 05:09:37 +03:00
continue ;
2001-08-27 12:19:43 +04:00
}
2007-06-13 13:55:13 +04:00
count + + ;
DEBUG ( 3 , ( " unlink_internals: succesful unlink [%s] \n " ,
fname ) ) ;
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( fname ) ;
2001-08-27 12:19:43 +04:00
}
2007-01-17 05:09:37 +03:00
CloseDir ( dir_hnd ) ;
2001-08-27 12:19:43 +04:00
}
2007-09-13 01:48:20 +04:00
2007-01-13 02:47:16 +03:00
if ( count = = 0 & & NT_STATUS_IS_OK ( status ) ) {
status = map_nt_error_from_unix ( errno ) ;
2001-08-27 12:19:43 +04:00
}
2001-09-04 11:13:01 +04:00
2007-01-13 02:47:16 +03:00
return status ;
2000-11-15 00:56:32 +03:00
}
/****************************************************************************
Reply to a unlink
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-31 11:57:33 +04:00
void reply_unlink ( connection_struct * conn , struct smb_request * req )
2000-11-15 00:56:32 +03:00
{
2007-09-11 22:31:29 +04:00
char * name = NULL ;
2005-06-25 07:03:44 +04:00
uint32 dirtype ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2007-10-19 04:40:25 +04:00
bool path_contains_wcard = False ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-10-31 23:11:58 +03:00
2005-11-02 02:49:40 +03:00
START_PROFILE ( SMBunlink ) ;
2007-07-31 11:57:33 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBunlink ) ;
return ;
}
2007-07-05 20:26:27 +04:00
2007-07-31 11:57:33 +04:00
dirtype = SVAL ( req - > inbuf , smb_vwv0 ) ;
2007-09-11 22:31:29 +04:00
2007-09-12 03:57:59 +04:00
srvstr_get_path_wcard ( ctx , ( char * ) req - > inbuf , req - > flags2 , & name ,
smb_buf ( req - > inbuf ) + 1 , 0 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status , & path_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBunlink ) ;
2007-07-31 11:57:33 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2007-03-12 20:55:24 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath_wcard ( ctx , conn ,
2007-07-31 11:57:33 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
name ,
2007-09-11 22:31:29 +04:00
& name ,
& path_contains_wcard ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-31 11:57:33 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBunlink ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBunlink ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " reply_unlink : %s \n " , name ) ) ;
2007-09-11 22:31:29 +04:00
2007-07-31 11:57:33 +04:00
status = unlink_internals ( conn , req , dirtype , name ,
2007-07-05 20:26:27 +04:00
path_contains_wcard ) ;
2004-06-08 20:14:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 11:57:33 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2007-07-31 11:57:33 +04:00
END_PROFILE ( SMBunlink ) ;
return ;
2004-06-08 20:14:31 +04:00
}
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBunlink ) ;
return ;
2004-06-08 20:14:31 +04:00
}
2001-09-04 11:13:01 +04:00
2007-07-31 11:57:33 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlink ) ;
2007-07-31 11:57:33 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2001-09-04 23:10:30 +04:00
/****************************************************************************
Fail for readbraw .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-11-25 01:05:59 +03:00
static void fail_readraw ( void )
2001-09-04 23:10:30 +04:00
{
2007-09-13 01:48:20 +04:00
const char * errstr = talloc_asprintf ( talloc_tos ( ) ,
" FAIL ! reply_readbraw: socket write fail (%s) " ,
strerror ( errno ) ) ;
if ( ! errstr ) {
errstr = " " ;
}
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( errstr ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2004-11-25 01:05:59 +03:00
/****************************************************************************
Fake ( read / write ) sendfile . Returns - 1 on read or write fail .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-12 15:22:26 +04:00
static ssize_t fake_sendfile ( files_struct * fsp , SMB_OFF_T startpos ,
size_t nread )
2004-11-25 01:05:59 +03:00
{
2007-08-12 15:22:26 +04:00
size_t bufsize ;
2007-05-16 04:07:38 +04:00
size_t tosend = nread ;
2007-08-12 15:22:26 +04:00
char * buf ;
if ( nread = = 0 ) {
return 0 ;
}
bufsize = MIN ( nread , 65536 ) ;
if ( ! ( buf = SMB_MALLOC_ARRAY ( char , bufsize ) ) ) {
return - 1 ;
}
2004-11-25 01:05:59 +03:00
2007-05-16 04:07:38 +04:00
while ( tosend > 0 ) {
ssize_t ret ;
size_t cur_read ;
2004-11-25 01:05:59 +03:00
2007-05-16 04:07:38 +04:00
if ( tosend > bufsize ) {
cur_read = bufsize ;
} else {
cur_read = tosend ;
}
ret = read_file ( fsp , buf , startpos , cur_read ) ;
2004-11-25 01:05:59 +03:00
if ( ret = = - 1 ) {
2007-08-12 15:22:26 +04:00
SAFE_FREE ( buf ) ;
2004-11-25 01:05:59 +03:00
return - 1 ;
}
2007-05-16 04:07:38 +04:00
/* If we had a short read, fill with zeros. */
if ( ret < cur_read ) {
memset ( buf , ' \0 ' , cur_read - ret ) ;
}
2004-11-25 01:05:59 +03:00
2007-05-16 04:07:38 +04:00
if ( write_data ( smbd_server_fd ( ) , buf , cur_read ) ! = cur_read ) {
2007-08-12 15:22:26 +04:00
SAFE_FREE ( buf ) ;
2007-05-16 04:07:38 +04:00
return - 1 ;
}
tosend - = cur_read ;
startpos + = cur_read ;
}
2004-11-25 01:05:59 +03:00
2007-08-12 15:22:26 +04:00
SAFE_FREE ( buf ) ;
2004-11-25 01:05:59 +03:00
return ( ssize_t ) nread ;
}
2007-08-14 05:45:26 +04:00
/****************************************************************************
Return a readbraw error ( 4 bytes of zero ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void reply_readbraw_error ( void )
{
char header [ 4 ] ;
SIVAL ( header , 0 , 0 ) ;
if ( write_data ( smbd_server_fd ( ) , header , 4 ) ! = 4 ) {
fail_readraw ( ) ;
}
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Use sendfile in readbraw .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 05:45:26 +04:00
void send_file_readbraw ( connection_struct * conn ,
files_struct * fsp ,
SMB_OFF_T startpos ,
size_t nread ,
ssize_t mincount )
2002-09-25 19:19:00 +04:00
{
2007-08-14 05:45:26 +04:00
char * outbuf = NULL ;
2002-09-25 19:19:00 +04:00
ssize_t ret = 0 ;
# if defined(WITH_SENDFILE)
/*
2004-07-01 03:00:40 +04:00
* We can only use sendfile on a non - chained packet
* but we can use on a non - oplocked file . tridge proved this
* on a train in Germany : - ) . JRA .
* reply_readbraw has already checked the length .
2002-09-25 19:19:00 +04:00
*/
2006-03-20 02:32:50 +03:00
if ( ( chain_size = = 0 ) & & ( nread > 0 ) & &
( fsp - > wcp = = NULL ) & & lp_use_sendfile ( SNUM ( conn ) ) ) {
2007-08-14 05:45:26 +04:00
char header [ 4 ] ;
DATA_BLOB header_blob ;
_smb_setlen ( header , nread ) ;
2007-08-14 10:18:55 +04:00
header_blob = data_blob_const ( header , 4 ) ;
2007-08-14 05:45:26 +04:00
if ( SMB_VFS_SENDFILE ( smbd_server_fd ( ) , fsp , fsp - > fh - > fd ,
& header_blob , startpos , nread ) = = - 1 ) {
/* Returning ENOSYS means no data at all was sent.
* Do this as a normal read . */
2004-12-21 01:01:42 +03:00
if ( errno = = ENOSYS ) {
goto normal_readbraw ;
}
2002-09-25 19:19:00 +04:00
/*
2004-11-25 01:05:59 +03:00
* Special hack for broken Linux with no working sendfile . If we
* return EINTR we sent the header but not the rest of the data .
* Fake this up by doing read / write calls .
2002-09-25 19:19:00 +04:00
*/
2004-11-25 01:05:59 +03:00
if ( errno = = EINTR ) {
/* Ensure we don't do this again. */
2004-08-06 21:49:00 +04:00
set_use_sendfile ( SNUM ( conn ) , False ) ;
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readbraw: sendfile not available. Faking.. \n " ) ) ;
2007-08-12 15:22:26 +04:00
if ( fake_sendfile ( fsp , startpos , nread ) = = - 1 ) {
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readbraw: fake_sendfile failed for file %s (%s). \n " ,
fsp - > fsp_name , strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readbraw fake_sendfile failed " ) ;
2004-11-25 01:05:59 +03:00
}
return ;
2004-08-06 21:49:00 +04:00
}
2002-09-25 19:19:00 +04:00
DEBUG ( 0 , ( " send_file_readbraw: sendfile failed for file %s (%s). Terminating \n " ,
fsp - > fsp_name , strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readbraw sendfile failed " ) ;
2002-09-25 19:19:00 +04:00
}
2007-05-09 04:52:46 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
# endif
2007-06-01 23:34:08 +04:00
normal_readbraw :
2007-08-14 05:45:26 +04:00
outbuf = TALLOC_ARRAY ( NULL , char , nread + 4 ) ;
if ( ! outbuf ) {
DEBUG ( 0 , ( " send_file_readbraw: TALLOC_ARRAY failed for size %u. \n " ,
2007-08-14 12:29:36 +04:00
( unsigned ) ( nread + 4 ) ) ) ;
2007-08-14 05:45:26 +04:00
reply_readbraw_error ( ) ;
return ;
}
2002-09-25 19:19:00 +04:00
if ( nread > 0 ) {
ret = read_file ( fsp , outbuf + 4 , startpos , nread ) ;
2003-10-09 05:46:01 +04:00
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2002-09-25 19:19:00 +04:00
if ( ret < mincount )
ret = 0 ;
2003-10-09 05:46:01 +04:00
# else
if ( ret < nread )
ret = 0 ;
# endif
2002-09-25 19:19:00 +04:00
}
_smb_setlen ( outbuf , ret ) ;
if ( write_data ( smbd_server_fd ( ) , outbuf , 4 + ret ) ! = 4 + ret )
fail_readraw ( ) ;
2007-08-14 05:45:26 +04:00
TALLOC_FREE ( outbuf ) ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-09-04 23:10:30 +04:00
Reply to a readbraw ( core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-14 05:45:26 +04:00
void reply_readbraw ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-11-14 05:35:56 +03:00
ssize_t maxcount , mincount ;
2001-09-04 23:10:30 +04:00
size_t nread = 0 ;
SMB_OFF_T startpos ;
files_struct * fsp ;
2007-08-14 05:45:26 +04:00
SMB_STRUCT_STAT st ;
SMB_OFF_T size = 0 ;
2001-09-04 23:10:30 +04:00
START_PROFILE ( SMBreadbraw ) ;
1996-05-04 11:50:46 +04:00
2003-07-18 04:53:34 +04:00
if ( srv_is_signing_active ( ) ) {
2007-08-14 05:45:26 +04:00
exit_server_cleanly ( " reply_readbraw: SMB signing is active - "
" raw reads/writes are disallowed. " ) ;
}
if ( req - > wct < 8 ) {
reply_readbraw_error ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ;
2003-07-17 04:53:37 +04:00
}
2001-09-04 23:10:30 +04:00
/*
* Special check if an oplock break has been issued
* and the readraw request croses on the wire , we must
* return a zero length response here .
*/
1997-10-02 03:32:22 +04:00
2007-08-14 05:45:26 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
1996-05-04 11:50:46 +04:00
2007-08-25 23:47:57 +04:00
/*
2007-08-14 05:45:26 +04:00
* We have to do a check_fsp by hand here , as
* we must always return 4 zero bytes on error ,
* not a NTSTATUS .
*/
if ( ! fsp | | ! conn | | conn ! = fsp - > conn | |
current_user . vuid ! = fsp - > vuid | |
fsp - > is_directory | | fsp - > fh - > fd = = - 1 ) {
2001-09-04 23:10:30 +04:00
/*
* fsp could be NULL here so use the value from the packet . JRA .
*/
2007-08-14 05:45:26 +04:00
DEBUG ( 3 , ( " reply_readbraw: fnum %d not valid "
" - cache prime? \n " ,
( int ) SVAL ( req - > inbuf , smb_vwv0 ) ) ) ;
reply_readbraw_error ( ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
1999-12-13 16:27:58 +03:00
2007-08-14 05:45:26 +04:00
/* Do a "by hand" version of CHECK_READ. */
if ( ! ( fsp - > can_read | |
( ( req - > flags2 & FLAGS2_READ_PERMIT_EXECUTE ) & &
( fsp - > access_mask & FILE_EXECUTE ) ) ) ) {
DEBUG ( 3 , ( " reply_readbraw: fnum %d not readable. \n " ,
( int ) SVAL ( req - > inbuf , smb_vwv0 ) ) ) ;
reply_readbraw_error ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ;
}
1999-12-13 16:27:58 +03:00
2001-09-04 23:10:30 +04:00
flush_write_cache ( fsp , READRAW_FLUSH ) ;
1999-12-13 16:27:58 +03:00
2007-08-14 05:45:26 +04:00
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv1 ) ;
2007-08-14 10:18:55 +04:00
if ( req - > wct = = 10 ) {
2001-09-04 23:10:30 +04:00
/*
* This is a large offset ( 64 bit ) read .
*/
1999-12-13 16:27:58 +03:00
# ifdef LARGE_SMB_OFF_T
2007-08-14 05:45:26 +04:00
startpos | = ( ( ( SMB_OFF_T ) IVAL ( req - > inbuf , smb_vwv8 ) ) < < 32 ) ;
1999-12-13 16:27:58 +03:00
# else /* !LARGE_SMB_OFF_T */
2001-09-04 23:10:30 +04:00
/*
* Ensure we haven ' t been sent a > 32 bit offset .
*/
1999-12-13 16:27:58 +03:00
2007-08-14 05:45:26 +04:00
if ( IVAL ( req - > inbuf , smb_vwv8 ) ! = 0 ) {
DEBUG ( 0 , ( " reply_readbraw: large offset "
" (%x << 32) used and we don't support "
" 64 bit offsets. \n " ,
( unsigned int ) IVAL ( req - > inbuf , smb_vwv8 ) ) ) ;
reply_readbraw_error ( ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
1999-12-13 16:27:58 +03:00
# endif /* LARGE_SMB_OFF_T */
2001-09-04 23:10:30 +04:00
if ( startpos < 0 ) {
2007-08-14 05:45:26 +04:00
DEBUG ( 0 , ( " reply_readbraw: negative 64 bit "
" readraw offset (%.0f) ! \n " ,
( double ) startpos ) ) ;
reply_readbraw_error ( ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
}
2007-08-14 05:45:26 +04:00
maxcount = ( SVAL ( req - > inbuf , smb_vwv3 ) & 0xFFFF ) ;
mincount = ( SVAL ( req - > inbuf , smb_vwv4 ) & 0xFFFF ) ;
2001-09-04 23:10:30 +04:00
/* ensure we don't overrun the packet size */
maxcount = MIN ( 65535 , maxcount ) ;
2007-08-14 05:45:26 +04:00
if ( is_locked ( fsp , ( uint32 ) req - > smbpid ,
( SMB_BIG_UINT ) maxcount ,
( SMB_BIG_UINT ) startpos ,
READ_LOCK ) ) {
reply_readbraw_error ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2007-08-14 05:45:26 +04:00
if ( SMB_VFS_FSTAT ( fsp , fsp - > fh - > fd , & st ) = = 0 ) {
size = st . st_size ;
}
if ( startpos > = size ) {
nread = 0 ;
} else {
2007-08-25 23:47:57 +04:00
nread = MIN ( maxcount , ( size - startpos ) ) ;
2001-09-04 23:10:30 +04:00
}
1998-07-31 01:18:57 +04:00
2003-10-09 05:46:01 +04:00
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2001-09-04 23:10:30 +04:00
if ( nread < mincount )
nread = 0 ;
2003-10-09 05:46:01 +04:00
# endif
1996-05-04 11:50:46 +04:00
2007-08-14 05:45:26 +04:00
DEBUG ( 3 , ( " reply_readbraw: fnum=%d start=%.0f max=%lu "
" min=%lu nread=%lu \n " ,
fsp - > fnum , ( double ) startpos ,
( unsigned long ) maxcount ,
( unsigned long ) mincount ,
( unsigned long ) nread ) ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 05:45:26 +04:00
send_file_readbraw ( conn , fsp , startpos , nread , mincount ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 05:45:26 +04:00
DEBUG ( 5 , ( " reply_readbraw finished \n " ) ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lockread ( core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-15 00:20:51 +04:00
void reply_lockread ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-08-27 12:19:43 +04:00
ssize_t nread = - 1 ;
char * data ;
SMB_OFF_T startpos ;
size_t numtoread ;
NTSTATUS status ;
2007-08-15 00:20:51 +04:00
files_struct * fsp ;
2006-07-18 05:05:51 +04:00
struct byte_range_lock * br_lck = NULL ;
2007-09-08 00:57:01 +04:00
char * p = NULL ;
2007-08-15 00:20:51 +04:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBlockread ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:20:51 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockread ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBlockread ) ;
return ;
}
if ( ! CHECK_READ ( fsp , req - > inbuf ) ) {
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
END_PROFILE ( SMBlockread ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
release_level_2_oplocks_on_change ( fsp ) ;
2000-11-16 03:59:18 +03:00
2007-08-15 00:20:51 +04:00
numtoread = SVAL ( req - > inbuf , smb_vwv1 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv2 ) ;
numtoread = MIN ( BUFFER_SIZE - ( smb_size + 3 * 2 + 3 ) , numtoread ) ;
reply_outbuf ( req , 5 , numtoread + 3 ) ;
data = smb_buf ( req - > outbuf ) + 3 ;
2001-08-27 12:19:43 +04:00
/*
* NB . Discovered by Menny Hamburger at Mainsoft . This is a core +
* protocol request that predates the read / write lock concept .
* Thus instead of asking for a read lock here we need to ask
* for a write lock . JRA .
2003-10-09 05:46:01 +04:00
* Note that the requested lock size is unaffected by max_recv .
2001-08-27 12:19:43 +04:00
*/
2007-05-14 17:01:28 +04:00
br_lck = do_lock ( smbd_messaging_context ( ) ,
fsp ,
2007-08-15 00:20:51 +04:00
req - > smbpid ,
2006-07-18 01:09:02 +04:00
( SMB_BIG_UINT ) numtoread ,
( SMB_BIG_UINT ) startpos ,
WRITE_LOCK ,
WINDOWS_LOCK ,
2006-07-18 05:05:51 +04:00
False , /* Non-blocking lock. */
2007-05-20 00:57:12 +04:00
& status ,
NULL ) ;
2006-07-18 05:05:51 +04:00
TALLOC_FREE ( br_lck ) ;
1999-12-13 16:27:58 +03:00
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
1998-08-01 02:39:15 +04:00
2003-10-09 05:46:01 +04:00
/*
* However the requested READ size IS affected by max_recv . Insanity . . . . JRA .
*/
2003-10-09 23:01:31 +04:00
if ( numtoread > max_recv ) {
DEBUG ( 0 , ( " reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
Returning short read of maximum allowed for compatibility with Windows 2000. \ n " ,
( unsigned int ) numtoread , ( unsigned int ) max_recv ) ) ;
numtoread = MIN ( numtoread , max_recv ) ;
}
2001-08-27 12:19:43 +04:00
nread = read_file ( fsp , data , startpos , numtoread ) ;
1998-08-01 02:39:15 +04:00
2001-08-27 12:19:43 +04:00
if ( nread < 0 ) {
2007-08-15 00:20:51 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
2007-10-11 00:34:30 +04:00
set_message ( ( char * ) req - > outbuf , 5 , nread + 3 , False ) ;
2007-08-15 00:20:51 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nread ) ;
SSVAL ( req - > outbuf , smb_vwv5 , nread + 3 ) ;
2007-09-08 00:57:01 +04:00
p = smb_buf ( req - > outbuf ) ;
SCVAL ( p , 0 , 0 ) ; /* pad byte. */
SSVAL ( p , 1 , nread ) ;
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " lockread fnum=%d num=%d nread=%d \n " ,
fsp - > fnum , ( int ) numtoread , ( int ) nread ) ) ;
1998-08-01 02:39:15 +04:00
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a read .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-14 22:33:29 +04:00
void reply_read ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-09-25 19:19:00 +04:00
size_t numtoread ;
ssize_t nread = 0 ;
char * data ;
SMB_OFF_T startpos ;
int outsize = 0 ;
2007-08-14 22:33:29 +04:00
files_struct * fsp ;
2002-09-25 19:19:00 +04:00
START_PROFILE ( SMBread ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:33:29 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBread ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2001-08-27 12:19:43 +04:00
2007-08-14 22:33:29 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBread ) ;
return ;
}
if ( ! CHECK_READ ( fsp , req - > inbuf ) ) {
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
END_PROFILE ( SMBread ) ;
return ;
}
numtoread = SVAL ( req - > inbuf , smb_vwv1 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv2 ) ;
2001-08-27 12:19:43 +04:00
2002-09-25 19:19:00 +04:00
numtoread = MIN ( BUFFER_SIZE - outsize , numtoread ) ;
2007-08-14 22:33:29 +04:00
2003-10-09 05:46:01 +04:00
/*
* The requested read size cannot be greater than max_recv . JRA .
*/
2003-10-09 23:01:31 +04:00
if ( numtoread > max_recv ) {
DEBUG ( 0 , ( " reply_read: requested read size (%u) is greater than maximum allowed (%u). \
Returning short read of maximum allowed for compatibility with Windows 2000. \ n " ,
( unsigned int ) numtoread , ( unsigned int ) max_recv ) ) ;
numtoread = MIN ( numtoread , max_recv ) ;
}
2003-10-09 05:46:01 +04:00
2007-08-14 22:33:29 +04:00
reply_outbuf ( req , 5 , numtoread + 3 ) ;
data = smb_buf ( req - > outbuf ) + 3 ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:33:29 +04:00
if ( is_locked ( fsp , ( uint32 ) req - > smbpid , ( SMB_BIG_UINT ) numtoread ,
( SMB_BIG_UINT ) startpos , READ_LOCK ) ) {
reply_doserror ( req , ERRDOS , ERRlock ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
2007-08-14 22:33:29 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
if ( numtoread > 0 )
nread = read_file ( fsp , data , startpos , numtoread ) ;
2001-08-27 12:19:43 +04:00
2002-09-25 19:19:00 +04:00
if ( nread < 0 ) {
2007-08-14 22:33:29 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
2007-08-14 22:33:29 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2007-08-14 22:33:29 +04:00
2007-10-11 00:34:30 +04:00
set_message ( ( char * ) req - > outbuf , 5 , nread + 3 , False ) ;
2007-08-14 22:33:29 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nread ) ;
SSVAL ( req - > outbuf , smb_vwv5 , nread + 3 ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , nread ) ;
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
DEBUG ( 3 , ( " read fnum=%d num=%d nread=%d \n " ,
fsp - > fnum , ( int ) numtoread , ( int ) nread ) ) ;
1998-08-01 02:39:15 +04:00
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
2007-08-14 22:33:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2007-05-16 04:07:38 +04:00
/****************************************************************************
Setup readX header .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-11 00:34:30 +04:00
static int setup_readX_header ( char * outbuf , size_t smb_maxcnt )
2007-05-16 04:07:38 +04:00
{
int outsize ;
2007-08-12 15:40:27 +04:00
char * data ;
2007-10-11 00:34:30 +04:00
outsize = set_message ( outbuf , 12 , smb_maxcnt , False ) ;
2007-08-12 15:40:27 +04:00
data = smb_buf ( outbuf ) ;
2007-05-16 04:07:38 +04:00
2007-09-13 01:48:20 +04:00
memset ( outbuf + smb_vwv0 , ' \0 ' , 24 ) ; /* valgrind init. */
SCVAL ( outbuf , smb_vwv0 , 0xFF ) ;
2007-05-16 04:07:38 +04:00
SSVAL ( outbuf , smb_vwv2 , 0xFFFF ) ; /* Remaining - must be -1. */
SSVAL ( outbuf , smb_vwv5 , smb_maxcnt ) ;
SSVAL ( outbuf , smb_vwv6 , smb_offset ( data , outbuf ) ) ;
SSVAL ( outbuf , smb_vwv7 , ( smb_maxcnt > > 16 ) ) ;
SSVAL ( smb_buf ( outbuf ) , - 2 , smb_maxcnt ) ;
/* Reset the outgoing length, set_message truncates at 0x1FFFF. */
_smb_setlen_large ( outbuf , ( smb_size + 12 * 2 + smb_maxcnt - 4 ) ) ;
return outsize ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Reply to a read and X - possibly using sendfile .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-12 13:16:54 +04:00
static void send_file_readX ( connection_struct * conn , struct smb_request * req ,
files_struct * fsp , SMB_OFF_T startpos ,
size_t smb_maxcnt )
2002-09-25 19:19:00 +04:00
{
2007-05-16 04:07:38 +04:00
SMB_STRUCT_STAT sbuf ;
2002-09-25 19:19:00 +04:00
ssize_t nread = - 1 ;
2007-08-12 13:16:54 +04:00
2007-05-16 04:07:38 +04:00
if ( SMB_VFS_FSTAT ( fsp , fsp - > fh - > fd , & sbuf ) = = - 1 ) {
2007-08-12 13:16:54 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2007-05-16 04:07:38 +04:00
}
if ( startpos > sbuf . st_size ) {
smb_maxcnt = 0 ;
2007-07-09 04:48:07 +04:00
} else if ( smb_maxcnt > ( sbuf . st_size - startpos ) ) {
2007-05-16 04:07:38 +04:00
smb_maxcnt = ( sbuf . st_size - startpos ) ;
}
if ( smb_maxcnt = = 0 ) {
goto normal_read ;
}
2002-09-25 19:19:00 +04:00
# if defined(WITH_SENDFILE)
/*
2007-09-13 01:48:20 +04:00
* We can only use sendfile on a non - chained packet
2004-07-01 03:00:40 +04:00
* but we can use on a non - oplocked file . tridge proved this
* on a train in Germany : - ) . JRA .
2002-09-25 19:19:00 +04:00
*/
2007-08-12 15:40:27 +04:00
if ( ( chain_size = = 0 ) & & ( CVAL ( req - > inbuf , smb_vwv0 ) = = 0xFF ) & &
2006-03-20 02:32:50 +03:00
lp_use_sendfile ( SNUM ( conn ) ) & & ( fsp - > wcp = = NULL ) ) {
2007-08-12 16:57:56 +04:00
uint8 headerbuf [ smb_size + 12 * 2 ] ;
2002-09-25 19:19:00 +04:00
DATA_BLOB header ;
2007-09-13 01:48:20 +04:00
/*
2002-09-25 19:19:00 +04:00
* Set up the packet header before send . We
* assume here the sendfile will work ( get the
* correct amount of data ) .
*/
2007-08-12 15:40:27 +04:00
header = data_blob_const ( headerbuf , sizeof ( headerbuf ) ) ;
2007-08-12 16:57:56 +04:00
construct_reply_common ( ( char * ) req - > inbuf , ( char * ) headerbuf ) ;
2007-10-11 00:34:30 +04:00
setup_readX_header ( ( char * ) headerbuf , smb_maxcnt ) ;
2002-09-25 19:19:00 +04:00
2005-07-08 08:51:27 +04:00
if ( ( nread = SMB_VFS_SENDFILE ( smbd_server_fd ( ) , fsp , fsp - > fh - > fd , & header , startpos , smb_maxcnt ) ) = = - 1 ) {
2004-12-21 01:01:42 +03:00
/* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
if ( errno = = ENOSYS ) {
goto normal_read ;
}
2002-09-25 19:19:00 +04:00
/*
2004-11-25 01:05:59 +03:00
* Special hack for broken Linux with no working sendfile . If we
* return EINTR we sent the header but not the rest of the data .
* Fake this up by doing read / write calls .
2002-09-25 19:19:00 +04:00
*/
2004-12-21 01:01:42 +03:00
2004-11-25 01:05:59 +03:00
if ( errno = = EINTR ) {
/* Ensure we don't do this again. */
2004-08-06 21:49:00 +04:00
set_use_sendfile ( SNUM ( conn ) , False ) ;
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readX: sendfile not available. Faking.. \n " ) ) ;
2007-08-12 15:22:26 +04:00
nread = fake_sendfile ( fsp , startpos ,
smb_maxcnt ) ;
if ( nread = = - 1 ) {
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readX: fake_sendfile failed for file %s (%s). \n " ,
fsp - > fsp_name , strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readX: fake_sendfile failed " ) ;
2004-11-25 01:05:59 +03:00
}
2004-12-21 01:01:42 +03:00
DEBUG ( 3 , ( " send_file_readX: fake_sendfile fnum=%d max=%d nread=%d \n " ,
2004-12-21 01:04:53 +03:00
fsp - > fnum , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2007-08-12 13:16:54 +04:00
/* No outbuf here means successful sendfile. */
TALLOC_FREE ( req - > outbuf ) ;
return ;
2004-08-06 21:49:00 +04:00
}
2002-09-25 19:19:00 +04:00
DEBUG ( 0 , ( " send_file_readX: sendfile failed for file %s (%s). Terminating \n " ,
fsp - > fsp_name , strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readX sendfile failed " ) ;
2002-09-25 19:19:00 +04:00
}
DEBUG ( 3 , ( " send_file_readX: sendfile fnum=%d max=%d nread=%d \n " ,
fsp - > fnum , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2007-08-12 13:16:54 +04:00
/* No outbuf here means successful sendfile. */
TALLOC_FREE ( req - > outbuf ) ;
return ;
2002-09-25 19:19:00 +04:00
}
# endif
2007-06-01 23:34:08 +04:00
normal_read :
2007-05-16 04:21:12 +04:00
2007-08-12 16:57:56 +04:00
if ( ( smb_maxcnt & 0xFF0000 ) > 0x10000 ) {
uint8 headerbuf [ smb_size + 2 * 12 ] ;
2007-08-12 15:40:27 +04:00
2007-08-12 16:57:56 +04:00
construct_reply_common ( ( char * ) req - > inbuf , ( char * ) headerbuf ) ;
2007-10-11 00:34:30 +04:00
setup_readX_header ( ( char * ) headerbuf , smb_maxcnt ) ;
2007-08-12 15:40:27 +04:00
2007-05-16 04:07:38 +04:00
/* Send out the header. */
2007-08-12 16:57:56 +04:00
if ( write_data ( smbd_server_fd ( ) , ( char * ) headerbuf ,
sizeof ( headerbuf ) ) ! = sizeof ( headerbuf ) ) {
2007-05-16 04:07:38 +04:00
DEBUG ( 0 , ( " send_file_readX: write_data failed for file %s (%s). Terminating \n " ,
fsp - > fsp_name , strerror ( errno ) ) ) ;
exit_server_cleanly ( " send_file_readX sendfile failed " ) ;
}
2007-08-12 15:22:26 +04:00
nread = fake_sendfile ( fsp , startpos , smb_maxcnt ) ;
if ( nread = = - 1 ) {
2007-05-16 04:07:38 +04:00
DEBUG ( 0 , ( " send_file_readX: fake_sendfile failed for file %s (%s). \n " ,
fsp - > fsp_name , strerror ( errno ) ) ) ;
exit_server_cleanly ( " send_file_readX: fake_sendfile failed " ) ;
}
2007-08-12 13:16:54 +04:00
TALLOC_FREE ( req - > outbuf ) ;
return ;
2007-05-16 04:07:38 +04:00
} else {
2007-08-12 16:57:56 +04:00
reply_outbuf ( req , 12 , smb_maxcnt ) ;
2002-09-25 19:19:00 +04:00
2007-08-12 16:57:56 +04:00
nread = read_file ( fsp , smb_buf ( req - > outbuf ) , startpos ,
smb_maxcnt ) ;
2007-05-16 04:07:38 +04:00
if ( nread < 0 ) {
2007-08-12 13:16:54 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2007-05-16 04:07:38 +04:00
}
2002-09-25 19:19:00 +04:00
2007-10-11 00:34:30 +04:00
setup_readX_header ( ( char * ) req - > outbuf , nread ) ;
2007-05-16 04:07:38 +04:00
DEBUG ( 3 , ( " send_file_readX fnum=%d max=%d nread=%d \n " ,
fsp - > fnum , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2007-08-12 13:16:54 +04:00
return ;
2007-05-16 04:07:38 +04:00
}
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a read and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-11 14:40:35 +04:00
void reply_read_and_X ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-11 01:33:58 +04:00
files_struct * fsp ;
SMB_OFF_T startpos ;
size_t smb_maxcnt ;
2007-10-19 04:40:25 +04:00
bool big_readX = False ;
2002-09-25 19:19:00 +04:00
#if 0
2007-08-11 14:40:35 +04:00
size_t smb_mincnt = SVAL ( req - > inbuf , smb_vwv6 ) ;
2002-09-25 19:19:00 +04:00
# endif
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
START_PROFILE ( SMBreadX ) ;
1998-03-12 02:20:26 +03:00
2007-08-11 14:40:35 +04:00
if ( ( req - > wct ! = 10 ) & & ( req - > wct ! = 12 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2007-08-11 01:33:58 +04:00
}
2007-08-11 14:40:35 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv2 ) ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv3 ) ;
smb_maxcnt = SVAL ( req - > inbuf , smb_vwv5 ) ;
2002-09-25 19:19:00 +04:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-08-11 14:53:36 +04:00
reply_pipe_read_and_X ( req ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
2007-08-11 14:40:35 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2007-08-11 14:40:35 +04:00
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBreadX ) ;
return ;
}
if ( ! CHECK_READ ( fsp , req - > inbuf ) ) {
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
END_PROFILE ( SMBreadX ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2004-11-24 06:42:01 +03:00
if ( global_client_caps & CAP_LARGE_READX ) {
2007-08-11 15:20:21 +04:00
size_t upper_size = SVAL ( req - > inbuf , smb_vwv7 ) ;
2007-05-16 04:07:38 +04:00
smb_maxcnt | = ( upper_size < < 16 ) ;
if ( upper_size > 1 ) {
/* Can't do this on a chained packet. */
2007-08-11 15:20:21 +04:00
if ( ( CVAL ( req - > inbuf , smb_vwv0 ) ! = 0xFF ) ) {
2007-08-11 14:40:35 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
END_PROFILE ( SMBreadX ) ;
return ;
2007-05-16 04:07:38 +04:00
}
2007-10-11 00:34:30 +04:00
/* We currently don't do this on signed data. */
if ( srv_is_signing_active ( ) ) {
2007-08-11 14:40:35 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
END_PROFILE ( SMBreadX ) ;
return ;
2007-05-16 04:07:38 +04:00
}
2007-05-19 05:27:34 +04:00
/* Is there room in the reply for this data ? */
if ( smb_maxcnt > ( 0xFFFFFF - ( smb_size - 4 + 12 * 2 ) ) ) {
2007-08-11 14:40:35 +04:00
reply_nterror ( req ,
NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBreadX ) ;
return ;
2007-05-19 05:27:34 +04:00
}
2007-05-16 04:07:38 +04:00
big_readX = True ;
2004-11-24 08:24:38 +03:00
}
2004-11-24 06:42:01 +03:00
}
2007-08-11 15:20:21 +04:00
if ( req - > wct = = 12 ) {
1999-12-13 16:27:58 +03:00
# ifdef LARGE_SMB_OFF_T
2002-09-25 19:19:00 +04:00
/*
* This is a large offset ( 64 bit ) read .
*/
2007-08-11 15:20:21 +04:00
startpos | = ( ( ( SMB_OFF_T ) IVAL ( req - > inbuf , smb_vwv10 ) ) < < 32 ) ;
1999-12-13 16:27:58 +03:00
# else /* !LARGE_SMB_OFF_T */
2002-09-25 19:19:00 +04:00
/*
* Ensure we haven ' t been sent a > 32 bit offset .
*/
1999-12-13 16:27:58 +03:00
2007-08-11 15:20:21 +04:00
if ( IVAL ( req - > inbuf , smb_vwv10 ) ! = 0 ) {
2007-08-11 14:40:35 +04:00
DEBUG ( 0 , ( " reply_read_and_X - large offset (%x << 32) "
" used and we don't support 64 bit offsets. \n " ,
2007-08-11 15:20:21 +04:00
( unsigned int ) IVAL ( req - > inbuf , smb_vwv10 ) ) ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
2007-08-11 14:40:35 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
return ;
2002-09-25 19:19:00 +04:00
}
1999-12-13 16:27:58 +03:00
1998-09-11 23:14:27 +04:00
# endif /* LARGE_SMB_OFF_T */
1998-09-11 05:24:30 +04:00
2002-09-25 19:19:00 +04:00
}
1999-12-13 16:27:58 +03:00
2007-08-11 14:40:35 +04:00
if ( is_locked ( fsp , ( uint32 ) req - > smbpid , ( SMB_BIG_UINT ) smb_maxcnt ,
( SMB_BIG_UINT ) startpos , READ_LOCK ) ) {
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
2007-08-11 14:40:35 +04:00
reply_doserror ( req , ERRDOS , ERRlock ) ;
return ;
2002-09-25 19:19:00 +04:00
}
2001-08-27 12:19:43 +04:00
2007-08-11 20:28:10 +04:00
if ( ! big_readX
& & schedule_aio_read_and_X ( conn , req , fsp , startpos , smb_maxcnt ) ) {
2007-08-11 15:20:21 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
}
2007-08-12 13:16:54 +04:00
send_file_readX ( conn , req , fsp , startpos , smb_maxcnt ) ;
2007-08-11 14:40:35 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
2007-08-11 14:26:40 +04:00
}
2007-08-15 05:54:37 +04:00
/****************************************************************************
Error replies to writebraw must have smb_wct = = 1. Fix this up .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void error_to_writebrawerr ( struct smb_request * req )
{
uint8 * old_outbuf = req - > outbuf ;
reply_outbuf ( req , 1 , 0 ) ;
memcpy ( req - > outbuf , old_outbuf , smb_size ) ;
TALLOC_FREE ( old_outbuf ) ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writebraw ( core + or LANMAN1 .0 protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-15 05:54:37 +04:00
void reply_writebraw ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-15 05:54:37 +04:00
int outsize = 0 ;
char * buf = NULL ;
2001-09-04 23:10:30 +04:00
ssize_t nwritten = 0 ;
ssize_t total_written = 0 ;
size_t numtowrite = 0 ;
size_t tcount ;
SMB_OFF_T startpos ;
char * data = NULL ;
2007-10-19 04:40:25 +04:00
bool write_through ;
2007-08-15 05:54:37 +04:00
files_struct * fsp ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2007-08-15 05:54:37 +04:00
2001-09-04 23:10:30 +04:00
START_PROFILE ( SMBwritebraw ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/*
* If we ever reply with an error , it must have the SMB command
* type of SMBwritec , not SMBwriteBraw , as this tells the client
* we ' re finished .
*/
SCVAL ( req - > inbuf , smb_com , SMBwritec ) ;
2003-07-18 04:53:34 +04:00
if ( srv_is_signing_active ( ) ) {
2007-08-15 05:54:37 +04:00
END_PROFILE ( SMBwritebraw ) ;
exit_server_cleanly ( " reply_writebraw: SMB signing is active - "
" raw reads/writes are disallowed. " ) ;
}
if ( req - > wct < 12 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
2003-07-17 04:53:37 +04:00
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2007-08-15 05:54:37 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2007-08-15 05:54:37 +04:00
tcount = IVAL ( req - > inbuf , smb_vwv1 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv3 ) ;
write_through = BITSETW ( req - > inbuf + smb_vwv7 , 0 ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
/* We have to deal with slightly different formats depending
on whether we are using the core + or lanman1 .0 protocol */
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( Protocol < = PROTOCOL_COREPLUS ) {
2007-08-15 05:54:37 +04:00
numtowrite = SVAL ( smb_buf ( req - > inbuf ) , - 2 ) ;
data = smb_buf ( req - > inbuf ) ;
2001-09-04 23:10:30 +04:00
} else {
2007-08-15 05:54:37 +04:00
numtowrite = SVAL ( req - > inbuf , smb_vwv10 ) ;
data = smb_base ( req - > inbuf ) + SVAL ( req - > inbuf , smb_vwv11 ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Ensure we don't write bytes past the end of this packet. */
if ( data + numtowrite > smb_base ( req - > inbuf ) + smb_len ( req - > inbuf ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
if ( is_locked ( fsp , ( uint32 ) req - > smbpid , ( SMB_BIG_UINT ) tcount ,
( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
reply_doserror ( req , ERRDOS , ERRlock ) ;
error_to_writebrawerr ( req ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBwritebraw ) ;
2007-08-15 05:54:37 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
if ( numtowrite > 0 ) {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2007-08-15 05:54:37 +04:00
}
DEBUG ( 3 , ( " reply_writebraw: initial write fnum=%d start=%.0f num=%d "
" wrote=%d sync=%d \n " ,
fsp - > fnum , ( double ) startpos , ( int ) numtowrite ,
( int ) nwritten , ( int ) write_through ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-31 13:25:11 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-15 05:54:37 +04:00
reply_unixerror ( req , ERRHRD , ERRdiskfull ) ;
error_to_writebrawerr ( req ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBwritebraw ) ;
2007-08-15 05:54:37 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
total_written = nwritten ;
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Allocate a buffer of 64k + length. */
buf = TALLOC_ARRAY ( NULL , char , 65540 ) ;
if ( ! buf ) {
reply_doserror ( req , ERRDOS , ERRnomem ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
/* Return a SMBwritebraw message to the redirector to tell
* it to send more bytes */
memcpy ( buf , req - > inbuf , smb_size ) ;
2007-10-11 00:34:30 +04:00
outsize = set_message ( buf ,
2007-08-15 05:54:37 +04:00
Protocol > PROTOCOL_COREPLUS ? 1 : 0 , 0 , True ) ;
SCVAL ( buf , smb_com , SMBwritebraw ) ;
SSVALS ( buf , smb_vwv0 , 0xFFFF ) ;
show_msg ( buf ) ;
if ( ! send_smb ( smbd_server_fd ( ) , buf ) ) {
exit_server_cleanly ( " reply_writebraw: send_smb "
" failed. " ) ;
}
2001-09-04 23:10:30 +04:00
/* Now read the raw data into the buffer and write it */
2007-08-15 05:54:37 +04:00
if ( read_smb_length ( smbd_server_fd ( ) , buf , SMB_SECONDARY_WAIT ) = = - 1 ) {
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/*
* Even though this is not an smb message ,
* smb_len returns the generic length of a packet .
*/
numtowrite = smb_len ( buf ) ;
/* Set up outbuf to return the correct size */
reply_outbuf ( req , 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( numtowrite ! = 0 ) {
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
if ( numtowrite > 0xFFFF ) {
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write "
" raw requested (%u). Terminating \n " ,
2001-09-04 23:10:30 +04:00
( unsigned int ) numtowrite ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( tcount > nwritten + numtowrite ) {
2007-08-15 05:54:37 +04:00
DEBUG ( 3 , ( " reply_writebraw: Client overestimated the "
" write %d %d %d \n " ,
2001-09-04 23:10:30 +04:00
( int ) tcount , ( int ) nwritten , ( int ) numtowrite ) ) ;
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
if ( read_data ( smbd_server_fd ( ) , buf + 4 , numtowrite )
! = numtowrite ) {
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write "
" raw read failed (%s). Terminating \n " ,
2001-09-04 23:10:30 +04:00
strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , buf + 4 , startpos + nwritten , numtowrite ) ;
2006-07-25 04:16:45 +04:00
if ( nwritten = = - 1 ) {
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( buf ) ;
reply_unixerror ( req , ERRHRD , ERRdiskfull ) ;
error_to_writebrawerr ( req ) ;
2006-07-25 04:16:45 +04:00
END_PROFILE ( SMBwritebraw ) ;
2007-08-15 05:54:37 +04:00
return ;
2006-07-25 04:16:45 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-15 05:54:37 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
if ( nwritten > 0 ) {
2001-09-04 23:10:30 +04:00
total_written + = nwritten ;
2007-08-15 05:54:37 +04:00
}
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( buf ) ;
SSVAL ( req - > outbuf , smb_vwv0 , total_written ) ;
2005-07-10 20:37:32 +04:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , write_through ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_writebraw: sync_file for %s returned %s \n " ,
fsp - > fsp_name , nt_errstr ( status ) ) ) ;
2007-08-15 05:54:37 +04:00
reply_nterror ( req , status ) ;
error_to_writebrawerr ( req ) ;
2007-06-15 23:24:04 +04:00
END_PROFILE ( SMBwritebraw ) ;
2007-08-15 05:54:37 +04:00
return ;
2007-06-15 23:24:04 +04:00
}
2001-09-04 23:10:30 +04:00
2007-08-15 05:54:37 +04:00
DEBUG ( 3 , ( " reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
" wrote=%d \n " ,
fsp - > fnum , ( double ) startpos , ( int ) numtowrite ,
( int ) total_written ) ) ;
2001-09-04 23:10:30 +04:00
2007-08-15 05:54:37 +04:00
/* We won't return a status if write through is not selected - this
* follows what WfWg does */
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBwritebraw ) ;
2007-08-15 05:54:37 +04:00
2001-09-04 23:10:30 +04:00
if ( ! write_through & & total_written = = tcount ) {
2002-04-11 06:20:56 +04:00
# if RABBIT_PELLET_FIX
2001-09-04 23:10:30 +04:00
/*
* Fix for " rabbit pellet " mode , trigger an early TCP ack by
2007-08-15 05:54:37 +04:00
* sending a SMBkeepalive . Thanks to DaveCB at Sun for this .
* JRA .
2001-09-04 23:10:30 +04:00
*/
2007-08-15 05:54:37 +04:00
if ( ! send_keepalive ( smbd_server_fd ( ) ) ) {
exit_server_cleanly ( " reply_writebraw: send of "
" keepalive failed " ) ;
}
2002-04-11 06:20:56 +04:00
# endif
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( req - > outbuf ) ;
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writeunlock ( core + ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-15 00:20:51 +04:00
void reply_writeunlock ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-08-27 12:19:43 +04:00
ssize_t nwritten = - 1 ;
size_t numtowrite ;
SMB_OFF_T startpos ;
char * data ;
2003-10-10 01:04:48 +04:00
NTSTATUS status = NT_STATUS_OK ;
2007-08-15 00:20:51 +04:00
files_struct * fsp ;
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2001-08-27 12:19:43 +04:00
2007-08-15 00:20:51 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2007-08-15 00:20:51 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
END_PROFILE ( SMBwriteunlock ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 00:20:51 +04:00
numtowrite = SVAL ( req - > inbuf , smb_vwv1 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv2 ) ;
data = smb_buf ( req - > inbuf ) + 3 ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:20:51 +04:00
if ( numtowrite
& & is_locked ( fsp , ( uint32 ) req - > smbpid , ( SMB_BIG_UINT ) numtowrite ,
( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
reply_doserror ( req , ERRDOS , ERRlock ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
2001-08-07 05:19:32 +04:00
2001-08-27 12:19:43 +04:00
/* The special X/Open SMB protocol handling of
zero length writes is * NOT * done for
this call */
2005-07-08 08:51:27 +04:00
if ( numtowrite = = 0 ) {
2001-08-27 12:19:43 +04:00
nwritten = 0 ;
2005-07-08 08:51:27 +04:00
} else {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2005-07-08 08:51:27 +04:00
}
2001-08-27 12:19:43 +04:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , False /* write through */ ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_writeunlock: sync_file for %s returned %s \n " ,
fsp - > fsp_name , nt_errstr ( status ) ) ) ;
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBwriteunlock ) ;
return ;
2007-06-15 23:24:04 +04:00
}
2001-08-27 12:19:43 +04:00
2007-10-31 04:18:40 +03:00
if ( ( ( nwritten < numtowrite ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
2007-08-15 00:20:51 +04:00
reply_unixerror ( req , ERRHRD , ERRdiskfull ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-07 05:19:32 +04:00
}
2003-10-10 01:04:48 +04:00
if ( numtowrite ) {
2007-05-14 17:01:28 +04:00
status = do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2007-08-15 00:20:51 +04:00
req - > smbpid ,
2006-04-10 19:33:04 +04:00
( SMB_BIG_UINT ) numtowrite ,
( SMB_BIG_UINT ) startpos ,
WINDOWS_LOCK ) ;
2003-10-10 01:04:48 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
2003-10-10 01:04:48 +04:00
END_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
return ;
2003-10-10 01:04:48 +04:00
}
2001-08-27 12:19:43 +04:00
}
2007-08-15 00:20:51 +04:00
reply_outbuf ( req , 1 , 0 ) ;
2001-08-27 12:19:43 +04:00
2007-08-15 00:20:51 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " writeunlock fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
END_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-07 05:19:32 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
2001-08-07 05:19:32 +04:00
/****************************************************************************
Reply to a write .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 22:16:04 +04:00
void reply_write ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-11-25 05:23:22 +03:00
size_t numtowrite ;
ssize_t nwritten = - 1 ;
SMB_OFF_T startpos ;
char * data ;
2007-08-14 22:16:04 +04:00
files_struct * fsp ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2007-08-14 22:16:04 +04:00
2001-11-25 05:23:22 +03:00
START_PROFILE ( SMBwrite ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
if ( req - > wct < 5 ) {
END_PROFILE ( SMBwrite ) ;
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2001-11-25 05:23:22 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-08-14 22:16:04 +04:00
reply_pipe_write ( req ) ;
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
2007-08-15 05:54:37 +04:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2001-11-25 05:23:22 +03:00
}
1999-11-16 01:11:10 +03:00
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2007-08-14 22:16:04 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
2007-06-15 23:24:04 +04:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
numtowrite = SVAL ( req - > inbuf , smb_vwv1 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv2 ) ;
data = smb_buf ( req - > inbuf ) + 3 ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
if ( is_locked ( fsp , ( uint32 ) req - > smbpid , ( SMB_BIG_UINT ) numtowrite ,
( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
reply_doserror ( req , ERRDOS , ERRlock ) ;
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
/*
* X / Open SMB protocol says that if smb_vwv1 is
* zero then the file size should be extended or
* truncated to the size given in smb_vwv [ 2 - 3 ] .
*/
if ( numtowrite = = 0 ) {
/*
* This is actually an allocate call , and set EOF . JRA .
*/
nwritten = vfs_allocate_file_space ( fsp , ( SMB_OFF_T ) startpos ) ;
if ( nwritten < 0 ) {
2007-08-14 22:16:04 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2001-11-25 05:23:22 +03:00
}
nwritten = vfs_set_filelen ( fsp , ( SMB_OFF_T ) startpos ) ;
if ( nwritten < 0 ) {
2007-08-14 22:16:04 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2001-11-25 05:23:22 +03:00
}
} else
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
1996-05-04 11:50:46 +04:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , False ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_write: sync_file for %s returned %s \n " ,
fsp - > fsp_name , nt_errstr ( status ) ) ) ;
2007-08-14 22:16:04 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBwrite ) ;
return ;
2007-06-15 23:24:04 +04:00
}
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
2007-08-14 22:16:04 +04:00
reply_unixerror ( req , ERRHRD , ERRdiskfull ) ;
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
reply_outbuf ( req , 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-14 22:16:04 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
DEBUG ( 3 , ( " write fnum=%d num=%d wrote=%d \n " , fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
1998-08-01 02:39:15 +04:00
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2007-10-31 02:22:24 +03:00
/****************************************************************************
Ensure a buffer is a valid writeX for recvfile purposes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
( 2 * 14 ) + /* word count (including bcc) */ \
1 /* pad byte */ )
2007-11-02 22:21:34 +03:00
bool is_valid_writeX_buffer ( const char * inbuf )
2007-10-31 02:22:24 +03:00
{
size_t numtowrite ;
connection_struct * conn = NULL ;
unsigned int doff = 0 ;
2007-11-02 22:21:34 +03:00
size_t len = smb_len_large ( inbuf ) ;
2007-10-31 02:22:24 +03:00
if ( CVAL ( inbuf , smb_com ) ! = SMBwriteX | |
CVAL ( inbuf , smb_vwv0 ) ! = 0xFF | |
CVAL ( inbuf , smb_wct ) ! = 14 ) {
return false ;
}
conn = conn_find ( SVAL ( inbuf , smb_tid ) ) ;
if ( conn = = NULL ) {
return false ;
}
if ( IS_IPC ( conn ) ) {
return false ;
}
2007-11-02 22:21:34 +03:00
doff = SVAL ( inbuf , smb_vwv11 ) ;
2007-10-31 02:22:24 +03:00
numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
2007-11-02 22:21:34 +03:00
if ( len > doff & & len - doff > 0xFFFF ) {
numtowrite | = ( ( ( size_t ) SVAL ( inbuf , smb_vwv9 ) ) < < 16 ) ;
}
2007-10-31 02:22:24 +03:00
if ( numtowrite = = 0 ) {
return false ;
}
2007-11-02 22:21:34 +03:00
/* Ensure the sizes match up. */
2007-10-31 02:22:24 +03:00
if ( doff < STANDARD_WRITE_AND_X_HEADER_SIZE ) {
/* no pad byte...old smbclient :-( */
return false ;
}
if ( len - doff ! = numtowrite ) {
DEBUG ( 10 , ( " is_valid_writeX_buffer: doff mismatch "
" len = %u, doff = %u, numtowrite = %u \n " ,
( unsigned int ) len ,
( unsigned int ) doff ,
( unsigned int ) numtowrite ) ) ;
return false ;
}
DEBUG ( 10 , ( " is_valid_writeX_buffer: true "
" len = %u, doff = %u, numtowrite = %u \n " ,
( unsigned int ) len ,
( unsigned int ) doff ,
( unsigned int ) numtowrite ) ) ;
return true ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a write and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-07 17:43:02 +04:00
void reply_write_and_X ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-07 17:12:46 +04:00
files_struct * fsp ;
SMB_OFF_T startpos ;
size_t numtowrite ;
2007-10-19 04:40:25 +04:00
bool write_through ;
2007-08-07 17:12:46 +04:00
ssize_t nwritten ;
unsigned int smb_doff ;
unsigned int smblen ;
2002-12-04 02:57:45 +03:00
char * data ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2007-08-07 17:12:46 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBwriteX ) ;
2007-08-08 22:40:26 +04:00
if ( ( req - > wct ! = 12 ) & & ( req - > wct ! = 14 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-07 17:43:02 +04:00
END_PROFILE ( SMBwriteX ) ;
return ;
}
2007-08-08 22:40:26 +04:00
numtowrite = SVAL ( req - > inbuf , smb_vwv10 ) ;
smb_doff = SVAL ( req - > inbuf , smb_vwv11 ) ;
smblen = smb_len ( req - > inbuf ) ;
2007-11-02 08:24:39 +03:00
if ( req - > unread_bytes > 0xFFFF | |
2007-11-02 20:35:10 +03:00
( smblen > smb_doff & &
smblen - smb_doff > 0xFFFF ) ) {
2007-11-02 08:24:39 +03:00
numtowrite | = ( ( ( size_t ) SVAL ( req - > inbuf , smb_vwv9 ) ) < < 16 ) ;
2007-08-08 22:40:26 +04:00
}
2007-10-31 02:22:24 +03:00
if ( req - > unread_bytes ) {
if ( numtowrite ! = req - > unread_bytes ) {
reply_doserror ( req , ERRDOS , ERRbadmem ) ;
END_PROFILE ( SMBwriteX ) ;
return ;
}
} else {
2007-11-02 20:35:10 +03:00
if ( smb_doff > smblen | | smb_doff + numtowrite < numtowrite | |
smb_doff + numtowrite > smblen ) {
2007-10-31 02:22:24 +03:00
reply_doserror ( req , ERRDOS , ERRbadmem ) ;
END_PROFILE ( SMBwriteX ) ;
return ;
}
2007-08-07 17:12:46 +04:00
}
2002-12-04 02:57:45 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-11-02 08:42:21 +03:00
if ( req - > unread_bytes ) {
reply_doserror ( req , ERRDOS , ERRbadmem ) ;
END_PROFILE ( SMBwriteX ) ;
return ;
}
2007-08-08 22:40:26 +04:00
reply_pipe_write_and_X ( req ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
}
2007-08-08 22:40:26 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv2 ) ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv3 ) ;
write_through = BITSETW ( req - > inbuf + smb_vwv7 , 0 ) ;
2007-08-07 17:43:02 +04:00
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBwriteX ) ;
return ;
2002-12-04 02:57:45 +03:00
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2007-08-07 17:43:02 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
2007-08-07 17:14:49 +04:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2007-08-08 23:05:30 +04:00
data = smb_base ( req - > inbuf ) + smb_doff ;
2002-12-04 02:57:45 +03:00
2007-08-08 23:05:30 +04:00
if ( req - > wct = = 14 ) {
1999-12-13 16:27:58 +03:00
# ifdef LARGE_SMB_OFF_T
2002-12-04 02:57:45 +03:00
/*
* This is a large offset ( 64 bit ) write .
*/
2007-08-08 23:05:30 +04:00
startpos | = ( ( ( SMB_OFF_T ) IVAL ( req - > inbuf , smb_vwv12 ) ) < < 32 ) ;
1999-12-13 16:27:58 +03:00
# else /* !LARGE_SMB_OFF_T */
2002-12-04 02:57:45 +03:00
/*
* Ensure we haven ' t been sent a > 32 bit offset .
*/
1999-12-13 16:27:58 +03:00
2007-08-08 23:05:30 +04:00
if ( IVAL ( req - > inbuf , smb_vwv12 ) ! = 0 ) {
2007-08-07 17:43:02 +04:00
DEBUG ( 0 , ( " reply_write_and_X - large offset (%x << 32) "
" used and we don't support 64 bit offsets. \n " ,
2007-10-04 17:13:16 +04:00
( unsigned int ) IVAL ( req - > inbuf , smb_vwv12 ) ) ) ;
2007-08-07 17:43:02 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1999-12-13 16:27:58 +03:00
1998-09-11 23:14:27 +04:00
# endif /* LARGE_SMB_OFF_T */
2002-12-04 02:57:45 +03:00
}
2007-08-08 23:05:30 +04:00
if ( is_locked ( fsp , ( uint32 ) req - > smbpid ,
2007-08-07 17:43:02 +04:00
( SMB_BIG_UINT ) numtowrite ,
( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
reply_doserror ( req , ERRDOS , ERRlock ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
/* X/Open SMB protocol says that, unlike SMBwrite
if the length is zero then NO truncation is
done , just a write of zero . To truncate a file ,
use SMBwrite . */
2005-06-09 22:15:23 +04:00
if ( numtowrite = = 0 ) {
2002-12-04 02:57:45 +03:00
nwritten = 0 ;
2005-06-09 22:15:23 +04:00
} else {
2007-10-31 02:22:24 +03:00
if ( req - > unread_bytes = = 0 & &
schedule_aio_write_and_X ( conn , req , fsp , data ,
startpos , numtowrite ) ) {
2005-06-09 22:15:23 +04:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2005-06-09 22:15:23 +04:00
}
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2005-06-09 22:15:23 +04:00
}
2007-10-31 02:22:24 +03:00
2002-12-04 02:57:45 +03:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
2007-08-07 17:43:02 +04:00
reply_unixerror ( req , ERRHRD , ERRdiskfull ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-08-13 11:20:19 +04:00
reply_outbuf ( req , 6 , 0 ) ;
2007-08-08 23:05:30 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , nwritten ) ;
2007-11-02 08:24:39 +03:00
SSVAL ( req - > outbuf , smb_vwv4 , nwritten > > 16 ) ;
2002-12-04 02:57:45 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-08 23:05:30 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2002-12-04 02:57:45 +03:00
}
DEBUG ( 3 , ( " writeX fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , write_through ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_write_and_X: sync_file for %s returned %s \n " ,
fsp - > fsp_name , nt_errstr ( status ) ) ) ;
2007-08-07 17:43:02 +04:00
reply_nterror ( req , status ) ;
2007-08-07 17:14:49 +04:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2007-06-15 23:24:04 +04:00
}
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2007-08-07 17:43:02 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lseek .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-14 20:04:31 +04:00
void reply_lseek ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
SMB_OFF_T startpos ;
SMB_OFF_T res = - 1 ;
int mode , umode ;
2007-08-14 20:04:31 +04:00
files_struct * fsp ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBlseek ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 20:04:31 +04:00
if ( req - > wct < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlseek ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
return ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
flush_write_cache ( fsp , SEEK_FLUSH ) ;
1999-12-13 16:27:58 +03:00
2007-08-14 20:04:31 +04:00
mode = SVAL ( req - > inbuf , smb_vwv1 ) & 3 ;
2002-12-04 02:57:45 +03:00
/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2007-08-14 20:04:31 +04:00
startpos = ( SMB_OFF_T ) IVALS ( req - > inbuf , smb_vwv2 ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
switch ( mode ) {
case 0 :
umode = SEEK_SET ;
2003-08-15 01:16:06 +04:00
res = startpos ;
2002-12-04 02:57:45 +03:00
break ;
case 1 :
umode = SEEK_CUR ;
2005-07-08 08:51:27 +04:00
res = fsp - > fh - > pos + startpos ;
2002-12-04 02:57:45 +03:00
break ;
case 2 :
umode = SEEK_END ;
break ;
default :
umode = SEEK_SET ;
2003-08-15 01:16:06 +04:00
res = startpos ;
2002-12-04 02:57:45 +03:00
break ;
}
1998-07-31 01:18:57 +04:00
2003-08-15 01:16:06 +04:00
if ( umode = = SEEK_END ) {
2005-07-08 08:51:27 +04:00
if ( ( res = SMB_VFS_LSEEK ( fsp , fsp - > fh - > fd , startpos , umode ) ) = = - 1 ) {
2003-08-15 01:16:06 +04:00
if ( errno = = EINVAL ) {
SMB_OFF_T current_pos = startpos ;
2002-12-04 02:57:45 +03:00
SMB_STRUCT_STAT sbuf ;
1999-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
if ( SMB_VFS_FSTAT ( fsp , fsp - > fh - > fd , & sbuf ) = = - 1 ) {
2007-08-14 20:04:31 +04:00
reply_unixerror ( req , ERRDOS ,
ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
current_pos + = sbuf . st_size ;
2003-08-15 01:16:06 +04:00
if ( current_pos < 0 )
2005-07-08 08:51:27 +04:00
res = SMB_VFS_LSEEK ( fsp , fsp - > fh - > fd , 0 , SEEK_SET ) ;
2002-12-04 02:57:45 +03:00
}
}
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
if ( res = = - 1 ) {
2007-08-14 20:04:31 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
}
1998-10-19 02:06:35 +04:00
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos = res ;
2007-08-14 20:04:31 +04:00
reply_outbuf ( req , 2 , 0 ) ;
SIVAL ( req - > outbuf , smb_vwv0 , res ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d \n " ,
fsp - > fnum , ( double ) startpos , ( double ) res , mode ) ) ;
1998-08-01 02:39:15 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a flush .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-05 00:44:33 +04:00
void reply_flush ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-05 00:44:33 +04:00
uint16 fnum ;
files_struct * fsp ;
2001-08-24 08:56:33 +04:00
START_PROFILE ( SMBflush ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:44:33 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
fnum = SVAL ( req - > inbuf , smb_vwv0 ) ;
fsp = file_fsp ( fnum ) ;
if ( ( fnum ! = 0xFFFF ) & & ! check_fsp ( conn , req , fsp , & current_user ) ) {
return ;
}
2001-08-24 08:56:33 +04:00
if ( ! fsp ) {
file_sync_all ( conn ) ;
} else {
2007-06-15 23:24:04 +04:00
NTSTATUS status = sync_file ( conn , fsp , True ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_flush: sync_file for %s returned %s \n " ,
fsp - > fsp_name , nt_errstr ( status ) ) ) ;
2007-08-05 00:44:33 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBflush ) ;
return ;
2007-06-15 23:24:04 +04:00
}
2001-08-24 08:56:33 +04:00
}
2007-08-05 00:44:33 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2001-08-24 08:56:33 +04:00
DEBUG ( 3 , ( " flush \n " ) ) ;
END_PROFILE ( SMBflush ) ;
2007-08-05 00:44:33 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a exit .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-02 09:50:40 +04:00
void reply_exit ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBexit ) ;
2003-08-19 05:53:45 +04:00
2007-08-02 09:50:40 +04:00
file_close_pid ( req - > smbpid , req - > vuid ) ;
2003-08-19 05:53:45 +04:00
2007-08-02 09:50:40 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " exit \n " ) ) ;
1998-08-01 02:39:15 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBexit ) ;
2007-08-02 09:50:40 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1998-07-18 02:21:24 +04:00
Reply to a close - has to deal with closing a directory opened by NT SMB ' s .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-07-23 13:53:06 +04:00
void reply_close ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-02-07 00:05:34 +03:00
NTSTATUS status = NT_STATUS_OK ;
1998-08-14 21:38:29 +04:00
files_struct * fsp = NULL ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBclose ) ;
1996-05-04 11:50:46 +04:00
2007-07-23 13:53:06 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBclose ) ;
return ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
/* If it's an IPC, pass off to the pipe handler. */
2000-10-06 07:21:49 +04:00
if ( IS_IPC ( conn ) ) {
2007-07-23 13:53:06 +04:00
reply_pipe_close ( conn , req ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1997-10-30 04:05:13 +03:00
2007-07-31 16:05:40 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
1997-10-30 04:05:13 +03:00
1998-08-14 21:38:29 +04:00
/*
1998-08-15 11:27:34 +04:00
* We can only use CHECK_FSP if we know it ' s not a directory .
1998-08-14 21:38:29 +04:00
*/
1998-07-18 02:21:24 +04:00
2003-04-10 02:31:37 +04:00
if ( ! fsp | | ( fsp - > conn ! = conn ) | | ( fsp - > vuid ! = current_user . vuid ) ) {
2007-07-23 13:53:06 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( fsp - > is_directory ) {
1998-08-14 21:38:29 +04:00
/*
2002-03-20 03:46:53 +03:00
* Special case - close NT SMB directory handle .
1998-08-14 21:38:29 +04:00
*/
2006-12-20 01:13:10 +03:00
DEBUG ( 3 , ( " close directory fnum=%d \n " , fsp - > fnum ) ) ;
2007-02-07 00:05:34 +03:00
status = close_file ( fsp , NORMAL_CLOSE ) ;
1998-08-14 21:38:29 +04:00
} else {
/*
* Close ordinary file .
*/
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " close fd=%d fnum=%d (numopen=%d) \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , fsp - > fnum ,
1998-08-14 21:38:29 +04:00
conn - > num_files_open ) ) ;
1999-12-13 16:27:58 +03:00
2005-03-10 04:30:14 +03:00
/*
* Take care of any time sent in the close .
*/
2007-07-23 13:53:06 +04:00
fsp_set_pending_modtime ( fsp , convert_time_t_to_timespec (
srv_make_unix_date3 (
req - > inbuf + smb_vwv1 ) ) ) ;
2005-03-10 04:30:14 +03:00
1999-12-13 16:27:58 +03:00
/*
* close_file ( ) returns the unix errno if an error
* was detected on close - normally this is due to
* a disk full error . If not then it was probably an I / O error .
*/
2007-02-07 00:05:34 +03:00
status = close_file ( fsp , NORMAL_CLOSE ) ;
1998-08-14 21:38:29 +04:00
}
1996-06-04 10:42:03 +04:00
2007-07-23 13:53:06 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
2007-07-23 13:53:06 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writeclose ( Core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-14 23:29:02 +04:00
void reply_writeclose ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
1998-09-11 05:24:30 +04:00
size_t numtowrite ;
ssize_t nwritten = - 1 ;
2007-02-07 00:05:34 +03:00
NTSTATUS close_status = NT_STATUS_OK ;
1998-09-11 05:24:30 +04:00
SMB_OFF_T startpos ;
1998-08-14 21:38:29 +04:00
char * data ;
2007-03-06 02:40:03 +03:00
struct timespec mtime ;
2007-08-14 23:29:02 +04:00
files_struct * fsp ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBwriteclose ) ;
1998-08-14 21:38:29 +04:00
2007-08-14 23:29:02 +04:00
if ( req - > wct < 6 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteclose ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2007-08-14 23:29:02 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
END_PROFILE ( SMBwriteclose ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-08-14 21:38:29 +04:00
2007-08-14 23:29:02 +04:00
numtowrite = SVAL ( req - > inbuf , smb_vwv1 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > inbuf , smb_vwv2 ) ;
mtime = convert_time_t_to_timespec ( srv_make_unix_date3 (
req - > inbuf + smb_vwv4 ) ) ;
data = smb_buf ( req - > inbuf ) + 1 ;
1998-08-14 21:38:29 +04:00
2007-08-14 23:29:02 +04:00
if ( numtowrite
& & is_locked ( fsp , ( uint32 ) req - > smbpid , ( SMB_BIG_UINT ) numtowrite ,
( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
reply_doserror ( req , ERRDOS , ERRlock ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2007-08-14 23:29:02 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
1996-05-04 11:50:46 +04:00
2007-03-06 02:40:03 +03:00
set_filetime ( conn , fsp - > fsp_name , mtime ) ;
1996-05-04 11:50:46 +04:00
2003-10-10 01:04:48 +04:00
/*
* More insanity . W2K only closes the file if writelen > 0.
* JRA .
*/
if ( numtowrite ) {
DEBUG ( 3 , ( " reply_writeclose: zero length write doesn't close file %s \n " ,
fsp - > fsp_name ) ) ;
2007-02-07 00:05:34 +03:00
close_status = close_file ( fsp , NORMAL_CLOSE ) ;
2003-10-10 01:04:48 +04:00
}
1996-06-04 10:42:03 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " writeclose fnum=%d num=%d wrote=%d (numopen=%d) \n " ,
1999-12-13 16:27:58 +03:00
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ,
1998-08-14 21:38:29 +04:00
conn - > num_files_open ) ) ;
1996-05-04 11:50:46 +04:00
2003-01-09 02:49:21 +03:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
2007-08-14 23:29:02 +04:00
reply_doserror ( req , ERRHRD , ERRdiskfull ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2007-08-14 23:29:02 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1999-12-13 16:27:58 +03:00
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( close_status ) ) {
2007-08-14 23:29:02 +04:00
reply_nterror ( req , close_status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2007-08-14 23:29:02 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
2007-08-14 23:29:02 +04:00
reply_outbuf ( req , 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 23:29:02 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2007-08-14 23:29:02 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lock .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 22:52:58 +04:00
void reply_lock ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2000-04-11 23:44:54 +04:00
SMB_BIG_UINT count , offset ;
2001-08-27 12:19:43 +04:00
NTSTATUS status ;
2007-08-14 22:52:58 +04:00
files_struct * fsp ;
2006-07-18 05:05:51 +04:00
struct byte_range_lock * br_lck = NULL ;
2003-10-09 05:46:01 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBlock ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:52:58 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlock ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBlock ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2000-11-16 03:59:18 +03:00
release_level_2_oplocks_on_change ( fsp ) ;
2007-08-14 22:52:58 +04:00
count = ( SMB_BIG_UINT ) IVAL ( req - > inbuf , smb_vwv1 ) ;
offset = ( SMB_BIG_UINT ) IVAL ( req - > inbuf , smb_vwv3 ) ;
1996-05-04 11:50:46 +04:00
1998-09-11 05:24:30 +04:00
DEBUG ( 3 , ( " lock fd=%d fnum=%d offset=%.0f count=%.0f \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , fsp - > fnum , ( double ) offset , ( double ) count ) ) ;
1996-05-04 11:50:46 +04:00
2007-05-14 17:01:28 +04:00
br_lck = do_lock ( smbd_messaging_context ( ) ,
fsp ,
2007-08-14 22:52:58 +04:00
req - > smbpid ,
2006-07-18 01:09:02 +04:00
count ,
offset ,
WRITE_LOCK ,
WINDOWS_LOCK ,
2006-07-18 05:05:51 +04:00
False , /* Non-blocking lock. */
2007-05-20 00:57:12 +04:00
& status ,
NULL ) ;
2006-07-18 05:05:51 +04:00
TALLOC_FREE ( br_lck ) ;
2006-07-18 01:09:02 +04:00
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-14 22:52:58 +04:00
reply_nterror ( req , status ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlock ) ;
2007-08-14 22:52:58 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1998-08-01 02:39:15 +04:00
2007-08-14 22:52:58 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlock ) ;
2007-08-14 22:52:58 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a unlock .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 23:09:37 +04:00
void reply_unlock ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-08-27 12:19:43 +04:00
SMB_BIG_UINT count , offset ;
NTSTATUS status ;
2007-08-14 23:09:37 +04:00
files_struct * fsp ;
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBunlock ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 23:09:37 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBunlock ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBunlock ) ;
return ;
}
2001-08-27 12:19:43 +04:00
2007-08-14 23:09:37 +04:00
count = ( SMB_BIG_UINT ) IVAL ( req - > inbuf , smb_vwv1 ) ;
offset = ( SMB_BIG_UINT ) IVAL ( req - > inbuf , smb_vwv3 ) ;
2001-08-27 12:19:43 +04:00
2007-05-14 17:01:28 +04:00
status = do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2007-08-14 23:09:37 +04:00
req - > smbpid ,
2006-04-10 19:33:04 +04:00
count ,
offset ,
WINDOWS_LOCK ) ;
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-14 23:09:37 +04:00
reply_nterror ( req , status ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
2007-08-14 23:09:37 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " unlock fd=%d fnum=%d offset=%.0f count=%.0f \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , fsp - > fnum , ( double ) offset , ( double ) count ) ) ;
2007-08-14 23:09:37 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
2007-08-14 23:09:37 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a tdis .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-07-30 14:20:52 +04:00
void reply_tdis ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBtdis ) ;
1996-10-26 00:30:22 +04:00
1998-08-14 21:38:29 +04:00
if ( ! conn ) {
DEBUG ( 4 , ( " Invalid connection in tdis \n " ) ) ;
2007-07-30 14:20:52 +04:00
reply_doserror ( req , ERRSRV , ERRinvnid ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtdis ) ;
2007-07-30 14:20:52 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-07-03 05:58:27 +04:00
1998-08-14 21:38:29 +04:00
conn - > used = False ;
1996-05-04 11:50:46 +04:00
2007-07-30 14:20:52 +04:00
close_cnum ( conn , req - > vuid ) ;
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtdis ) ;
2007-07-30 14:20:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a echo .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-05 00:08:35 +04:00
void reply_echo ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-05 00:08:35 +04:00
int smb_reverb ;
1998-08-14 21:38:29 +04:00
int seq_num ;
2007-08-05 00:08:35 +04:00
unsigned int data_len = smb_buflen ( req - > inbuf ) ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBecho ) ;
2000-04-27 20:53:31 +04:00
2007-08-05 00:08:35 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBecho ) ;
return ;
}
2003-10-16 22:17:44 +04:00
if ( data_len > BUFFER_SIZE ) {
DEBUG ( 0 , ( " reply_echo: data_len too large. \n " ) ) ;
2007-08-05 00:08:35 +04:00
reply_nterror ( req , NT_STATUS_INSUFFICIENT_RESOURCES ) ;
2003-10-16 22:17:44 +04:00
END_PROFILE ( SMBecho ) ;
2007-08-05 00:08:35 +04:00
return ;
2003-10-16 22:17:44 +04:00
}
2000-04-27 20:53:31 +04:00
2007-08-05 00:08:35 +04:00
smb_reverb = SVAL ( req - > inbuf , smb_vwv0 ) ;
reply_outbuf ( req , 1 , data_len ) ;
1998-08-14 21:38:29 +04:00
/* copy any incoming data back out */
2007-08-05 00:08:35 +04:00
if ( data_len > 0 ) {
memcpy ( smb_buf ( req - > outbuf ) , smb_buf ( req - > inbuf ) , data_len ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( smb_reverb > 100 ) {
DEBUG ( 0 , ( " large reverb (%d)?? Setting to 100 \n " , smb_reverb ) ) ;
smb_reverb = 100 ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
for ( seq_num = 1 ; seq_num < = smb_reverb ; seq_num + + ) {
2007-08-05 00:08:35 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , seq_num ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:08:35 +04:00
show_msg ( ( char * ) req - > outbuf ) ;
if ( ! send_smb ( smbd_server_fd ( ) , ( char * ) req - > outbuf ) )
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " reply_echo: send_smb failed. " ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " echo %d times \n " , smb_reverb ) ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:08:35 +04:00
TALLOC_FREE ( req - > outbuf ) ;
1999-12-13 16:27:58 +03:00
smb_echo_count + + ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBecho ) ;
2007-08-05 00:08:35 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printopen .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 23:45:24 +04:00
void reply_printopen ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
files_struct * fsp ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplopen ) ;
return ;
}
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2007-08-14 23:45:24 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
/* Open for exclusive use, write only. */
2006-07-11 22:01:26 +04:00
status = print_fsp_open ( conn , NULL , & fsp ) ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 23:45:24 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
1996-05-04 11:50:46 +04:00
2000-04-10 17:05:23 +04:00
DEBUG ( 3 , ( " openprint fd=%d fnum=%d \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , fsp - > fnum ) ) ;
1998-08-01 02:39:15 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printclose .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-12-04 02:57:45 +03:00
2007-08-14 23:45:24 +04:00
void reply_printclose ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-14 23:45:24 +04:00
files_struct * fsp ;
2007-02-07 00:05:34 +03:00
NTSTATUS status ;
2007-08-14 23:45:24 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplclose ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 23:45:24 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplclose ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBsplclose ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , NT_STATUS_DOS ( ERRSRV , ERRerror ) ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " printclose fd=%d fnum=%d \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , fsp - > fnum ) ) ;
1996-05-04 11:50:46 +04:00
2007-02-07 00:05:34 +03:00
status = close_file ( fsp , NORMAL_CLOSE ) ;
1999-12-13 16:27:58 +03:00
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
1998-04-16 23:23:10 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printqueue .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 23:45:24 +04:00
void reply_printqueue ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-14 23:45:24 +04:00
int max_count ;
int start_index ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplretq ) ;
1998-08-14 21:38:29 +04:00
2007-08-14 23:45:24 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplretq ) ;
return ;
}
max_count = SVAL ( req - > inbuf , smb_vwv0 ) ;
start_index = SVAL ( req - > inbuf , smb_vwv1 ) ;
1998-08-14 21:38:29 +04:00
/* we used to allow the client to get the cnum wrong, but that
is really quite gross and only worked when there was only
one printer - I think we should now only accept it if they
get it right ( tridge ) */
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2007-08-14 23:45:24 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplretq ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1998-08-14 21:38:29 +04:00
2007-08-14 23:45:24 +04:00
reply_outbuf ( req , 2 , 3 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " printqueue start_index=%d max_count=%d \n " ,
start_index , max_count ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
{
print_queue_struct * queue = NULL ;
2001-12-29 12:52:24 +03:00
print_status_struct status ;
int count = print_queue_status ( SNUM ( conn ) , & queue , & status ) ;
1998-08-14 21:38:29 +04:00
int num_to_get = ABS ( max_count ) ;
int first = ( max_count > 0 ? start_index : start_index + max_count + 1 ) ;
int i ;
if ( first > = count )
num_to_get = 0 ;
else
num_to_get = MIN ( num_to_get , count - first ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
for ( i = first ; i < first + num_to_get ; i + + ) {
2007-08-14 23:45:24 +04:00
char blob [ 28 ] ;
char * p = blob ;
2005-11-05 07:21:55 +03:00
srv_put_dos_date2 ( p , 0 , queue [ i ] . time ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( p , 4 , ( queue [ i ] . status = = LPQ_PRINTING ? 2 : 3 ) ) ;
2000-04-16 10:22:31 +04:00
SSVAL ( p , 5 , queue [ i ] . job ) ;
1998-08-14 21:38:29 +04:00
SIVAL ( p , 7 , queue [ i ] . size ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( p , 11 , 0 ) ;
2007-08-14 23:45:24 +04:00
srvstr_push ( blob , req - > flags2 , p + 12 ,
2007-08-02 21:37:38 +04:00
queue [ i ] . fs_user , 16 , STR_ASCII ) ;
2007-08-14 23:45:24 +04:00
if ( message_push_blob (
& req - > outbuf ,
data_blob_const (
blob , sizeof ( blob ) ) ) = = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsplretq ) ;
return ;
}
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( count > 0 ) {
2007-08-14 23:45:24 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , count ) ;
SSVAL ( req - > outbuf , smb_vwv1 ,
( max_count > 0 ? first + count : first - 1 ) ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , 28 * count ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-17 15:25:41 +04:00
SAFE_FREE ( queue ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " %d entries returned in queue \n " , count ) ) ;
}
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplretq ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printwrite .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-08-14 23:45:24 +04:00
void reply_printwrite ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int numtowrite ;
char * data ;
2007-08-14 23:45:24 +04:00
files_struct * fsp ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplwr ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2007-08-14 23:45:24 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
END_PROFILE ( SMBsplwr ) ;
return ;
}
2002-12-04 02:57:45 +03:00
if ( ! CAN_PRINT ( conn ) ) {
2007-08-14 23:45:24 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2007-08-14 23:45:24 +04:00
reply_doserror ( req , ERRDOS , ERRbadaccess ) ;
END_PROFILE ( SMBsplwr ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 23:45:24 +04:00
numtowrite = SVAL ( smb_buf ( req - > inbuf ) , 1 ) ;
if ( smb_buflen ( req - > inbuf ) < numtowrite + 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplwr ) ;
return ;
}
data = smb_buf ( req - > inbuf ) + 3 ;
2007-10-31 02:22:24 +03:00
if ( write_file ( req , fsp , data , - 1 , numtowrite ) ! = numtowrite ) {
2007-08-14 23:45:24 +04:00
reply_unixerror ( req , ERRHRD , ERRdiskfull ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2000-10-06 07:21:49 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " printwrite fnum=%d num=%d \n " , fsp - > fnum , numtowrite ) ) ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2000-07-25 17:15:16 +04:00
/****************************************************************************
2001-08-31 02:20:02 +04:00
Reply to a mkdir .
2000-07-25 17:15:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-31 02:20:02 +04:00
2007-07-30 15:35:39 +04:00
void reply_mkdir ( connection_struct * conn , struct smb_request * req )
2000-07-25 17:15:16 +04:00
{
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2005-03-15 04:19:58 +03:00
SMB_STRUCT_STAT sbuf ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-03-15 04:19:58 +03:00
2001-08-31 02:20:02 +04:00
START_PROFILE ( SMBmkdir ) ;
2007-09-11 22:31:29 +04:00
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & directory ,
smb_buf ( req - > inbuf ) + 1 , 0 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBmkdir ) ;
2007-07-30 15:35:39 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2000-07-25 17:15:16 +04:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
2007-07-30 15:35:39 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
directory ,
2007-09-11 22:31:29 +04:00
& directory ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-30 15:35:39 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBmkdir ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBmkdir ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2002-08-17 19:27:10 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , directory , False , & directory , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
2007-01-06 21:59:02 +03:00
END_PROFILE ( SMBmkdir ) ;
2007-07-30 15:35:39 +04:00
return ;
2007-01-06 21:59:02 +03:00
}
2005-03-15 04:19:58 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBmkdir ) ;
2007-07-30 15:35:39 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-08-16 21:42:34 +04:00
2006-12-24 14:45:55 +03:00
status = create_directory ( conn , directory ) ;
2006-12-19 19:36:54 +03:00
2006-12-29 00:34:31 +03:00
DEBUG ( 5 , ( " create_directory returned %s \n " , nt_errstr ( status ) ) ) ;
2005-04-02 03:11:28 +04:00
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
2006-12-24 14:13:32 +03:00
if ( ! use_nt_status ( )
& & NT_STATUS_EQUAL ( status ,
NT_STATUS_OBJECT_NAME_COLLISION ) ) {
2006-07-11 22:01:26 +04:00
/*
* Yes , in the DOS error code case we get a
* ERRDOS : ERRnoaccess here . See BASE - SAMBA3ERROR
* samba4 torture test .
*/
status = NT_STATUS_DOS ( ERRDOS , ERRnoaccess ) ;
}
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBmkdir ) ;
2007-07-30 15:35:39 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2001-09-04 11:13:01 +04:00
2007-07-30 15:35:39 +04:00
reply_outbuf ( req , 0 , 0 ) ;
1998-08-01 02:39:15 +04:00
2007-07-30 15:35:39 +04:00
DEBUG ( 3 , ( " mkdir %s \n " , directory ) ) ;
1998-08-01 02:39:15 +04:00
2001-08-31 02:20:02 +04:00
END_PROFILE ( SMBmkdir ) ;
2007-07-30 15:35:39 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
1997-09-17 05:29:53 +04:00
/****************************************************************************
2001-08-31 02:20:02 +04:00
Static function used by reply_rmdir to delete an entire directory
2007-01-05 20:42:54 +03:00
tree recursively . Return True on ok , False on fail .
1997-09-17 05:29:53 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-10-19 04:40:25 +04:00
static bool recursive_rmdir ( TALLOC_CTX * ctx ,
2007-09-13 01:48:20 +04:00
connection_struct * conn ,
char * directory )
1997-09-17 05:29:53 +04:00
{
2003-03-18 01:56:13 +03:00
const char * dname = NULL ;
2007-10-19 04:40:25 +04:00
bool ret = True ;
2005-01-29 00:01:58 +03:00
long offset = 0 ;
2005-06-25 07:03:44 +04:00
struct smb_Dir * dir_hnd = OpenDir ( conn , directory , NULL , 0 ) ;
1997-09-17 05:29:53 +04:00
2005-02-01 03:28:20 +03:00
if ( dir_hnd = = NULL )
2007-01-05 20:42:54 +03:00
return False ;
1997-09-17 05:29:53 +04:00
2005-02-01 03:28:20 +03:00
while ( ( dname = ReadDirName ( dir_hnd , & offset ) ) ) {
2007-09-13 01:48:20 +04:00
char * fullname = NULL ;
2001-08-31 02:20:02 +04:00
SMB_STRUCT_STAT st ;
1997-09-17 05:29:53 +04:00
2007-09-13 01:48:20 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
2001-08-31 02:20:02 +04:00
continue ;
2007-09-13 01:48:20 +04:00
}
1997-09-17 05:29:53 +04:00
2007-09-13 01:48:20 +04:00
if ( ! is_visible_file ( conn , directory , dname , & st , False ) ) {
2005-02-01 21:33:50 +03:00
continue ;
2007-09-13 01:48:20 +04:00
}
2005-02-01 21:33:50 +03:00
2001-08-31 02:20:02 +04:00
/* Construct the full name. */
2007-09-13 01:48:20 +04:00
fullname = talloc_asprintf ( ctx ,
" %s/%s " ,
directory ,
dname ) ;
if ( ! fullname ) {
2001-08-31 02:20:02 +04:00
errno = ENOMEM ;
2007-01-05 20:42:54 +03:00
ret = False ;
2001-08-31 02:20:02 +04:00
break ;
}
1997-09-17 05:29:53 +04:00
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_LSTAT ( conn , fullname , & st ) ! = 0 ) {
2007-01-05 20:42:54 +03:00
ret = False ;
2001-08-31 02:20:02 +04:00
break ;
}
if ( st . st_mode & S_IFDIR ) {
2007-09-13 01:48:20 +04:00
if ( ! recursive_rmdir ( ctx , conn , fullname ) ) {
2007-01-05 20:42:54 +03:00
ret = False ;
2001-08-31 02:20:02 +04:00
break ;
}
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_RMDIR ( conn , fullname ) ! = 0 ) {
2007-01-05 20:42:54 +03:00
ret = False ;
2001-08-31 02:20:02 +04:00
break ;
}
2003-05-14 14:59:01 +04:00
} else if ( SMB_VFS_UNLINK ( conn , fullname ) ! = 0 ) {
2007-01-05 20:42:54 +03:00
ret = False ;
2001-08-31 02:20:02 +04:00
break ;
}
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( fullname ) ;
2001-08-31 02:20:02 +04:00
}
2005-02-01 03:28:20 +03:00
CloseDir ( dir_hnd ) ;
2001-08-31 02:20:02 +04:00
return ret ;
1997-09-17 05:29:53 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
The internals of the rmdir code - called elsewhere .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-13 01:48:20 +04:00
NTSTATUS rmdir_internals ( TALLOC_CTX * ctx ,
connection_struct * conn ,
const char * directory )
1999-12-13 16:27:58 +03:00
{
2007-01-16 23:32:39 +03:00
int ret ;
2005-02-01 21:33:50 +03:00
SMB_STRUCT_STAT st ;
2001-08-31 02:20:02 +04:00
2007-04-24 16:56:23 +04:00
/* Might be a symlink. */
if ( SMB_VFS_LSTAT ( conn , directory , & st ) ! = 0 ) {
return map_nt_error_from_unix ( errno ) ;
}
if ( S_ISLNK ( st . st_mode ) ) {
/* Is what it points to a directory ? */
if ( SMB_VFS_STAT ( conn , directory , & st ) ! = 0 ) {
return map_nt_error_from_unix ( errno ) ;
}
if ( ! ( S_ISDIR ( st . st_mode ) ) ) {
return NT_STATUS_NOT_A_DIRECTORY ;
}
ret = SMB_VFS_UNLINK ( conn , directory ) ;
} else {
ret = SMB_VFS_RMDIR ( conn , directory ) ;
}
2007-01-16 23:32:39 +03:00
if ( ret = = 0 ) {
2007-01-31 17:14:57 +03:00
notify_fname ( conn , NOTIFY_ACTION_REMOVED ,
FILE_NOTIFY_CHANGE_DIR_NAME ,
directory ) ;
2007-02-07 00:05:34 +03:00
return NT_STATUS_OK ;
2007-01-16 23:32:39 +03:00
}
if ( ( ( errno = = ENOTEMPTY ) | | ( errno = = EEXIST ) ) & & lp_veto_files ( SNUM ( conn ) ) ) {
2007-09-13 01:48:20 +04:00
/*
2001-08-31 02:20:02 +04:00
* Check to see if the only thing in this directory are
* vetoed files / directories . If so then delete them and
* retry . If we fail to delete any of them ( and we * don ' t *
* do a recursive delete ) then fail the rmdir .
*/
2003-03-18 01:56:13 +03:00
const char * dname ;
2007-01-05 20:42:54 +03:00
long dirpos = 0 ;
2005-06-25 07:03:44 +04:00
struct smb_Dir * dir_hnd = OpenDir ( conn , directory , NULL , 0 ) ;
1999-12-13 16:27:58 +03:00
2007-01-05 20:42:54 +03:00
if ( dir_hnd = = NULL ) {
errno = ENOTEMPTY ;
goto err ;
}
while ( ( dname = ReadDirName ( dir_hnd , & dirpos ) ) ) {
if ( ( strcmp ( dname , " . " ) = = 0 ) | | ( strcmp ( dname , " .. " ) = = 0 ) )
continue ;
if ( ! is_visible_file ( conn , directory , dname , & st , False ) )
continue ;
if ( ! IS_VETO_PATH ( conn , dname ) ) {
CloseDir ( dir_hnd ) ;
errno = ENOTEMPTY ;
goto err ;
2001-08-31 02:20:02 +04:00
}
2007-01-05 20:42:54 +03:00
}
1999-12-13 16:27:58 +03:00
2007-01-05 20:42:54 +03:00
/* We only have veto files/directories. Recursive delete. */
1999-12-13 16:27:58 +03:00
2007-01-05 20:42:54 +03:00
RewindDir ( dir_hnd , & dirpos ) ;
while ( ( dname = ReadDirName ( dir_hnd , & dirpos ) ) ) {
2007-09-13 01:48:20 +04:00
char * fullname = NULL ;
1999-12-13 16:27:58 +03:00
2007-09-13 01:48:20 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
2007-01-05 20:42:54 +03:00
continue ;
2007-09-13 01:48:20 +04:00
}
if ( ! is_visible_file ( conn , directory , dname , & st , False ) ) {
2007-01-05 20:42:54 +03:00
continue ;
2007-09-13 01:48:20 +04:00
}
2001-08-31 02:20:02 +04:00
2007-09-13 01:48:20 +04:00
fullname = talloc_asprintf ( ctx ,
" %s/%s " ,
directory ,
dname ) ;
if ( ! fullname ) {
2007-01-05 20:42:54 +03:00
errno = ENOMEM ;
break ;
}
2007-09-13 01:48:20 +04:00
if ( SMB_VFS_LSTAT ( conn , fullname , & st ) ! = 0 ) {
2007-01-05 20:42:54 +03:00
break ;
2007-09-13 01:48:20 +04:00
}
2007-01-05 20:42:54 +03:00
if ( st . st_mode & S_IFDIR ) {
if ( lp_recursive_veto_delete ( SNUM ( conn ) ) ) {
2007-09-13 01:48:20 +04:00
if ( ! recursive_rmdir ( ctx , conn , fullname ) )
2001-08-31 02:20:02 +04:00
break ;
}
2007-09-13 01:48:20 +04:00
if ( SMB_VFS_RMDIR ( conn , fullname ) ! = 0 ) {
2007-01-05 20:42:54 +03:00
break ;
2007-09-13 01:48:20 +04:00
}
} else if ( SMB_VFS_UNLINK ( conn , fullname ) ! = 0 ) {
2007-01-05 20:42:54 +03:00
break ;
2007-09-13 01:48:20 +04:00
}
TALLOC_FREE ( fullname ) ;
2001-08-31 02:20:02 +04:00
}
2007-01-05 20:42:54 +03:00
CloseDir ( dir_hnd ) ;
/* Retry the rmdir */
2007-01-16 23:32:39 +03:00
ret = SMB_VFS_RMDIR ( conn , directory ) ;
2001-08-31 02:20:02 +04:00
}
2007-01-05 20:42:54 +03:00
err :
2007-01-16 23:32:39 +03:00
if ( ret ! = 0 ) {
2006-12-29 00:50:31 +03:00
DEBUG ( 3 , ( " rmdir_internals: couldn't remove directory %s : "
" %s \n " , directory , strerror ( errno ) ) ) ;
2007-02-07 00:05:34 +03:00
return map_nt_error_from_unix ( errno ) ;
2006-12-29 00:50:31 +03:00
}
2007-01-31 17:14:57 +03:00
notify_fname ( conn , NOTIFY_ACTION_REMOVED ,
FILE_NOTIFY_CHANGE_DIR_NAME ,
directory ) ;
2007-01-17 19:23:45 +03:00
2007-02-07 00:05:34 +03:00
return NT_STATUS_OK ;
1999-12-13 16:27:58 +03:00
}
/****************************************************************************
Reply to a rmdir .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-07-30 18:07:29 +04:00
void reply_rmdir ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2002-12-04 02:57:45 +03:00
SMB_STRUCT_STAT sbuf ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBrmdir ) ;
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & directory ,
smb_buf ( req - > inbuf ) + 1 , 0 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBrmdir ) ;
2007-07-30 18:07:29 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
2007-07-30 18:07:29 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
directory ,
2007-09-11 22:31:29 +04:00
& directory ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-30 18:07:29 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBrmdir ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBrmdir ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2002-12-04 02:57:45 +03:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , directory , False , & directory ,
2007-09-08 00:57:01 +04:00
NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBrmdir ) ;
2007-07-30 18:07:29 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
2007-09-11 22:31:29 +04:00
2007-01-17 05:09:37 +03:00
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
2007-01-16 23:49:51 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-07-30 18:07:29 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-01-16 23:49:51 +03:00
2007-07-30 18:07:29 +04:00
dptr_closepath ( directory , req - > smbpid ) ;
2007-09-13 01:48:20 +04:00
status = rmdir_internals ( ctx , conn , directory ) ;
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-07-30 18:07:29 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-09-13 01:48:20 +04:00
2007-07-30 18:07:29 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2007-09-13 01:48:20 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " rmdir %s \n " , directory ) ) ;
2007-09-13 01:48:20 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-07-30 18:07:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2002-09-25 19:19:00 +04:00
Resolve wildcards in a filename rename .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-10-19 04:40:25 +04:00
static bool resolve_wildcards ( TALLOC_CTX * ctx ,
2007-09-08 00:57:01 +04:00
const char * name1 ,
const char * name2 ,
char * * pp_newname )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * name2_copy = NULL ;
char * root1 = NULL ;
char * root2 = NULL ;
char * ext1 = NULL ;
char * ext2 = NULL ;
2003-04-12 03:48:24 +04:00
char * p , * p2 , * pname1 , * pname2 ;
2007-09-08 00:57:01 +04:00
name2_copy = talloc_strdup ( ctx , name2 ) ;
if ( ! name2_copy ) {
return False ;
}
2003-04-12 03:48:24 +04:00
pname1 = strrchr_m ( name1 , ' / ' ) ;
2007-09-08 00:57:01 +04:00
pname2 = strrchr_m ( name2_copy , ' / ' ) ;
2002-12-04 02:57:45 +03:00
2007-09-08 00:57:01 +04:00
if ( ! pname1 | | ! pname2 ) {
return False ;
}
2002-12-04 02:57:45 +03:00
2007-09-08 00:57:01 +04:00
/* Truncate the copy of name2 at the last '/' */
* pname2 = ' \0 ' ;
/* Now go past the '/' */
pname1 + + ;
pname2 + + ;
root1 = talloc_strdup ( ctx , pname1 ) ;
root2 = talloc_strdup ( ctx , pname2 ) ;
if ( ! root1 | | ! root2 ) {
return False ;
}
2002-12-04 02:57:45 +03:00
p = strrchr_m ( root1 , ' . ' ) ;
if ( p ) {
* p = 0 ;
2007-09-08 00:57:01 +04:00
ext1 = talloc_strdup ( ctx , p + 1 ) ;
2002-12-04 02:57:45 +03:00
} else {
2007-09-08 00:57:01 +04:00
ext1 = talloc_strdup ( ctx , " " ) ;
2002-12-04 02:57:45 +03:00
}
p = strrchr_m ( root2 , ' . ' ) ;
if ( p ) {
* p = 0 ;
2007-09-08 00:57:01 +04:00
ext2 = talloc_strdup ( ctx , p + 1 ) ;
2002-12-04 02:57:45 +03:00
} else {
2007-09-08 00:57:01 +04:00
ext2 = talloc_strdup ( ctx , " " ) ;
}
if ( ! ext1 | | ! ext2 ) {
return False ;
2002-12-04 02:57:45 +03:00
}
p = root1 ;
p2 = root2 ;
while ( * p2 ) {
if ( * p2 = = ' ? ' ) {
2007-09-08 00:57:01 +04:00
/* Hmmm. Should this be mb-aware ? */
2002-12-04 02:57:45 +03:00
* p2 = * p ;
p2 + + ;
2004-04-03 05:21:13 +04:00
} else if ( * p2 = = ' * ' ) {
2007-09-08 00:57:01 +04:00
* p2 = ' \0 ' ;
root2 = talloc_asprintf ( ctx , " %s%s " ,
root2 ,
p ) ;
if ( ! root2 ) {
return False ;
}
2004-04-03 05:21:13 +04:00
break ;
2002-12-04 02:57:45 +03:00
} else {
p2 + + ;
}
2007-09-08 00:57:01 +04:00
if ( * p ) {
2002-12-04 02:57:45 +03:00
p + + ;
2007-09-08 00:57:01 +04:00
}
2002-12-04 02:57:45 +03:00
}
p = ext1 ;
p2 = ext2 ;
while ( * p2 ) {
if ( * p2 = = ' ? ' ) {
2007-09-08 00:57:01 +04:00
/* Hmmm. Should this be mb-aware ? */
2002-12-04 02:57:45 +03:00
* p2 = * p ;
p2 + + ;
2004-04-03 05:21:13 +04:00
} else if ( * p2 = = ' * ' ) {
2007-09-08 00:57:01 +04:00
* p2 = ' \0 ' ;
ext2 = talloc_asprintf ( ctx , " %s%s " ,
ext2 ,
p ) ;
if ( ! ext2 ) {
return False ;
}
2004-04-03 05:21:13 +04:00
break ;
2002-12-04 02:57:45 +03:00
} else {
p2 + + ;
}
2007-09-08 00:57:01 +04:00
if ( * p ) {
2002-12-04 02:57:45 +03:00
p + + ;
2007-09-08 00:57:01 +04:00
}
2002-12-04 02:57:45 +03:00
}
2007-09-08 00:57:01 +04:00
if ( * ext2 ) {
* pp_newname = talloc_asprintf ( ctx , " %s/%s.%s " ,
name2_copy ,
root2 ,
ext2 ) ;
2003-04-14 03:45:35 +04:00
} else {
2007-09-08 00:57:01 +04:00
* pp_newname = talloc_asprintf ( ctx , " %s/%s " ,
name2_copy ,
root2 ) ;
2002-12-04 02:57:45 +03:00
}
2007-09-08 00:57:01 +04:00
if ( ! * pp_newname ) {
return False ;
}
return True ;
1996-05-04 11:50:46 +04:00
}
2003-08-16 06:34:03 +04:00
/****************************************************************************
2005-12-13 21:11:50 +03:00
Ensure open files have their names updated . Updated to notify other smbd ' s
asynchronously .
2003-08-16 06:34:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-14 16:03:46 +04:00
static void rename_open_files ( connection_struct * conn ,
struct share_mode_lock * lck ,
const char * newname )
2003-08-16 06:34:03 +04:00
{
files_struct * fsp ;
2007-10-19 04:40:25 +04:00
bool did_rename = False ;
2003-08-16 06:34:03 +04:00
2007-06-14 16:03:46 +04:00
for ( fsp = file_find_di_first ( lck - > id ) ; fsp ;
fsp = file_find_di_next ( fsp ) ) {
2005-12-14 20:46:29 +03:00
/* fsp_name is a relative path under the fsp. To change this for other
sharepaths we need to manipulate relative paths . */
/* TODO - create the absolute path and manipulate the newname
relative to the sharepath . */
if ( fsp - > conn ! = conn ) {
continue ;
}
2007-05-29 13:30:34 +04:00
DEBUG ( 10 , ( " rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s \n " ,
2007-09-10 14:56:07 +04:00
fsp - > fnum , file_id_string_tos ( & fsp - > file_id ) ,
2003-08-16 06:34:03 +04:00
fsp - > fsp_name , newname ) ) ;
string_set ( & fsp - > fsp_name , newname ) ;
did_rename = True ;
}
2005-12-13 21:11:50 +03:00
if ( ! did_rename ) {
2007-05-29 13:30:34 +04:00
DEBUG ( 10 , ( " rename_open_files: no open files on file_id %s for %s \n " ,
2007-09-10 14:56:07 +04:00
file_id_string_tos ( & lck - > id ) , newname ) ) ;
2005-12-13 21:11:50 +03:00
}
/* Send messages to all smbd's (not ourself) that the name has changed. */
2007-05-14 17:01:28 +04:00
rename_share_filename ( smbd_messaging_context ( ) , lck , conn - > connectpath ,
newname ) ;
2003-08-16 06:34:03 +04:00
}
2005-09-27 21:42:11 +04:00
/****************************************************************************
We need to check if the source path is a parent directory of the destination
( ie . a rename of / foo / bar / baz - > / foo / bar / baz / bibble / bobble . If so we must
refuse the rename with a sharing violation . Under UNIX the above call can
* succeed * if / foo / bar / baz is a symlink to another area in the share . We
probably need to check that the client is a Windows one before disallowing
this as a UNIX client ( one with UNIX extensions ) can know the source is a
symlink and make this decision intelligently . Found by an excellent bug
report from < AndyLiebman @ aol . com > .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool rename_path_prefix_equal ( const char * src , const char * dest )
2005-09-27 21:42:11 +04:00
{
const char * psrc = src ;
const char * pdst = dest ;
size_t slen ;
if ( psrc [ 0 ] = = ' . ' & & psrc [ 1 ] = = ' / ' ) {
psrc + = 2 ;
}
if ( pdst [ 0 ] = = ' . ' & & pdst [ 1 ] = = ' / ' ) {
pdst + = 2 ;
}
if ( ( slen = strlen ( psrc ) ) > strlen ( pdst ) ) {
return False ;
}
return ( ( memcmp ( psrc , pdst , slen ) = = 0 ) & & pdst [ slen ] = = ' / ' ) ;
}
2007-06-14 19:50:47 +04:00
/*
* Do the notify calls from a rename
*/
2007-10-19 04:40:25 +04:00
static void notify_rename ( connection_struct * conn , bool is_dir ,
2007-06-14 19:50:47 +04:00
const char * oldpath , const char * newpath )
{
char * olddir , * newdir ;
const char * oldname , * newname ;
uint32 mask ;
mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME ;
if ( ! parent_dirname_talloc ( NULL , oldpath , & olddir , & oldname )
| | ! parent_dirname_talloc ( NULL , newpath , & newdir , & newname ) ) {
TALLOC_FREE ( olddir ) ;
return ;
}
if ( strcmp ( olddir , newdir ) = = 0 ) {
notify_fname ( conn , NOTIFY_ACTION_OLD_NAME , mask , oldpath ) ;
notify_fname ( conn , NOTIFY_ACTION_NEW_NAME , mask , newpath ) ;
}
else {
notify_fname ( conn , NOTIFY_ACTION_REMOVED , mask , oldpath ) ;
notify_fname ( conn , NOTIFY_ACTION_ADDED , mask , newpath ) ;
}
TALLOC_FREE ( olddir ) ;
TALLOC_FREE ( newdir ) ;
/* this is a strange one. w2k3 gives an additional event for
CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
files , but not directories */
if ( ! is_dir ) {
notify_fname ( conn , NOTIFY_ACTION_MODIFIED ,
FILE_NOTIFY_CHANGE_ATTRIBUTES
| FILE_NOTIFY_CHANGE_CREATION ,
newpath ) ;
}
}
2003-08-16 06:34:03 +04:00
/****************************************************************************
Rename an open file - given an fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-08 00:57:01 +04:00
NTSTATUS rename_internals_fsp ( connection_struct * conn ,
files_struct * fsp ,
char * newname ,
const char * newname_last_component ,
uint32 attrs ,
2007-10-19 04:40:25 +04:00
bool replace_if_exists )
2003-08-16 06:34:03 +04:00
{
2007-09-08 00:57:01 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-06-14 18:45:37 +04:00
SMB_STRUCT_STAT sbuf , sbuf1 ;
2007-01-13 02:47:16 +03:00
NTSTATUS status = NT_STATUS_OK ;
2005-12-14 20:46:29 +03:00
struct share_mode_lock * lck = NULL ;
2007-10-19 04:40:25 +04:00
bool dst_exists ;
2003-08-16 06:34:03 +04:00
ZERO_STRUCT ( sbuf ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , newname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-09-08 00:57:01 +04:00
2003-08-16 06:34:03 +04:00
/* Ensure newname contains a '/' */
if ( strrchr_m ( newname , ' / ' ) = = 0 ) {
2007-09-08 00:57:01 +04:00
newname = talloc_asprintf ( ctx ,
" ./%s " ,
newname ) ;
if ( ! newname ) {
return NT_STATUS_NO_MEMORY ;
}
2003-08-16 06:34:03 +04:00
}
/*
* Check for special case with case preserving and not
* case sensitive . If the old last component differs from the original
* last component only by case , then we should allow
* the rename ( user is trying to change the case of the
* filename ) .
*/
2004-05-07 22:37:47 +04:00
if ( ( conn - > case_sensitive = = False ) & & ( conn - > case_preserve = = True ) & &
2003-08-16 06:34:03 +04:00
strequal ( newname , fsp - > fsp_name ) ) {
char * p ;
2007-09-08 00:57:01 +04:00
char * newname_modified_last_component = NULL ;
2003-08-16 06:34:03 +04:00
/*
* Get the last component of the modified name .
* Note that we guarantee that newname contains a ' / '
* character above .
*/
p = strrchr_m ( newname , ' / ' ) ;
2007-09-08 00:57:01 +04:00
newname_modified_last_component = talloc_strdup ( ctx ,
p + 1 ) ;
if ( ! newname_modified_last_component ) {
return NT_STATUS_NO_MEMORY ;
}
if ( strcsequal ( newname_modified_last_component ,
2003-08-16 06:34:03 +04:00
newname_last_component ) = = False ) {
/*
* Replace the modified last component with
* the original .
*/
2007-09-08 00:57:01 +04:00
* p = ' \0 ' ; /* Truncate at the '/' */
newname = talloc_asprintf ( ctx ,
" %s/%s " ,
newname ,
newname_last_component ) ;
2003-08-16 06:34:03 +04:00
}
}
/*
* If the src and dest names are identical - including case ,
* don ' t do the rename , just return success .
*/
if ( strcsequal ( fsp - > fsp_name , newname ) ) {
DEBUG ( 3 , ( " rename_internals_fsp: identical names in rename %s - returning success \n " ,
newname ) ) ;
return NT_STATUS_OK ;
}
2007-06-14 18:45:37 +04:00
/*
* Have vfs_object_exist also fill sbuf1
*/
dst_exists = vfs_object_exist ( conn , newname , & sbuf1 ) ;
if ( ! replace_if_exists & & dst_exists ) {
2003-08-16 06:34:03 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: dest exists doing rename %s -> %s \n " ,
fsp - > fsp_name , newname ) ) ;
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2007-07-17 06:06:38 +04:00
if ( dst_exists ) {
2007-08-02 12:53:24 +04:00
struct file_id fileid = vfs_file_id_from_sbuf ( conn , & sbuf1 ) ;
files_struct * dst_fsp = file_find_di_first ( fileid ) ;
2007-07-17 09:55:10 +04:00
if ( dst_fsp ) {
2007-07-17 06:06:38 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: Target file open \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2007-06-14 18:45:37 +04:00
}
2007-05-24 01:32:10 +04:00
/* Ensure we have a valid stat struct for the source. */
if ( fsp - > fh - > fd ! = - 1 ) {
if ( SMB_VFS_FSTAT ( fsp , fsp - > fh - > fd , & sbuf ) = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
} else {
if ( SMB_VFS_STAT ( conn , fsp - > fsp_name , & sbuf ) = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
}
2003-08-16 06:34:03 +04:00
2007-06-16 14:02:51 +04:00
status = can_rename ( conn , fsp , attrs , & sbuf ) ;
2007-05-24 01:32:10 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-05-23 03:56:47 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: Error %s rename %s -> %s \n " ,
2007-01-13 02:47:16 +03:00
nt_errstr ( status ) , fsp - > fsp_name , newname ) ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) )
status = NT_STATUS_ACCESS_DENIED ;
return status ;
2003-08-16 06:34:03 +04:00
}
2005-09-27 21:42:11 +04:00
if ( rename_path_prefix_equal ( fsp - > fsp_name , newname ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
2007-05-29 13:30:34 +04:00
lck = get_share_mode_lock ( NULL , fsp - > file_id , NULL , NULL ) ;
2005-12-14 20:46:29 +03:00
2007-06-14 16:03:46 +04:00
/*
* We have the file open ourselves , so not being able to get the
* corresponding share mode lock is a fatal error .
*/
SMB_ASSERT ( lck ! = NULL ) ;
2003-08-16 06:34:03 +04:00
if ( SMB_VFS_RENAME ( conn , fsp - > fsp_name , newname ) = = 0 ) {
2007-05-24 01:32:10 +04:00
uint32 create_options = fsp - > fh - > private_options ;
2003-08-16 06:34:03 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: succeeded doing rename on %s -> %s \n " ,
fsp - > fsp_name , newname ) ) ;
2007-05-24 01:32:10 +04:00
2007-06-14 16:03:46 +04:00
rename_open_files ( conn , lck , newname ) ;
2007-05-24 01:32:10 +04:00
2007-06-14 19:50:47 +04:00
notify_rename ( conn , fsp - > is_directory , fsp - > fsp_name , newname ) ;
2007-05-24 01:32:10 +04:00
/*
* A rename acts as a new file create w . r . t . allowing an initial delete
* on close , probably because in Windows there is a new handle to the
* new file . If initial delete on close was requested but not
* originally set , we need to set it here . This is probably not 100 % correct ,
* but will work for the CIFSFS client which in non - posix mode
* depends on these semantics . JRA .
*/
set_allow_initial_delete_on_close ( lck , fsp , True ) ;
if ( create_options & FILE_DELETE_ON_CLOSE ) {
status = can_set_delete_on_close ( fsp , True , 0 ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
/* Note that here we set the *inital* delete on close flag,
* not the regular one . The magic gets handled in close . */
fsp - > initial_delete_on_close = True ;
}
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2007-09-08 00:57:01 +04:00
return NT_STATUS_OK ;
2003-08-16 06:34:03 +04:00
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2005-12-14 20:46:29 +03:00
2005-12-13 21:11:50 +03:00
if ( errno = = ENOTDIR | | errno = = EISDIR ) {
2007-01-13 02:47:16 +03:00
status = NT_STATUS_OBJECT_NAME_COLLISION ;
2005-12-13 21:11:50 +03:00
} else {
2007-01-13 02:47:16 +03:00
status = map_nt_error_from_unix ( errno ) ;
2005-12-13 21:11:50 +03:00
}
2007-09-08 00:57:01 +04:00
2003-08-16 06:34:03 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: Error %s rename %s -> %s \n " ,
2007-01-13 02:47:16 +03:00
nt_errstr ( status ) , fsp - > fsp_name , newname ) ) ;
2003-08-16 06:34:03 +04:00
2007-01-13 02:47:16 +03:00
return status ;
2003-08-16 06:34:03 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1998-07-11 04:28:34 +04:00
The guts of the rename command , split out so it may be called by the NT SMB
2007-09-13 01:48:20 +04:00
code .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-05 00:11:35 +03:00
2007-09-13 01:48:20 +04:00
NTSTATUS rename_internals ( TALLOC_CTX * ctx ,
connection_struct * conn ,
struct smb_request * req ,
const char * name_in ,
const char * newname_in ,
uint32 attrs ,
2007-10-19 04:40:25 +04:00
bool replace_if_exists ,
bool src_has_wild ,
bool dest_has_wild )
1996-05-04 11:50:46 +04:00
{
2007-09-13 01:48:20 +04:00
char * directory = NULL ;
char * mask = NULL ;
2007-09-08 00:57:01 +04:00
char * last_component_src = NULL ;
char * last_component_dest = NULL ;
char * name = NULL ;
char * newname = NULL ;
1998-08-14 21:38:29 +04:00
char * p ;
int count = 0 ;
2007-01-13 02:47:16 +03:00
NTSTATUS status = NT_STATUS_OK ;
2000-10-19 06:58:24 +04:00
SMB_STRUCT_STAT sbuf1 , sbuf2 ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
struct smb_Dir * dir_hnd = NULL ;
const char * dname ;
long offset = 0 ;
1998-08-14 21:38:29 +04:00
2003-08-16 06:34:03 +04:00
ZERO_STRUCT ( sbuf1 ) ;
ZERO_STRUCT ( sbuf2 ) ;
2004-03-03 23:55:59 +03:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , name_in , src_has_wild , & name ,
2007-09-08 00:57:01 +04:00
& last_component_src , & sbuf1 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-03-03 23:55:59 +03:00
}
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , newname_in , dest_has_wild , & newname ,
2007-09-08 00:57:01 +04:00
& last_component_dest , & sbuf2 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-03-03 23:55:59 +03:00
}
2004-02-25 04:35:14 +03:00
1998-08-14 21:38:29 +04:00
/*
* Split the old name into directory and last component
2007-09-13 01:48:20 +04:00
* strings . Note that unix_convert may have stripped off a
* leading . / from both name and newname if the rename is
1998-08-14 21:38:29 +04:00
* at the root of the share . We need to make sure either both
* name and newname contain a / character or neither of them do
* as this is checked in resolve_wildcards ( ) .
*/
2004-02-25 04:35:14 +03:00
2001-07-04 11:36:09 +04:00
p = strrchr_m ( name , ' / ' ) ;
1998-08-14 21:38:29 +04:00
if ( ! p ) {
2007-09-13 01:48:20 +04:00
directory = talloc_strdup ( ctx , " . " ) ;
if ( ! directory ) {
return NT_STATUS_NO_MEMORY ;
}
mask = name ;
1998-08-14 21:38:29 +04:00
} else {
* p = 0 ;
2007-09-13 01:48:20 +04:00
directory = talloc_strdup ( ctx , name ) ;
if ( ! directory ) {
return NT_STATUS_NO_MEMORY ;
}
mask = p + 1 ;
1998-08-14 21:38:29 +04:00
* p = ' / ' ; /* Replace needed for exceptional test below. */
}
1997-01-13 22:41:08 +03:00
1999-12-13 16:27:58 +03:00
/*
* We should only check the mangled cache
* here if unix_convert failed . This means
* that the path in ' mask ' doesn ' t exist
* on the file system and so we need to look
* for a possible mangle . This patch from
* Tine Smukavec < valentin . smukavec @ hermes . si > .
*/
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! VALID_STAT ( sbuf1 ) & & mangle_is_mangled ( mask , conn - > params ) ) {
2007-09-08 00:57:01 +04:00
char * new_mask = NULL ;
2007-09-13 01:48:20 +04:00
mangle_lookup_name_from_8_3 ( ctx ,
2007-09-08 00:57:01 +04:00
mask ,
& new_mask ,
conn - > params ) ;
if ( new_mask ) {
2007-09-13 01:48:20 +04:00
mask = new_mask ;
2007-09-08 00:57:01 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
1997-02-18 20:20:14 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! src_has_wild ) {
2007-06-16 14:02:51 +04:00
files_struct * fsp ;
1998-08-14 21:38:29 +04:00
/*
* No wildcards - just process the one file .
*/
2007-10-19 04:40:25 +04:00
bool is_short_name = mangle_is_8_3 ( name , True , conn - > params ) ;
1997-01-13 22:41:08 +03:00
1998-08-14 21:38:29 +04:00
/* Add a terminating '/' to the directory name. */
2007-09-13 01:48:20 +04:00
directory = talloc_asprintf_append ( directory ,
" /%s " ,
mask ) ;
if ( ! directory ) {
return NT_STATUS_NO_MEMORY ;
}
2007-09-08 00:57:01 +04:00
1998-08-14 21:38:29 +04:00
/* Ensure newname contains a '/' also */
2001-07-04 11:36:09 +04:00
if ( strrchr_m ( newname , ' / ' ) = = 0 ) {
2007-09-13 01:48:20 +04:00
newname = talloc_asprintf ( ctx ,
2007-09-08 00:57:01 +04:00
" ./%s " ,
newname ) ;
if ( ! newname ) {
return NT_STATUS_NO_MEMORY ;
}
1998-08-14 21:38:29 +04:00
}
2007-09-08 00:57:01 +04:00
2007-01-31 15:55:39 +03:00
DEBUG ( 3 , ( " rename_internals: case_sensitive = %d, "
" case_preserve = %d, short case preserve = %d, "
" directory = %s, newname = %s, "
2007-09-13 01:48:20 +04:00
" last_component_dest = %s, is_8_3 = %d \n " ,
2007-01-31 15:55:39 +03:00
conn - > case_sensitive , conn - > case_preserve ,
2007-09-13 01:48:20 +04:00
conn - > short_case_preserve , directory ,
2007-01-31 15:55:39 +03:00
newname , last_component_dest , is_short_name ) ) ;
1998-08-14 21:38:29 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
/* The dest name still may have wildcards. */
if ( dest_has_wild ) {
2007-09-08 00:57:01 +04:00
char * mod_newname = NULL ;
2007-09-13 01:48:20 +04:00
if ( ! resolve_wildcards ( ctx ,
2007-09-08 00:57:01 +04:00
directory , newname , & mod_newname ) ) {
2007-09-13 01:48:20 +04:00
DEBUG ( 6 , ( " rename_internals: resolve_wildcards "
" %s %s failed \n " ,
directory ,
newname ) ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
return NT_STATUS_NO_MEMORY ;
}
2007-09-08 00:57:01 +04:00
newname = mod_newname ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
2007-06-16 14:02:51 +04:00
ZERO_STRUCT ( sbuf1 ) ;
SMB_VFS_STAT ( conn , directory , & sbuf1 ) ;
status = S_ISDIR ( sbuf1 . st_mode ) ?
2007-07-05 20:26:27 +04:00
open_directory ( conn , req , directory , & sbuf1 ,
2007-06-16 14:02:51 +04:00
DELETE_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN , 0 , 0 , NULL ,
& fsp )
2007-07-05 20:26:27 +04:00
: open_file_ntcreate ( conn , req , directory , & sbuf1 ,
2007-06-16 14:02:51 +04:00
DELETE_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN , 0 , 0 , 0 , NULL ,
& fsp ) ;
2002-01-05 00:11:35 +03:00
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-06-16 14:02:51 +04:00
DEBUG ( 3 , ( " Could not open rename source %s: %s \n " ,
directory , nt_errstr ( status ) ) ) ;
2007-01-13 02:47:16 +03:00
return status ;
2002-01-05 00:11:35 +03:00
}
2007-08-19 23:57:55 +04:00
status = rename_internals_fsp ( conn , fsp , newname ,
last_component_dest ,
attrs , replace_if_exists ) ;
2005-12-14 20:46:29 +03:00
2007-06-16 14:02:51 +04:00
close_file ( fsp , NORMAL_CLOSE ) ;
2002-01-05 00:11:35 +03:00
2007-06-16 14:02:51 +04:00
DEBUG ( 3 , ( " rename_internals: Error %s rename %s -> %s \n " ,
nt_errstr ( status ) , directory , newname ) ) ;
2002-01-05 00:11:35 +03:00
2007-01-13 02:47:16 +03:00
return status ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
/*
* Wildcards - process each file that matches .
*/
if ( strequal ( mask , " ????????.??? " ) ) {
2007-09-13 01:48:20 +04:00
mask [ 0 ] = ' * ' ;
mask [ 1 ] = ' \0 ' ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
dir_hnd = OpenDir ( conn , directory , mask , attrs ) ;
if ( dir_hnd = = NULL ) {
return map_nt_error_from_unix ( errno ) ;
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = NT_STATUS_NO_SUCH_FILE ;
/*
* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
* - gentest fix . JRA
*/
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
while ( ( dname = ReadDirName ( dir_hnd , & offset ) ) ) {
2007-09-13 01:48:20 +04:00
files_struct * fsp = NULL ;
char * fname = NULL ;
char * destname = NULL ;
2007-10-19 04:40:25 +04:00
bool sysdir_entry = False ;
2000-03-29 11:44:23 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
/* Quick check for "." and ".." */
2007-09-13 01:48:20 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
if ( attrs & aDIR ) {
sysdir_entry = True ;
} else {
continue ;
2007-01-17 05:09:37 +03:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2004-02-25 03:48:35 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! is_visible_file ( conn , directory , dname , & sbuf1 , False ) ) {
continue ;
}
2005-02-01 21:33:50 +03:00
2007-09-13 01:48:20 +04:00
if ( ! mask_match ( dname , mask , conn - > case_sensitive ) ) {
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( sysdir_entry ) {
status = NT_STATUS_OBJECT_NAME_INVALID ;
break ;
}
2004-03-03 23:55:59 +03:00
2007-09-13 01:48:20 +04:00
fname = talloc_asprintf ( ctx ,
" %s/%s " ,
directory ,
dname ) ;
if ( ! fname ) {
return NT_STATUS_NO_MEMORY ;
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
2007-09-13 01:48:20 +04:00
if ( ! resolve_wildcards ( ctx ,
fname , newname , & destname ) ) {
DEBUG ( 6 , ( " resolve_wildcards %s %s failed \n " ,
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
fname , destname ) ) ;
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( fname ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
if ( ! destname ) {
return NT_STATUS_NO_MEMORY ;
}
2007-06-16 14:02:51 +04:00
ZERO_STRUCT ( sbuf1 ) ;
SMB_VFS_STAT ( conn , fname , & sbuf1 ) ;
status = S_ISDIR ( sbuf1 . st_mode ) ?
2007-07-05 20:26:27 +04:00
open_directory ( conn , req , fname , & sbuf1 ,
2007-06-16 14:02:51 +04:00
DELETE_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN , 0 , 0 , NULL ,
& fsp )
2007-07-05 20:26:27 +04:00
: open_file_ntcreate ( conn , req , fname , & sbuf1 ,
2007-06-16 14:02:51 +04:00
DELETE_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN , 0 , 0 , 0 , NULL ,
& fsp ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-06-16 14:02:51 +04:00
DEBUG ( 3 , ( " rename_internals: open_file_ntcreate "
" returned %s rename %s -> %s \n " ,
nt_errstr ( status ) , directory , newname ) ) ;
2007-06-18 16:22:42 +04:00
break ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2004-04-02 23:51:27 +04:00
2007-08-19 23:57:55 +04:00
status = rename_internals_fsp ( conn , fsp , destname , dname ,
attrs , replace_if_exists ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
2007-06-16 14:02:51 +04:00
close_file ( fsp , NORMAL_CLOSE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " rename_internals_fsp returned %s for "
" rename %s -> %s \n " , nt_errstr ( status ) ,
directory , newname ) ) ;
2007-06-18 16:22:42 +04:00
break ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2005-09-27 21:42:11 +04:00
2007-06-16 14:02:51 +04:00
count + + ;
2005-12-14 20:46:29 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
DEBUG ( 3 , ( " rename_internals: doing rename on %s -> "
" %s \n " , fname , destname ) ) ;
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( fname ) ;
TALLOC_FREE ( destname ) ;
2007-01-17 05:09:37 +03:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
CloseDir ( dir_hnd ) ;
2007-01-13 02:47:16 +03:00
if ( count = = 0 & & NT_STATUS_IS_OK ( status ) ) {
status = map_nt_error_from_unix ( errno ) ;
1998-08-14 21:38:29 +04:00
}
2007-09-13 01:48:20 +04:00
2007-01-13 02:47:16 +03:00
return status ;
1998-07-11 04:28:34 +04:00
}
/****************************************************************************
Reply to a mv .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 18:50:49 +04:00
void reply_mv ( connection_struct * conn , struct smb_request * req )
1998-07-11 04:28:34 +04:00
{
2007-09-11 22:31:29 +04:00
char * name = NULL ;
char * newname = NULL ;
2001-09-04 11:13:01 +04:00
char * p ;
2007-08-14 18:50:49 +04:00
uint32 attrs ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2007-10-19 04:40:25 +04:00
bool src_has_wcard = False ;
bool dest_has_wcard = False ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2000-03-09 01:14:30 +03:00
2001-09-04 11:13:01 +04:00
START_PROFILE ( SMBmv ) ;
1998-07-11 04:28:34 +04:00
2007-08-14 18:50:49 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBmv ) ;
return ;
}
2007-07-05 20:26:27 +04:00
2007-08-14 18:50:49 +04:00
attrs = SVAL ( req - > inbuf , smb_vwv0 ) ;
p = smb_buf ( req - > inbuf ) + 1 ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx , ( char * ) req - > inbuf , req - > flags2 , & name , p ,
0 , STR_TERMINATE , & status ,
2007-07-05 20:36:15 +04:00
& src_has_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBmv ) ;
2007-08-14 18:50:49 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2001-09-04 11:13:01 +04:00
p + + ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx , ( char * ) req - > inbuf , req - > flags2 , & newname , p ,
0 , STR_TERMINATE , & status ,
2007-07-05 20:36:15 +04:00
& dest_has_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBmv ) ;
2007-08-14 18:50:49 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2007-09-11 22:31:29 +04:00
status = resolve_dfspath_wcard ( ctx , conn ,
2007-08-14 18:50:49 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
name ,
2007-09-11 22:31:29 +04:00
& name ,
& src_has_wcard ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 18:50:49 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBmv ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBmv ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath_wcard ( ctx , conn ,
2007-08-14 18:50:49 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
newname ,
2007-09-11 22:31:29 +04:00
& newname ,
& dest_has_wcard ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 18:50:49 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBmv ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBmv ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2001-09-04 11:13:01 +04:00
DEBUG ( 3 , ( " reply_mv : %s -> %s \n " , name , newname ) ) ;
2007-09-11 22:31:29 +04:00
2007-09-13 01:48:20 +04:00
status = rename_internals ( ctx , conn , req , name , newname , attrs , False ,
2007-07-05 20:26:27 +04:00
src_has_wcard , dest_has_wcard ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2007-08-14 18:50:49 +04:00
END_PROFILE ( SMBmv ) ;
return ;
2004-06-08 20:14:31 +04:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBmv ) ;
return ;
2001-09-04 11:13:01 +04:00
}
2000-09-20 23:00:21 +04:00
2007-08-14 18:50:49 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2007-09-11 22:31:29 +04:00
2001-09-04 11:13:01 +04:00
END_PROFILE ( SMBmv ) ;
2007-08-14 18:50:49 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2001-09-04 23:10:30 +04:00
Copy a file as part of a reply_copy .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-23 04:58:28 +04:00
2007-01-05 16:13:15 +03:00
/*
* TODO : check error codes on all callers
*/
2007-09-13 01:48:20 +04:00
NTSTATUS copy_file ( TALLOC_CTX * ctx ,
connection_struct * conn ,
const char * src ,
const char * dest1 ,
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
int ofun ,
int count ,
2007-10-19 04:40:25 +04:00
bool target_is_directory )
1996-05-04 11:50:46 +04:00
{
2001-09-04 23:10:30 +04:00
SMB_STRUCT_STAT src_sbuf , sbuf2 ;
SMB_OFF_T ret = - 1 ;
files_struct * fsp1 , * fsp2 ;
2007-09-13 01:48:20 +04:00
char * dest = NULL ;
2004-04-02 22:46:19 +04:00
uint32 dosattrs ;
2005-07-08 08:51:27 +04:00
uint32 new_create_disposition ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
2007-09-13 01:48:20 +04:00
dest = talloc_strdup ( ctx , dest1 ) ;
if ( ! dest ) {
return NT_STATUS_NO_MEMORY ;
}
2001-09-04 23:10:30 +04:00
if ( target_is_directory ) {
2007-09-13 01:48:20 +04:00
const char * p = strrchr_m ( src , ' / ' ) ;
2005-07-08 08:51:27 +04:00
if ( p ) {
2001-09-04 23:10:30 +04:00
p + + ;
2005-07-08 08:51:27 +04:00
} else {
2001-09-04 23:10:30 +04:00
p = src ;
2005-07-08 08:51:27 +04:00
}
2007-09-13 01:48:20 +04:00
dest = talloc_asprintf_append ( dest ,
" /%s " ,
p ) ;
if ( ! dest ) {
return NT_STATUS_NO_MEMORY ;
}
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2005-07-08 08:51:27 +04:00
if ( ! vfs_file_exist ( conn , src , & src_sbuf ) ) {
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( dest ) ;
2007-01-05 16:13:15 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
2005-07-08 08:51:27 +04:00
}
if ( ! target_is_directory & & count ) {
new_create_disposition = FILE_OPEN ;
} else {
if ( ! map_open_params_to_ntcreate ( dest1 , 0 , ofun ,
NULL , NULL , & new_create_disposition , NULL ) ) {
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( dest ) ;
2007-01-05 16:13:15 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2005-07-08 08:51:27 +04:00
}
}
1996-05-04 11:50:46 +04:00
2007-07-05 20:26:27 +04:00
status = open_file_ntcreate ( conn , NULL , src , & src_sbuf ,
2005-07-08 08:51:27 +04:00
FILE_GENERIC_READ ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN ,
0 ,
FILE_ATTRIBUTE_NORMAL ,
INTERNAL_OPEN_ONLY ,
2006-07-11 22:01:26 +04:00
NULL , & fsp1 ) ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( dest ) ;
2007-01-05 16:13:15 +03:00
return status ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2004-04-02 22:46:19 +04:00
dosattrs = dos_mode ( conn , src , & src_sbuf ) ;
2005-07-08 08:51:27 +04:00
if ( SMB_VFS_STAT ( conn , dest , & sbuf2 ) = = - 1 ) {
2001-09-04 23:10:30 +04:00
ZERO_STRUCTP ( & sbuf2 ) ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2007-07-05 20:26:27 +04:00
status = open_file_ntcreate ( conn , NULL , dest , & sbuf2 ,
2005-07-08 08:51:27 +04:00
FILE_GENERIC_WRITE ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
new_create_disposition ,
0 ,
dosattrs ,
INTERNAL_OPEN_ONLY ,
2006-07-11 22:01:26 +04:00
NULL , & fsp2 ) ;
1996-05-04 11:50:46 +04:00
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( dest ) ;
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp1 , ERROR_CLOSE ) ;
2007-01-05 16:13:15 +03:00
return status ;
2001-09-04 23:10:30 +04:00
}
if ( ( ofun & 3 ) = = 1 ) {
2005-07-08 08:51:27 +04:00
if ( SMB_VFS_LSEEK ( fsp2 , fsp2 - > fh - > fd , 0 , SEEK_END ) = = - 1 ) {
2001-09-04 23:10:30 +04:00
DEBUG ( 0 , ( " copy_file: error - vfs lseek returned error %s \n " , strerror ( errno ) ) ) ;
/*
* Stop the copy from occurring .
*/
ret = - 1 ;
src_sbuf . st_size = 0 ;
}
}
2007-09-13 01:48:20 +04:00
2005-07-08 08:51:27 +04:00
if ( src_sbuf . st_size ) {
2001-09-04 23:10:30 +04:00
ret = vfs_transfer_file ( fsp1 , fsp2 , src_sbuf . st_size ) ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2006-02-02 23:44:50 +03:00
close_file ( fsp1 , NORMAL_CLOSE ) ;
2002-01-03 23:49:06 +03:00
/* Ensure the modtime is set correctly on the destination file. */
2007-03-06 02:40:03 +03:00
fsp_set_pending_modtime ( fsp2 , get_mtimespec ( & src_sbuf ) ) ;
2002-01-03 23:49:06 +03:00
2001-09-04 23:10:30 +04:00
/*
* As we are opening fsp1 read - only we only expect
* an error on close on fsp2 if we are out of space .
* Thus we don ' t look at the error return from the
* close of fsp1 .
*/
2007-02-07 00:05:34 +03:00
status = close_file ( fsp2 , NORMAL_CLOSE ) ;
1996-05-04 11:50:46 +04:00
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2007-01-05 16:13:15 +03:00
}
if ( ret ! = ( SMB_OFF_T ) src_sbuf . st_size ) {
return NT_STATUS_DISK_FULL ;
}
return NT_STATUS_OK ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a file copy .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-15 01:21:52 +04:00
void reply_copy ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * name = NULL ;
char * newname = NULL ;
2007-09-13 01:48:20 +04:00
char * directory = NULL ;
char * mask = NULL ;
2002-12-04 02:57:45 +03:00
char * p ;
int count = 0 ;
int error = ERRnoaccess ;
int err = 0 ;
2007-08-15 01:21:52 +04:00
int tid2 ;
int ofun ;
int flags ;
2007-10-19 04:40:25 +04:00
bool target_is_directory = False ;
bool source_has_wild = False ;
bool dest_has_wild = False ;
2002-12-04 02:57:45 +03:00
SMB_STRUCT_STAT sbuf1 , sbuf2 ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-08-15 01:21:52 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBcopy ) ;
return ;
}
tid2 = SVAL ( req - > inbuf , smb_vwv0 ) ;
ofun = SVAL ( req - > inbuf , smb_vwv1 ) ;
flags = SVAL ( req - > inbuf , smb_vwv2 ) ;
p = smb_buf ( req - > inbuf ) ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx , ( char * ) req - > inbuf , req - > flags2 , & name , p ,
0 , STR_TERMINATE , & status ,
2007-07-05 20:36:15 +04:00
& source_has_wild ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx , ( char * ) req - > inbuf , req - > flags2 , & newname , p ,
0 , STR_TERMINATE , & status ,
2007-07-05 20:36:15 +04:00
& dest_has_wild ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2007-09-11 22:31:29 +04:00
2007-09-12 03:57:59 +04:00
DEBUG ( 3 , ( " reply_copy : %s -> %s \n " , name , newname ) ) ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
if ( tid2 ! = conn - > cnum ) {
/* can't currently handle inter share copies XXXX */
DEBUG ( 3 , ( " Rejecting inter-share copy \n " ) ) ;
2007-08-15 01:21:52 +04:00
reply_doserror ( req , ERRSRV , ERRinvdevice ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
1996-05-04 11:50:46 +04:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath_wcard ( ctx , conn ,
2007-08-15 01:21:52 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
name ,
2007-09-11 22:31:29 +04:00
& name ,
& source_has_wild ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-15 01:21:52 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBcopy ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath_wcard ( ctx , conn ,
2007-08-15 01:21:52 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
newname ,
2007-09-11 22:31:29 +04:00
& newname ,
& dest_has_wild ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-15 01:21:52 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBcopy ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
2007-03-08 01:12:58 +03:00
}
1996-05-04 11:50:46 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , name , source_has_wild ,
& name , NULL , & sbuf1 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
2007-01-13 02:47:16 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2007-01-13 02:47:16 +03:00
}
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , newname , dest_has_wild ,
& newname , NULL , & sbuf2 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
2007-01-13 02:47:16 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2007-01-13 02:47:16 +03:00
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
target_is_directory = VALID_STAT_OF_DIR ( sbuf2 ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( ( flags & 1 ) & & target_is_directory ) {
2007-08-15 01:21:52 +04:00
reply_doserror ( req , ERRDOS , ERRbadfile ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( ( flags & 2 ) & & ! target_is_directory ) {
2007-08-15 01:21:52 +04:00
reply_doserror ( req , ERRDOS , ERRbadpath ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
if ( ( flags & ( 1 < < 5 ) ) & & VALID_STAT_OF_DIR ( sbuf1 ) ) {
/* wants a tree copy! XXXX */
DEBUG ( 3 , ( " Rejecting tree copy \n " ) ) ;
2007-08-15 01:21:52 +04:00
reply_doserror ( req , ERRSRV , ERRerror ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
p = strrchr_m ( name , ' / ' ) ;
if ( ! p ) {
2007-09-13 01:48:20 +04:00
directory = talloc_strdup ( ctx , " ./ " ) ;
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBcopy ) ;
return ;
}
mask = name ;
2002-12-04 02:57:45 +03:00
} else {
* p = 0 ;
2007-09-13 01:48:20 +04:00
directory = talloc_strdup ( ctx , name ) ;
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBcopy ) ;
return ;
}
mask = p + 1 ;
2002-12-04 02:57:45 +03:00
}
/*
* We should only check the mangled cache
* here if unix_convert failed . This means
* that the path in ' mask ' doesn ' t exist
* on the file system and so we need to look
* for a possible mangle . This patch from
* Tine Smukavec < valentin . smukavec @ hermes . si > .
*/
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! VALID_STAT ( sbuf1 ) & & mangle_is_mangled ( mask , conn - > params ) ) {
2007-09-08 00:57:01 +04:00
char * new_mask = NULL ;
2007-09-13 01:48:20 +04:00
mangle_lookup_name_from_8_3 ( ctx ,
2007-09-08 00:57:01 +04:00
mask ,
& new_mask ,
conn - > params ) ;
if ( new_mask ) {
2007-09-13 01:48:20 +04:00
mask = new_mask ;
2007-09-08 00:57:01 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2002-12-04 02:57:45 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! source_has_wild ) {
2007-09-13 01:48:20 +04:00
directory = talloc_asprintf_append ( directory ,
" /%s " ,
mask ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( dest_has_wild ) {
2007-09-08 00:57:01 +04:00
char * mod_newname = NULL ;
2007-09-13 01:48:20 +04:00
if ( ! resolve_wildcards ( ctx ,
2007-09-08 00:57:01 +04:00
directory , newname , & mod_newname ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-08 00:57:01 +04:00
newname = mod_newname ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
2002-12-04 02:57:45 +03:00
}
2007-09-12 03:57:59 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , newname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
status = copy_file ( ctx , conn , directory , newname , ofun ,
count , target_is_directory ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
} else {
count + + ;
2002-12-04 02:57:45 +03:00
}
} else {
2005-02-01 03:28:20 +03:00
struct smb_Dir * dir_hnd = NULL ;
2007-09-13 01:48:20 +04:00
const char * dname = NULL ;
2007-01-17 05:09:37 +03:00
long offset = 0 ;
2002-12-04 02:57:45 +03:00
2007-09-13 01:48:20 +04:00
if ( strequal ( mask , " ????????.??? " ) ) {
mask [ 0 ] = ' * ' ;
mask [ 1 ] = ' \0 ' ;
}
2005-06-25 07:03:44 +04:00
2007-01-17 05:09:37 +03:00
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
2007-01-17 05:09:37 +03:00
}
2007-09-13 01:48:20 +04:00
2007-01-17 05:09:37 +03:00
dir_hnd = OpenDir ( conn , directory , mask , 0 ) ;
if ( dir_hnd = = NULL ) {
status = map_nt_error_from_unix ( errno ) ;
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
2007-01-17 05:09:37 +03:00
}
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
error = ERRbadfile ;
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
while ( ( dname = ReadDirName ( dir_hnd , & offset ) ) ) {
2007-09-13 01:48:20 +04:00
char * destname = NULL ;
char * fname = NULL ;
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
continue ;
}
2007-01-17 05:09:37 +03:00
if ( ! is_visible_file ( conn , directory , dname , & sbuf1 , False ) ) {
continue ;
}
2005-02-01 21:33:50 +03:00
2007-09-13 01:48:20 +04:00
if ( ! mask_match ( dname , mask , conn - > case_sensitive ) ) {
2007-01-17 05:09:37 +03:00
continue ;
}
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
error = ERRnoaccess ;
2007-09-13 01:48:20 +04:00
fname = talloc_asprintf ( ctx ,
" %s/%s " ,
directory ,
dname ) ;
if ( ! fname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBcopy ) ;
return ;
}
if ( ! resolve_wildcards ( ctx ,
fname , newname , & destname ) ) {
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
if ( ! destname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBcopy ) ;
return ;
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = check_name ( conn , destname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBcopy ) ;
return ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
DEBUG ( 3 , ( " reply_copy : doing copy on %s -> %s \n " , fname , destname ) ) ;
2007-09-13 01:48:20 +04:00
status = copy_file ( ctx , conn , fname , destname , ofun ,
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
count , target_is_directory ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2007-01-17 05:09:37 +03:00
count + + ;
2002-12-04 02:57:45 +03:00
}
2007-09-13 01:48:20 +04:00
TALLOC_FREE ( fname ) ;
TALLOC_FREE ( destname ) ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 05:09:37 +03:00
CloseDir ( dir_hnd ) ;
2002-12-04 02:57:45 +03:00
}
2007-09-13 01:48:20 +04:00
2002-12-04 02:57:45 +03:00
if ( count = = 0 ) {
if ( err ) {
/* Error on close... */
errno = err ;
2007-08-15 01:21:52 +04:00
reply_unixerror ( req , ERRHRD , ERRgeneral ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-08-15 01:21:52 +04:00
reply_doserror ( req , ERRDOS , error ) ;
2007-01-13 02:47:16 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2007-08-15 01:21:52 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , count ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
2001-07-02 06:42:41 +04:00
/****************************************************************************
Get a lock pid , dealing with large count requests .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
uint32 get_lock_pid ( char * data , int data_offset , bool large_file_format )
2001-07-02 06:42:41 +04:00
{
if ( ! large_file_format )
2006-07-11 22:01:26 +04:00
return ( uint32 ) SVAL ( data , SMB_LPID_OFFSET ( data_offset ) ) ;
2001-07-02 06:42:41 +04:00
else
2006-07-11 22:01:26 +04:00
return ( uint32 ) SVAL ( data , SMB_LARGE_LPID_OFFSET ( data_offset ) ) ;
2001-07-02 06:42:41 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Get a lock count , dealing with large count requests .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
SMB_BIG_UINT get_lock_count ( char * data , int data_offset , bool large_file_format )
1999-12-13 16:27:58 +03:00
{
2002-12-04 02:57:45 +03:00
SMB_BIG_UINT count = 0 ;
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
if ( ! large_file_format ) {
count = ( SMB_BIG_UINT ) IVAL ( data , SMB_LKLEN_OFFSET ( data_offset ) ) ;
} else {
1999-12-13 16:27:58 +03:00
2000-04-11 23:44:54 +04:00
# if defined(HAVE_LONGLONG)
2002-12-04 02:57:45 +03:00
count = ( ( ( SMB_BIG_UINT ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_HIGH ( data_offset ) ) ) < < 32 ) |
( ( SMB_BIG_UINT ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_LOW ( data_offset ) ) ) ;
2000-04-11 23:44:54 +04:00
# else /* HAVE_LONGLONG */
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
/*
* NT4 . x seems to be broken in that it sends large file ( 64 bit )
* lockingX calls even if the CAP_LARGE_FILES was * not *
* negotiated . For boxes without large unsigned ints truncate the
* lock count by dropping the top 32 bits .
*/
if ( IVAL ( data , SMB_LARGE_LKLEN_OFFSET_HIGH ( data_offset ) ) ! = 0 ) {
DEBUG ( 3 , ( " get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count. \n " ,
( unsigned int ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_HIGH ( data_offset ) ) ,
( unsigned int ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_LOW ( data_offset ) ) ) ) ;
SIVAL ( data , SMB_LARGE_LKLEN_OFFSET_HIGH ( data_offset ) , 0 ) ;
}
count = ( SMB_BIG_UINT ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_LOW ( data_offset ) ) ;
2000-04-11 23:44:54 +04:00
# endif /* HAVE_LONGLONG */
2002-12-04 02:57:45 +03:00
}
2000-04-11 23:44:54 +04:00
2002-12-04 02:57:45 +03:00
return count ;
1999-12-13 16:27:58 +03:00
}
2001-09-08 00:01:19 +04:00
# if !defined(HAVE_LONGLONG)
2001-09-07 02:43:21 +04:00
/****************************************************************************
Pathetically try and map a 64 bit lock offset into 31 bits . I hate Windows : - ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2001-09-07 02:43:21 +04:00
static uint32 map_lock_offset ( uint32 high , uint32 low )
{
unsigned int i ;
uint32 mask = 0 ;
uint32 highcopy = high ;
/*
* Try and find out how many significant bits there are in high .
*/
for ( i = 0 ; highcopy ; i + + )
highcopy > > = 1 ;
/*
* We use 31 bits not 32 here as POSIX
* lock offsets may not be negative .
*/
mask = ( ~ 0 ) < < ( 31 - i ) ;
if ( low & mask )
return 0 ; /* Fail. */
high < < = ( 31 - i ) ;
return ( high | low ) ;
}
2001-09-08 00:01:19 +04:00
# endif /* !defined(HAVE_LONGLONG) */
2001-09-07 02:43:21 +04:00
1999-12-13 16:27:58 +03:00
/****************************************************************************
Get a lock offset , dealing with large offset requests .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
SMB_BIG_UINT get_lock_offset ( char * data , int data_offset , bool large_file_format , bool * err )
1999-12-13 16:27:58 +03:00
{
2002-12-04 02:57:45 +03:00
SMB_BIG_UINT offset = 0 ;
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
* err = False ;
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
if ( ! large_file_format ) {
offset = ( SMB_BIG_UINT ) IVAL ( data , SMB_LKOFF_OFFSET ( data_offset ) ) ;
} else {
1999-12-13 16:27:58 +03:00
2000-04-11 23:44:54 +04:00
# if defined(HAVE_LONGLONG)
2002-12-04 02:57:45 +03:00
offset = ( ( ( SMB_BIG_UINT ) IVAL ( data , SMB_LARGE_LKOFF_OFFSET_HIGH ( data_offset ) ) ) < < 32 ) |
( ( SMB_BIG_UINT ) IVAL ( data , SMB_LARGE_LKOFF_OFFSET_LOW ( data_offset ) ) ) ;
2000-04-11 23:44:54 +04:00
# else /* HAVE_LONGLONG */
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
/*
* NT4 . x seems to be broken in that it sends large file ( 64 bit )
* lockingX calls even if the CAP_LARGE_FILES was * not *
* negotiated . For boxes without large unsigned ints mangle the
* lock offset by mapping the top 32 bits onto the lower 32.
*/
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
if ( IVAL ( data , SMB_LARGE_LKOFF_OFFSET_HIGH ( data_offset ) ) ! = 0 ) {
uint32 low = IVAL ( data , SMB_LARGE_LKOFF_OFFSET_LOW ( data_offset ) ) ;
uint32 high = IVAL ( data , SMB_LARGE_LKOFF_OFFSET_HIGH ( data_offset ) ) ;
uint32 new_low = 0 ;
if ( ( new_low = map_lock_offset ( high , low ) ) = = 0 ) {
* err = True ;
return ( SMB_BIG_UINT ) - 1 ;
}
DEBUG ( 3 , ( " get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x. \n " ,
( unsigned int ) high , ( unsigned int ) low , ( unsigned int ) new_low ) ) ;
SIVAL ( data , SMB_LARGE_LKOFF_OFFSET_HIGH ( data_offset ) , 0 ) ;
SIVAL ( data , SMB_LARGE_LKOFF_OFFSET_LOW ( data_offset ) , new_low ) ;
}
offset = ( SMB_BIG_UINT ) IVAL ( data , SMB_LARGE_LKOFF_OFFSET_LOW ( data_offset ) ) ;
2000-04-13 01:46:22 +04:00
# endif /* HAVE_LONGLONG */
2002-12-04 02:57:45 +03:00
}
2000-04-11 23:44:54 +04:00
2002-12-04 02:57:45 +03:00
return offset ;
1999-12-13 16:27:58 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lockingX request .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-14 14:47:47 +04:00
void reply_lockingX ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-08-14 14:27:27 +04:00
files_struct * fsp ;
unsigned char locktype ;
unsigned char oplocklevel ;
uint16 num_ulocks ;
uint16 num_locks ;
2001-08-27 12:19:43 +04:00
SMB_BIG_UINT count = 0 , offset = 0 ;
2006-07-11 22:01:26 +04:00
uint32 lock_pid ;
2007-08-14 14:27:27 +04:00
int32 lock_timeout ;
2001-08-27 12:19:43 +04:00
int i ;
char * data ;
2007-10-19 04:40:25 +04:00
bool large_file_format ;
bool err ;
2005-11-02 03:19:26 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
1999-12-13 16:27:58 +03:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBlockingX ) ;
2007-08-14 14:27:27 +04:00
2007-08-14 17:38:14 +04:00
if ( req - > wct < 8 ) {
2007-08-14 14:47:47 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
2007-08-14 14:27:27 +04:00
}
2001-08-27 12:19:43 +04:00
2007-08-14 17:38:14 +04:00
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv2 ) ) ;
locktype = CVAL ( req - > inbuf , smb_vwv3 ) ;
oplocklevel = CVAL ( req - > inbuf , smb_vwv3 + 1 ) ;
num_ulocks = SVAL ( req - > inbuf , smb_vwv6 ) ;
num_locks = SVAL ( req - > inbuf , smb_vwv7 ) ;
lock_timeout = IVAL ( req - > inbuf , smb_vwv4 ) ;
2007-08-14 14:27:27 +04:00
large_file_format = ( locktype & LOCKING_ANDX_LARGE_FILES ) ? True : False ;
2007-08-14 14:47:47 +04:00
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
2007-08-14 17:38:14 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
}
2001-08-27 12:19:43 +04:00
2007-08-14 17:38:14 +04:00
data = smb_buf ( req - > inbuf ) ;
2002-03-11 04:34:14 +03:00
2004-10-19 02:01:10 +04:00
if ( locktype & LOCKING_ANDX_CHANGE_LOCKTYPE ) {
2002-03-11 04:34:14 +03:00
/* we don't support these - and CANCEL_LOCK makes w2k
and XP reboot so I don ' t really want to be
compatible ! ( tridge ) */
2007-08-14 14:47:47 +04:00
reply_nterror ( req , NT_STATUS_DOS ( ERRDOS , ERRnoatomiclocks ) ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
2002-03-11 04:34:14 +03:00
}
2001-08-27 12:19:43 +04:00
/* Check if this is an oplock break on a file
we have granted an oplock on .
*/
if ( ( locktype & LOCKING_ANDX_OPLOCK_RELEASE ) ) {
/* Client can insist on breaking to none. */
2007-10-19 04:40:25 +04:00
bool break_to_none = ( oplocklevel = = 0 ) ;
bool result ;
2005-09-30 21:13:37 +04:00
DEBUG ( 5 , ( " reply_lockingX: oplock break reply (%u) from client "
" for fnum = %d \n " , ( unsigned int ) oplocklevel ,
fsp - > fnum ) ) ;
1999-12-13 16:27:58 +03:00
2001-08-27 12:19:43 +04:00
/*
2005-09-30 21:13:37 +04:00
* Make sure we have granted an exclusive or batch oplock on
* this file .
2001-08-27 12:19:43 +04:00
*/
2005-09-30 21:13:37 +04:00
if ( fsp - > oplock_type = = 0 ) {
2006-04-10 22:44:27 +04:00
/* The Samba4 nbench simulator doesn't understand
the difference between break to level2 and break
to none from level2 - it sends oplock break
replies in both cases . Don ' t keep logging an error
message here - just ignore it . JRA . */
DEBUG ( 5 , ( " reply_lockingX: Error : oplock break from "
2005-09-30 21:13:37 +04:00
" client for fnum = %d (oplock=%d) and no "
" oplock granted on this file (%s). \n " ,
fsp - > fnum , fsp - > oplock_type , fsp - > fsp_name ) ) ;
/* if this is a pure oplock break request then don't
* send a reply */
2001-08-27 12:19:43 +04:00
if ( num_locks = = 0 & & num_ulocks = = 0 ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
} else {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_doserror ( req , ERRDOS , ERRlock ) ;
return ;
2001-08-27 12:19:43 +04:00
}
}
1998-09-11 05:24:30 +04:00
2005-09-30 21:13:37 +04:00
if ( ( fsp - > sent_oplock_break = = BREAK_TO_NONE_SENT ) | |
( break_to_none ) ) {
result = remove_oplock ( fsp ) ;
} else {
result = downgrade_oplock ( fsp ) ;
2001-08-27 12:19:43 +04:00
}
2005-09-30 21:13:37 +04:00
if ( ! result ) {
DEBUG ( 0 , ( " reply_lockingX: error in removing "
" oplock on file %s \n " , fsp - > fsp_name ) ) ;
/* Hmmm. Is this panic justified? */
smb_panic ( " internal tdb error " ) ;
}
reply_to_oplock_break_requests ( fsp ) ;
/* if this is a pure oplock break request then don't send a
* reply */
2001-08-27 12:19:43 +04:00
if ( num_locks = = 0 & & num_ulocks = = 0 ) {
/* Sanity check - ensure a pure oplock break is not a
chained request . */
2007-08-14 17:38:14 +04:00
if ( CVAL ( req - > inbuf , smb_vwv0 ) ! = 0xff )
2005-09-30 21:13:37 +04:00
DEBUG ( 0 , ( " reply_lockingX: Error : pure oplock "
" break is a chained %d request ! \n " ,
2007-08-14 17:38:14 +04:00
( unsigned int ) CVAL ( req - > inbuf ,
smb_vwv0 ) ) ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
}
1999-12-13 16:27:58 +03:00
2001-08-27 12:19:43 +04:00
/*
* We do this check * after * we have checked this is not a oplock break
* response message . JRA .
*/
release_level_2_oplocks_on_change ( fsp ) ;
2007-08-14 17:38:14 +04:00
if ( smb_buflen ( req - > inbuf ) <
( num_ulocks + num_locks ) * ( large_file_format ? 20 : 10 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
2001-08-27 12:19:43 +04:00
/* Data now points at the beginning of the list
of smb_unlkrng structs */
for ( i = 0 ; i < ( int ) num_ulocks ; i + + ) {
lock_pid = get_lock_pid ( data , i , large_file_format ) ;
count = get_lock_count ( data , i , large_file_format ) ;
offset = get_lock_offset ( data , i , large_file_format , & err ) ;
/*
* There is no error code marked " stupid client bug " . . . . : - ) .
*/
if ( err ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2001-08-27 12:19:43 +04:00
}
1998-09-11 05:24:30 +04:00
2005-09-30 21:13:37 +04:00
DEBUG ( 10 , ( " reply_lockingX: unlock start=%.0f, len=%.0f for "
" pid %u, file %s \n " , ( double ) offset , ( double ) count ,
( unsigned int ) lock_pid , fsp - > fsp_name ) ) ;
2001-08-27 12:19:43 +04:00
2007-05-14 17:01:28 +04:00
status = do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2006-04-10 19:33:04 +04:00
lock_pid ,
count ,
offset ,
WINDOWS_LOCK ) ;
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_V ( status ) ) {
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_nterror ( req , status ) ;
return ;
2001-08-27 12:19:43 +04:00
}
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
/* Setup the timeout in seconds. */
2002-03-13 23:28:19 +03:00
2006-07-18 05:05:51 +04:00
if ( ! lp_blocking_locks ( SNUM ( conn ) ) ) {
2006-07-18 01:09:02 +04:00
lock_timeout = 0 ;
}
2001-08-27 12:19:43 +04:00
/* Now do any requested locks */
data + = ( ( large_file_format ? 20 : 10 ) * num_ulocks ) ;
/* Data now points at the beginning of the list
of smb_lkrng structs */
for ( i = 0 ; i < ( int ) num_locks ; i + + ) {
2006-07-18 01:09:02 +04:00
enum brl_type lock_type = ( ( locktype & LOCKING_ANDX_SHARED_LOCK ) ?
READ_LOCK : WRITE_LOCK ) ;
2001-08-27 12:19:43 +04:00
lock_pid = get_lock_pid ( data , i , large_file_format ) ;
count = get_lock_count ( data , i , large_file_format ) ;
offset = get_lock_offset ( data , i , large_file_format , & err ) ;
/*
* There is no error code marked " stupid client bug " . . . . : - ) .
*/
if ( err ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2001-08-27 12:19:43 +04:00
}
2005-09-30 21:13:37 +04:00
DEBUG ( 10 , ( " reply_lockingX: lock start=%.0f, len=%.0f for pid "
" %u, file %s timeout = %d \n " , ( double ) offset ,
( double ) count , ( unsigned int ) lock_pid ,
fsp - > fsp_name , ( int ) lock_timeout ) ) ;
2001-08-27 12:19:43 +04:00
2006-07-18 01:09:02 +04:00
if ( locktype & LOCKING_ANDX_CANCEL_LOCK ) {
if ( lp_blocking_locks ( SNUM ( conn ) ) ) {
/* Schedule a message to ourselves to
remove the blocking lock record and
return the right error . */
if ( ! blocking_lock_cancel ( fsp ,
lock_pid ,
offset ,
count ,
WINDOWS_LOCK ,
locktype ,
NT_STATUS_FILE_LOCK_CONFLICT ) ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_nterror (
req ,
NT_STATUS_DOS (
ERRDOS ,
ERRcancelviolation ) ) ;
return ;
2006-07-18 01:09:02 +04:00
}
}
/* Remove a matching pending lock. */
status = do_lock_cancel ( fsp ,
lock_pid ,
count ,
offset ,
WINDOWS_LOCK ) ;
} else {
2007-10-19 04:40:25 +04:00
bool blocking_lock = lock_timeout ? True : False ;
bool defer_lock = False ;
2006-07-18 05:05:51 +04:00
struct byte_range_lock * br_lck ;
2007-05-20 00:57:12 +04:00
uint32 block_smbpid ;
2006-07-18 05:05:51 +04:00
2007-05-14 17:01:28 +04:00
br_lck = do_lock ( smbd_messaging_context ( ) ,
fsp ,
2006-04-10 19:33:04 +04:00
lock_pid ,
count ,
offset ,
lock_type ,
WINDOWS_LOCK ,
2006-07-18 05:05:51 +04:00
blocking_lock ,
2007-05-20 00:57:12 +04:00
& status ,
& block_smbpid ) ;
2006-04-10 19:33:04 +04:00
2006-07-18 05:05:51 +04:00
if ( br_lck & & blocking_lock & & ERROR_WAS_LOCK_DENIED ( status ) ) {
2006-07-18 05:17:54 +04:00
/* Windows internal resolution for blocking locks seems
to be about 200 ms . . . Don ' t wait for less than that . JRA . */
2006-07-18 05:29:43 +04:00
if ( lock_timeout ! = - 1 & & lock_timeout < lp_lock_spin_time ( ) ) {
lock_timeout = lp_lock_spin_time ( ) ;
2006-07-18 05:17:54 +04:00
}
2006-07-18 05:05:51 +04:00
defer_lock = True ;
}
/* This heuristic seems to match W2K3 very well. If a
lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
it pretends we asked for a timeout of between 150 - 300 milliseconds as
far as I can tell . Replacement for do_lock_spin ( ) . JRA . */
if ( br_lck & & lp_blocking_locks ( SNUM ( conn ) ) & & ! blocking_lock & &
NT_STATUS_EQUAL ( ( status ) , NT_STATUS_FILE_LOCK_CONFLICT ) ) {
defer_lock = True ;
2006-07-18 05:29:43 +04:00
lock_timeout = lp_lock_spin_time ( ) ;
2006-07-18 05:05:51 +04:00
}
if ( br_lck & & defer_lock ) {
2001-08-27 12:19:43 +04:00
/*
2006-07-18 05:05:51 +04:00
* A blocking lock was requested . Package up
* this smb into a queued request and push it
* onto the blocking lock queue .
2001-08-27 12:19:43 +04:00
*/
2006-07-18 05:05:51 +04:00
if ( push_blocking_lock_request ( br_lck ,
2007-08-14 17:38:14 +04:00
( char * ) req - > inbuf ,
smb_len ( req - > inbuf ) + 4 ,
2006-07-18 05:05:51 +04:00
fsp ,
lock_timeout ,
i ,
lock_pid ,
lock_type ,
WINDOWS_LOCK ,
offset ,
2007-05-20 00:57:12 +04:00
count ,
block_smbpid ) ) {
2006-07-18 05:05:51 +04:00
TALLOC_FREE ( br_lck ) ;
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
}
2006-07-18 05:05:51 +04:00
TALLOC_FREE ( br_lck ) ;
2006-07-18 01:09:02 +04:00
}
if ( NT_STATUS_V ( status ) ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_nterror ( req , status ) ;
return ;
2001-08-27 12:19:43 +04:00
}
}
/* If any of the above locks failed, then we must unlock
all of the previous locks ( X / Open spec ) . */
2006-07-18 01:09:02 +04:00
if ( ! ( locktype & LOCKING_ANDX_CANCEL_LOCK ) & &
( i ! = num_locks ) & &
( num_locks ! = 0 ) ) {
2001-08-27 12:19:43 +04:00
/*
* Ensure we don ' t do a remove on the lock that just failed ,
* as under POSIX rules , if we have a lock already there , we
* will delete it ( and we shouldn ' t ) . . . . .
*/
for ( i - - ; i > = 0 ; i - - ) {
lock_pid = get_lock_pid ( data , i , large_file_format ) ;
count = get_lock_count ( data , i , large_file_format ) ;
2005-09-30 21:13:37 +04:00
offset = get_lock_offset ( data , i , large_file_format ,
& err ) ;
2001-08-27 12:19:43 +04:00
/*
2005-09-30 21:13:37 +04:00
* There is no error code marked " stupid client
* bug " .... :-).
2001-08-27 12:19:43 +04:00
*/
if ( err ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2001-08-27 12:19:43 +04:00
}
2007-05-14 17:01:28 +04:00
do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2006-04-10 19:33:04 +04:00
lock_pid ,
count ,
offset ,
WINDOWS_LOCK ) ;
2001-08-27 12:19:43 +04:00
}
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_nterror ( req , status ) ;
return ;
2001-08-27 12:19:43 +04:00
}
1998-09-11 05:24:30 +04:00
2007-08-14 17:38:14 +04:00
reply_outbuf ( req , 2 , 0 ) ;
2001-08-27 12:19:43 +04:00
2005-09-30 21:13:37 +04:00
DEBUG ( 3 , ( " lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d \n " ,
fsp - > fnum , ( unsigned int ) locktype , num_locks , num_ulocks ) ) ;
2001-08-27 12:19:43 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBreadbmpx ( read block multiplex ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-19 04:56:03 +04:00
2007-08-15 13:52:09 +04:00
void reply_readbmpx ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-10-19 04:56:03 +04:00
START_PROFILE ( SMBreadBmpx ) ;
2007-08-15 13:52:09 +04:00
reply_doserror ( req , ERRSRV , ERRuseSTD ) ;
END_PROFILE ( SMBreadBmpx ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2007-08-15 13:52:09 +04:00
/****************************************************************************
Reply to a SMBreadbs ( read block multiplex secondary ) request .
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
2007-08-15 13:52:09 +04:00
void reply_readbs ( connection_struct * conn , struct smb_request * req )
{
START_PROFILE ( SMBreadBs ) ;
reply_doserror ( req , ERRSRV , ERRuseSTD ) ;
END_PROFILE ( SMBreadBs ) ;
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBsetattrE .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-15 00:55:24 +04:00
void reply_setattrE ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2007-03-06 02:40:03 +03:00
struct timespec ts [ 2 ] ;
2007-08-15 00:55:24 +04:00
files_struct * fsp ;
2002-03-20 03:46:53 +03:00
START_PROFILE ( SMBsetattrE ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
if ( req - > wct < 7 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsetattrE ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
2007-08-15 00:55:24 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
2005-12-26 14:44:15 +03:00
END_PROFILE ( SMBsetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
2002-03-20 03:46:53 +03:00
/*
* Convert the DOS times into unix times . Ignore create
* time as UNIX can ' t set this .
*/
2007-08-15 00:55:24 +04:00
ts [ 0 ] = convert_time_t_to_timespec (
srv_make_unix_date2 ( req - > inbuf + smb_vwv3 ) ) ; /* atime. */
ts [ 1 ] = convert_time_t_to_timespec (
srv_make_unix_date2 ( req - > inbuf + smb_vwv5 ) ) ; /* mtime. */
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2002-03-20 03:46:53 +03:00
/*
* Patch from Ray Frush < frush @ engr . colostate . edu >
* Sometimes times are sent as zero - ignore them .
*/
1997-09-23 23:19:06 +04:00
2007-03-06 02:40:03 +03:00
if ( null_timespec ( ts [ 0 ] ) & & null_timespec ( ts [ 1 ] ) ) {
2002-03-20 03:46:53 +03:00
/* Ignore request */
if ( DEBUGLVL ( 3 ) ) {
dbgtext ( " reply_setattrE fnum=%d " , fsp - > fnum ) ;
dbgtext ( " ignoring zero request - not setting timestamps of 0 \n " ) ;
}
END_PROFILE ( SMBsetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2007-03-06 02:40:03 +03:00
} else if ( ! null_timespec ( ts [ 0 ] ) & & null_timespec ( ts [ 1 ] ) ) {
2005-03-10 04:30:14 +03:00
/* set modify time = to access time if modify time was unset */
2007-03-06 02:40:03 +03:00
ts [ 1 ] = ts [ 0 ] ;
2002-03-20 03:46:53 +03:00
}
1997-09-23 23:19:06 +04:00
2002-03-20 03:46:53 +03:00
/* Set the date on this file */
2005-03-10 04:30:14 +03:00
/* Should we set pending modtime here ? JRA */
2007-03-06 02:40:03 +03:00
if ( file_ntimes ( conn , fsp - > fsp_name , ts ) ) {
2007-08-15 00:55:24 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBsetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2007-03-06 02:40:03 +03:00
DEBUG ( 3 , ( " reply_setattrE fnum=%d actime=%u modtime=%u \n " ,
fsp - > fnum ,
( unsigned int ) ts [ 0 ] . tv_sec ,
( unsigned int ) ts [ 1 ] . tv_sec ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBsetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2001-10-19 04:56:03 +04:00
/* Back from the dead for OS/2..... JRA. */
/****************************************************************************
Reply to a SMBwritebmpx ( write block multiplex primary ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
2001-10-19 04:56:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-15 13:52:09 +04:00
void reply_writebmpx ( connection_struct * conn , struct smb_request * req )
2001-10-19 04:56:03 +04:00
{
START_PROFILE ( SMBwriteBmpx ) ;
2007-08-15 13:52:09 +04:00
reply_doserror ( req , ERRSRV , ERRuseSTD ) ;
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBmpx ) ;
2007-08-15 13:52:09 +04:00
return ;
2001-10-19 04:56:03 +04:00
}
/****************************************************************************
Reply to a SMBwritebs ( write block multiplex secondary ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
2001-10-19 04:56:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-15 13:52:09 +04:00
void reply_writebs ( connection_struct * conn , struct smb_request * req )
2001-10-19 04:56:03 +04:00
{
START_PROFILE ( SMBwriteBs ) ;
2007-08-15 13:52:09 +04:00
reply_doserror ( req , ERRSRV , ERRuseSTD ) ;
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBs ) ;
2007-08-15 13:52:09 +04:00
return ;
2001-10-19 04:56:03 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBgetattrE .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-15 00:55:24 +04:00
void reply_getattrE ( connection_struct * conn , struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-03-20 03:46:53 +03:00
SMB_STRUCT_STAT sbuf ;
int mode ;
2007-08-15 00:55:24 +04:00
files_struct * fsp ;
2002-03-20 03:46:53 +03:00
START_PROFILE ( SMBgetattrE ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBgetattrE ) ;
return ;
}
fsp = file_fsp ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
2007-08-15 00:55:24 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
/* Do an fstat on this file */
if ( fsp_stat ( fsp , & sbuf ) ) {
2007-08-15 00:55:24 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
mode = dos_mode ( conn , fsp - > fsp_name , & sbuf ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
/*
* Convert the times into dos times . Set create
* date to be last modify date as UNIX doesn ' t save
* this .
*/
2007-08-15 00:55:24 +04:00
reply_outbuf ( req , 11 , 0 ) ;
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv0 ,
get_create_time ( & sbuf ,
lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv2 , sbuf . st_atime ) ;
2005-03-10 04:30:14 +03:00
/* Should we check pending modtime here ? JRA */
2007-08-15 00:55:24 +04:00
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv4 , sbuf . st_mtime ) ;
2002-03-20 03:46:53 +03:00
if ( mode & aDIR ) {
2007-08-15 00:55:24 +04:00
SIVAL ( req - > outbuf , smb_vwv6 , 0 ) ;
SIVAL ( req - > outbuf , smb_vwv8 , 0 ) ;
2002-03-20 03:46:53 +03:00
} else {
2005-03-03 07:03:36 +03:00
uint32 allocation_size = get_allocation_size ( conn , fsp , & sbuf ) ;
2007-08-15 00:55:24 +04:00
SIVAL ( req - > outbuf , smb_vwv6 , ( uint32 ) sbuf . st_size ) ;
SIVAL ( req - > outbuf , smb_vwv8 , allocation_size ) ;
2002-03-20 03:46:53 +03:00
}
2007-08-15 00:55:24 +04:00
SSVAL ( req - > outbuf , smb_vwv10 , mode ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
DEBUG ( 3 , ( " reply_getattrE fnum=%d \n " , fsp - > fnum ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}