1996-05-04 11:50:46 +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.
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
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
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_send ;
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 ;
2001-09-26 17:55:59 +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-01-13 02:47:16 +03:00
NTSTATUS check_path_syntax_internal ( pstring destname ,
2007-01-13 23:26:53 +03:00
const pstring srcname ,
2007-03-12 20:55:24 +03:00
BOOL posix_path ,
2007-01-13 23:26:53 +03:00
BOOL * p_last_component_contains_wcard )
2005-03-25 01:32:52 +03:00
{
char * d = destname ;
const char * s = srcname ;
NTSTATUS ret = NT_STATUS_OK ;
BOOL start_of_name_component = True ;
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 + + ;
}
if ( ( d ! = destname ) & & ( * s ! = ' \0 ' ) ) {
/* 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 */
if ( ( d > destname ) & & ( * ( d - 1 ) = = ' / ' ) ) {
* ( d - 1 ) = ' \0 ' ;
d - - ;
}
/* Are we at the start ? Can't go back further if so. */
if ( d < = destname ) {
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. */
for ( d - - ; d > destname ; d - - ) {
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-01-13 02:47:16 +03:00
NTSTATUS check_path_syntax ( pstring destname , const pstring srcname )
2005-05-06 17:26:54 +04:00
{
2007-01-13 23:26:53 +03:00
BOOL ignore ;
2007-03-12 20:55:24 +03:00
return check_path_syntax_internal ( destname , srcname , 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-01-13 02:47:16 +03:00
NTSTATUS check_path_syntax_wcard ( pstring destname , const pstring srcname , BOOL * p_contains_wcard )
{
2007-03-12 20:55:24 +03:00
return check_path_syntax_internal ( destname , srcname , 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-03-12 20:55:24 +03:00
NTSTATUS check_path_syntax_posix ( pstring destname , const pstring srcname )
2007-01-13 02:47:16 +03:00
{
2007-01-13 23:26:53 +03:00
BOOL ignore ;
2007-03-12 20:55:24 +03:00
return check_path_syntax_internal ( destname , srcname , 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
size_t srvstr_get_path_wcard ( char * inbuf , char * dest , const char * src , size_t dest_len , size_t src_len , int flags ,
NTSTATUS * err , BOOL * contains_wcard )
{
pstring tmppath ;
char * tmppath_ptr = tmppath ;
size_t ret ;
# ifdef DEVELOPER
SMB_ASSERT ( dest_len = = sizeof ( pstring ) ) ;
# endif
if ( src_len = = 0 ) {
ret = srvstr_pull_buf ( inbuf , tmppath_ptr , src , dest_len , flags ) ;
} else {
ret = srvstr_pull ( inbuf , tmppath_ptr , src , dest_len , src_len , flags ) ;
}
* contains_wcard = False ;
2007-03-12 20:55:24 +03:00
if ( SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES ) {
/*
* For a DFS path the function parse_dfs_path ( )
* will do the path processing , just make a copy .
*/
pstrcpy ( dest , tmppath ) ;
* err = NT_STATUS_OK ;
return ret ;
}
2005-10-31 23:11:58 +03:00
if ( lp_posix_pathnames ( ) ) {
* err = check_path_syntax_posix ( dest , tmppath ) ;
} else {
* err = check_path_syntax_wcard ( dest , tmppath , contains_wcard ) ;
}
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-10-31 23:11:58 +03:00
size_t srvstr_get_path ( char * inbuf , char * dest , const char * src , size_t dest_len , size_t src_len , int flags , NTSTATUS * err )
2003-10-09 03:21:36 +04:00
{
2004-03-03 23:55:59 +03:00
pstring tmppath ;
char * tmppath_ptr = tmppath ;
2004-03-09 18:29:16 +03:00
size_t ret ;
2004-03-03 23:55:59 +03:00
# ifdef DEVELOPER
SMB_ASSERT ( dest_len = = sizeof ( pstring ) ) ;
# endif
if ( src_len = = 0 ) {
ret = srvstr_pull_buf ( inbuf , tmppath_ptr , src , dest_len , flags ) ;
} else {
ret = srvstr_pull ( inbuf , tmppath_ptr , src , dest_len , src_len , flags ) ;
}
2007-03-12 20:55:24 +03:00
if ( SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES ) {
/*
* For a DFS path the function parse_dfs_path ( )
* will do the path processing , just make a copy .
*/
pstrcpy ( dest , tmppath ) ;
* err = NT_STATUS_OK ;
return ret ;
}
2005-06-23 01:20:41 +04:00
if ( lp_posix_pathnames ( ) ) {
* err = check_path_syntax_posix ( dest , tmppath ) ;
2005-03-25 01:32:52 +03:00
} else {
* err = check_path_syntax ( dest , tmppath ) ;
}
2006-07-11 22:01:26 +04:00
2003-10-09 03:21:36 +04:00
return ret ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2003-06-13 21:49:03 +04:00
Reply to a special message .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
int reply_special ( char * inbuf , char * outbuf )
{
1997-09-18 11:05:43 +04:00
int outsize = 4 ;
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 ;
1997-09-18 11:05:43 +04:00
2002-08-17 19:27:10 +04:00
static BOOL already_got_session = False ;
1997-09-18 11:05:43 +04:00
* name1 = * name2 = 0 ;
1999-12-13 16:27:58 +03:00
memset ( outbuf , ' \0 ' , smb_size ) ;
1998-08-04 05:01:26 +04:00
2007-04-20 02:40:32 +04:00
smb_setlen ( inbuf , 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 " ) ) ;
return ( 0 ) ;
}
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 :
return ( 0 ) ;
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 ) ) ;
1997-09-18 11:05:43 +04:00
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_tcon ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-08-17 19:27:10 +04:00
const char * service ;
pstring service_buf ;
1998-08-14 21:38:29 +04:00
pstring password ;
pstring dev ;
int outsize = 0 ;
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
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 ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBtcon ) ;
1998-08-14 21:38:29 +04:00
2002-08-17 19:27:10 +04:00
* service_buf = * password = * dev = 0 ;
1998-08-14 21:38:29 +04:00
2001-03-13 09:55:47 +03:00
p = smb_buf ( inbuf ) + 1 ;
2003-03-18 14:22:52 +03:00
p + = srvstr_pull_buf ( inbuf , service_buf , p , sizeof ( service_buf ) , STR_TERMINATE ) + 1 ;
2002-07-15 14:35:28 +04:00
pwlen = srvstr_pull_buf ( inbuf , password , p , sizeof ( password ) , STR_TERMINATE ) + 1 ;
2001-10-31 13:46:25 +03:00
p + = pwlen ;
2002-07-15 14:35:28 +04:00
p + = srvstr_pull_buf ( inbuf , dev , p , sizeof ( dev ) , STR_TERMINATE ) + 1 ;
1998-08-14 21:38:29 +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 ) ;
conn = make_connection ( service , password_blob , dev , 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 ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( ! conn ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
2001-09-24 03:07:53 +04:00
return ERROR_NT ( nt_status ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 2 , 0 , True ) ;
1998-08-14 21:38:29 +04:00
SSVAL ( outbuf , smb_vwv0 , max_recv ) ;
SSVAL ( outbuf , smb_vwv1 , conn - > cnum ) ;
SSVAL ( outbuf , smb_tid , conn - > cnum ) ;
1996-05-04 11:50:46 +04:00
2001-09-15 16:55:59 +04:00
DEBUG ( 3 , ( " tcon service=%s cnum=%d \n " ,
service , conn - > cnum ) ) ;
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_tcon_and_X ( connection_struct * conn , char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
2000-04-22 12:28:22 +04:00
fstring service ;
2001-10-31 13:46:25 +03:00
DATA_BLOB password ;
2003-03-28 01:27:53 +03:00
/* what the cleint thinks the device is */
fstring client_devicetype ;
/* what the server tells the client the share represents */
const char * server_devicetype ;
2001-09-24 03:07:53 +04:00
NTSTATUS nt_status ;
1998-08-14 21:38:29 +04:00
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
int passlen = SVAL ( inbuf , smb_vwv3 ) ;
2001-03-10 14:38:27 +03:00
pstring path ;
char * p , * q ;
2007-04-07 09:49:24 +04:00
uint16 tcon_flags = SVAL ( inbuf , smb_vwv2 ) ;
2003-03-28 01:27:53 +03:00
2001-10-31 13:46:25 +03:00
START_PROFILE ( SMBtconX ) ;
2003-03-28 01:27:53 +03:00
* service = * client_devicetype = 0 ;
1998-06-10 23:45:13 +04:00
1998-08-14 21:38:29 +04:00
/* we might have to close an old one */
if ( ( SVAL ( inbuf , smb_vwv2 ) & 0x1 ) & & conn ) {
close_cnum ( conn , vuid ) ;
}
1998-06-10 23:45:13 +04:00
1998-08-14 21:38:29 +04:00
if ( passlen > MAX_PASS_LEN ) {
2001-10-15 11:50:21 +04:00
return ERROR_DOS ( ERRDOS , ERRbuftoosmall ) ;
1998-08-14 21:38:29 +04:00
}
1999-12-13 16:27:58 +03:00
2001-10-31 13:46:25 +03:00
if ( global_encrypted_passwords_negotiated ) {
password = data_blob ( smb_buf ( 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 .
*/
p = smb_buf ( inbuf ) + passlen + 1 ;
} else {
p = smb_buf ( inbuf ) + passlen ;
}
2001-10-31 13:46:25 +03:00
} else {
password = data_blob ( smb_buf ( inbuf ) , passlen + 1 ) ;
/* Ensure correct termination */
2007-04-17 06:14:28 +04:00
password . data [ passlen ] = 0 ;
p = smb_buf ( inbuf ) + passlen + 1 ;
2001-10-31 13:46:25 +03:00
}
2002-07-15 14:35:28 +04:00
p + = srvstr_pull_buf ( inbuf , path , p , sizeof ( path ) , STR_TERMINATE ) ;
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
*/
if ( * path = = ' \\ ' ) {
q = strchr_m ( path + 2 , ' \\ ' ) ;
if ( ! q ) {
END_PROFILE ( SMBtconX ) ;
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRDOS , ERRnosuchshare ) ) ;
2001-08-22 17:08:01 +04:00
}
fstrcpy ( service , q + 1 ) ;
2000-10-06 07:21:49 +04:00
}
2001-08-22 17:08:01 +04:00
else
fstrcpy ( service , path ) ;
2003-03-28 01:27:53 +03:00
p + = srvstr_pull ( inbuf , client_devicetype , p , sizeof ( client_devicetype ) , 6 , STR_ASCII ) ;
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
2003-03-28 01:27:53 +03:00
conn = make_connection ( service , password , client_devicetype , vuid , & nt_status ) ;
1998-08-14 21:38:29 +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 ) {
END_PROFILE ( SMBtconX ) ;
2001-09-24 03:07:53 +04:00
return ERROR_NT ( nt_status ) ;
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: " ;
2003-03-28 01:27:53 +03:00
else
server_devicetype = " A: " ;
1998-08-14 21:38:29 +04:00
if ( Protocol < PROTOCOL_NT1 ) {
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 2 , 0 , True ) ;
2001-03-13 03:55:19 +03:00
p = smb_buf ( outbuf ) ;
2003-03-28 01:27:53 +03:00
p + = srvstr_push ( outbuf , p , server_devicetype , - 1 ,
2001-07-04 11:15:53 +04:00
STR_TERMINATE | STR_ASCII ) ;
2007-04-20 02:40:32 +04:00
set_message_end ( inbuf , outbuf , p ) ;
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 ) ) ;
2003-03-25 07:14:54 +03: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-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 7 , 0 , True ) ;
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 ;
}
SIVAL ( outbuf , smb_vwv3 , perm1 ) ;
SIVAL ( outbuf , smb_vwv5 , perm2 ) ;
} else {
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 3 , 0 , True ) ;
2007-04-07 09:49:24 +04:00
}
1997-08-31 18:14:22 +04:00
1998-08-14 21:38:29 +04:00
p = smb_buf ( outbuf ) ;
2003-03-28 01:27:53 +03:00
p + = srvstr_push ( outbuf , p , server_devicetype , - 1 ,
2001-07-04 11:15:53 +04:00
STR_TERMINATE | STR_ASCII ) ;
2003-04-23 15:11:02 +04:00
p + = srvstr_push ( outbuf , p , fstype , - 1 ,
2001-07-04 11:15:53 +04:00
STR_TERMINATE ) ;
1998-08-14 21:38:29 +04:00
2007-04-20 02:40:32 +04:00
set_message_end ( inbuf , outbuf , p ) ;
1998-08-14 21:38:29 +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 */
2002-04-10 05:04:13 +04:00
SSVAL ( outbuf , smb_vwv2 , SMB_SUPPORT_SEARCH_BITS |
( lp_csc_policy ( SNUM ( conn ) ) < < 2 ) ) ;
2000-03-09 01:14:30 +03:00
init_dfsroot ( conn , inbuf , outbuf ) ;
1998-08-14 21:38:29 +04:00
}
2000-03-09 01:14:30 +03:00
1996-05-04 11:50:46 +04:00
2001-09-15 16:55:59 +04:00
DEBUG ( 3 , ( " tconX service=%s \n " ,
service ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
/* set the incoming and outgoing tid to the just created one */
SSVAL ( inbuf , smb_tid , conn - > cnum ) ;
SSVAL ( outbuf , smb_tid , conn - > cnum ) ;
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtconX ) ;
1998-08-14 21:38:29 +04:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
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
}
/****************************************************************************
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
1998-08-14 21:38:29 +04:00
int reply_ioctl ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
1999-12-13 16:27:58 +03:00
uint16 device = SVAL ( inbuf , smb_vwv1 ) ;
uint16 function = SVAL ( inbuf , smb_vwv2 ) ;
uint32 ioctl_code = ( device < < 16 ) + function ;
int replysize , outsize ;
char * p ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBioctl ) ;
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 :
replysize = 32 ;
break ;
default :
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBioctl ) ;
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRSRV , ERRnosupport ) ) ;
1999-12-13 16:27:58 +03:00
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 8 , replysize + 1 , True ) ;
1999-12-13 16:27:58 +03:00
SSVAL ( outbuf , smb_vwv1 , replysize ) ; /* Total data bytes returned */
SSVAL ( outbuf , smb_vwv5 , replysize ) ; /* Data bytes this buffer */
SSVAL ( outbuf , smb_vwv6 , 52 ) ; /* Offset to data */
p = smb_buf ( outbuf ) + 1 ; /* Allow for alignment */
2002-09-25 19:19:00 +04:00
switch ( ioctl_code ) {
case IOCTL_QUERY_JOB_INFO :
{
2003-09-09 00:27:28 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
if ( ! fsp ) {
END_PROFILE ( SMBioctl ) ;
return ( UNIXERROR ( ERRDOS , ERRbadfid ) ) ;
}
2002-12-05 07:00:16 +03:00
SSVAL ( p , 0 , fsp - > rap_print_jobid ) ; /* Job number */
2002-11-13 02:20:50 +03:00
srvstr_push ( outbuf , p + 2 , global_myname ( ) , 15 , STR_TERMINATE | STR_ASCII ) ;
2004-05-22 09:01:25 +04:00
if ( conn ) {
srvstr_push ( outbuf , p + 18 , lp_servicename ( SNUM ( conn ) ) , 13 , STR_TERMINATE | STR_ASCII ) ;
}
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 ) ;
1999-12-13 16:27:58 +03:00
return outsize ;
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 ;
}
/****************************************************************************
Reply to a checkpath .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int reply_checkpath ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-09-25 19:19:00 +04:00
int outsize = 0 ;
pstring name ;
SMB_STRUCT_STAT sbuf ;
2003-08-13 07:28:06 +04:00
NTSTATUS status ;
2007-01-14 01:10:18 +03:00
START_PROFILE ( SMBcheckpath ) ;
2001-03-13 06:45:09 +03:00
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , name , smb_buf ( inbuf ) + 1 , sizeof ( name ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
status = map_checkpath_error ( inbuf , status ) ;
2003-08-13 07:28:06 +04:00
return ERROR_NT ( status ) ;
2003-10-09 03:21:36 +04:00
}
2003-08-13 07:28:06 +04:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
END_PROFILE ( SMBcheckpath ) ;
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
goto path_err ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
2007-01-14 01:10:18 +03:00
DEBUG ( 3 , ( " reply_checkpath %s mode=%d \n " , name , ( int ) SVAL ( inbuf , smb_vwv0 ) ) ) ;
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , name , False , NULL , & sbuf ) ;
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-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-01-17 05:09:37 +03:00
return ERROR_BOTH ( NT_STATUS_NOT_A_DIRECTORY , ERRDOS , ERRbadpath ) ;
2002-09-25 19:19:00 +04:00
}
1998-08-01 02:39:15 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1998-08-01 02:39:15 +04:00
2007-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
return outsize ;
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 .
*/
status = map_checkpath_error ( inbuf , status ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
/*
* 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 .
*/
return ERROR_BOTH ( NT_STATUS_OBJECT_NAME_NOT_FOUND , ERRDOS , ERRbadpath ) ;
}
return ERROR_NT ( 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
1998-08-14 21:38:29 +04:00
int reply_getatr ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring fname ;
int outsize = 0 ;
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 ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBgetatr ) ;
p = smb_buf ( inbuf ) + 1 ;
2005-10-31 23:11:58 +03:00
p + = srvstr_get_path ( inbuf , fname , p , sizeof ( fname ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBgetatr ) ;
return ERROR_NT ( status ) ;
}
2002-12-04 02:57:45 +03:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBgetatr ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03: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-01-14 01:22:32 +03: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-01-13 02:47:16 +03:00
status = unix_convert ( conn , fname , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBgetatr ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
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-01-14 01:22:32 +03:00
END_PROFILE ( SMBgetatr ) ;
2007-01-17 05:09:37 +03:00
return ERROR_NT ( status ) ;
}
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-01-14 01:22:32 +03:00
return UNIXERROR ( ERRDOS , ERRbadfile ) ;
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
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 10 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_vwv0 , mode ) ;
2005-11-05 07:21:55 +03:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
srv_put_dos_date3 ( outbuf , smb_vwv1 , mtime & ~ 1 ) ;
} else {
srv_put_dos_date3 ( outbuf , smb_vwv1 , mtime ) ;
}
2002-12-04 02:57:45 +03:00
SIVAL ( 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 ) {
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_flg2 , SVAL ( 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 ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBgetatr ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_setatr ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring fname ;
int outsize = 0 ;
int mode ;
time_t mtime ;
SMB_STRUCT_STAT sbuf ;
char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBsetatr ) ;
p = smb_buf ( inbuf ) + 1 ;
2005-10-31 23:11:58 +03:00
p + = srvstr_get_path ( inbuf , fname , p , sizeof ( fname ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBsetatr ) ;
return ERROR_NT ( status ) ;
}
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2005-03-16 02:17:03 +03:00
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , fname , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBsetatr ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
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 ) ) {
END_PROFILE ( SMBsetatr ) ;
return ERROR_NT ( status ) ;
}
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
*/
END_PROFILE ( SMBsetatr ) ;
return ERROR_NT ( NT_STATUS_ACCESS_DENIED ) ;
}
2002-12-04 02:57:45 +03:00
mode = SVAL ( inbuf , smb_vwv0 ) ;
2005-11-05 07:21:55 +03:00
mtime = srv_make_unix_date3 ( inbuf + smb_vwv1 ) ;
2002-12-04 02:57:45 +03: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-01-08 16:21:43 +03:00
if ( file_set_dosmode ( conn , fname , mode , & sbuf , False ) ! = 0 ) {
END_PROFILE ( SMBsetatr ) ;
2007-01-08 18:36:33 +03:00
return UNIXERROR ( ERRDOS , ERRnoaccess ) ;
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 ) ) ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-01-08 18:36:33 +03:00
return UNIXERROR ( ERRDOS , ERRnoaccess ) ;
2002-12-04 02:57:45 +03:00
}
1997-08-21 00:32:23 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1996-05-04 11:50:46 +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 ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_dskattr ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-07-15 14:35:28 +04:00
int outsize = 0 ;
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 ) {
2005-03-16 04:41:21 +03:00
END_PROFILE ( SMBdskattr ) ;
return ( UNIXERROR ( ERRHRD , ERRgeneral ) ) ;
}
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 5 , 0 , True ) ;
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 ;
SSVAL ( outbuf , smb_vwv0 , dsize ) ;
SSVAL ( outbuf , smb_vwv1 , 64 ) ; /* this must be 64 for dos systems */
SSVAL ( outbuf , smb_vwv2 , 512 ) ; /* and this must be 512 */
SSVAL ( outbuf , smb_vwv3 , dfree ) ;
} else {
SSVAL ( outbuf , smb_vwv0 , dsize ) ;
SSVAL ( outbuf , smb_vwv1 , bsize / 512 ) ;
SSVAL ( outbuf , smb_vwv2 , 512 ) ;
SSVAL ( outbuf , smb_vwv3 , dfree ) ;
}
DEBUG ( 3 , ( " dskattr dfree=%d \n " , ( unsigned int ) dfree ) ) ;
END_PROFILE ( SMBdskattr ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_search ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring mask ;
pstring directory ;
pstring fname ;
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 ;
2002-12-04 02:57:45 +03:00
int outsize = 0 ;
2003-10-30 00:28:00 +03:00
unsigned int numentries = 0 ;
unsigned int maxentries = 0 ;
2002-12-04 02:57:45 +03:00
BOOL finished = False ;
char * p ;
int status_len ;
pstring path ;
char status [ 21 ] ;
int dptr_num = - 1 ;
BOOL check_descend = False ;
BOOL expect_close = False ;
2003-10-09 03:21:36 +04:00
NTSTATUS nt_status ;
2005-10-31 23:11:58 +03:00
BOOL mask_contains_wcard = False ;
2005-03-29 04:36:30 +04:00
BOOL allow_long_path_components = ( SVAL ( inbuf , smb_flg2 ) & FLAGS2_LONG_PATH_COMPONENTS ) ? True : False ;
2006-05-05 11:15:45 +04:00
START_PROFILE ( SMBsearch ) ;
2005-06-23 01:20:41 +04:00
if ( lp_posix_pathnames ( ) ) {
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBsearch ) ;
2005-06-23 01:20:41 +04:00
return reply_unknown ( inbuf , outbuf ) ;
}
2002-12-04 02:57:45 +03:00
* mask = * directory = * fname = 0 ;
/* If we were called as SMBffirst then we must expect close. */
2007-01-17 00:04:30 +03:00
if ( CVAL ( inbuf , smb_com ) = = SMBffirst ) {
2002-12-04 02:57:45 +03:00
expect_close = True ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 3 , True ) ;
2002-12-04 02:57:45 +03:00
maxentries = SVAL ( inbuf , smb_vwv0 ) ;
dirtype = SVAL ( inbuf , smb_vwv1 ) ;
p = smb_buf ( inbuf ) + 1 ;
2005-10-31 23:11:58 +03:00
p + = srvstr_get_path_wcard ( inbuf , path , p , sizeof ( path ) , 0 , STR_TERMINATE , & nt_status , & mask_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
END_PROFILE ( SMBsearch ) ;
return ERROR_NT ( nt_status ) ;
}
2005-03-16 02:17:03 +03:00
2007-03-12 20:55:24 +03:00
nt_status = resolve_dfspath_wcard ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , path , & mask_contains_wcard ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBsearch ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( nt_status ) ;
2007-03-08 01:12:58 +03:00
}
2005-03-16 02:17:03 +03:00
2002-12-04 02:57:45 +03:00
p + + ;
status_len = SVAL ( p , 0 ) ;
p + = 2 ;
/* dirtype &= ~aDIR; */
if ( status_len = = 0 ) {
SMB_STRUCT_STAT sbuf ;
pstrcpy ( directory , path ) ;
2007-01-13 04:29:10 +03:00
nt_status = unix_convert ( conn , directory , True , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
END_PROFILE ( SMBsearch ) ;
return ERROR_NT ( nt_status ) ;
}
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-01-17 00:04:30 +03:00
END_PROFILE ( SMBsearch ) ;
2007-01-17 05:09:37 +03:00
return ERROR_NT ( nt_status ) ;
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-03-09 05:16:03 +03:00
pstrcpy ( mask , directory ) ;
pstrcpy ( directory , " . " ) ;
2007-01-17 00:04:30 +03:00
} else {
2002-12-04 02:57:45 +03:00
* p = 0 ;
2007-03-09 05:16:03 +03:00
pstrcpy ( 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 ' ) {
2002-12-13 22:07:37 +03:00
pstrcpy ( directory , " . " ) ;
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 ) ) ;
} 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
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 ) ) ;
2003-01-14 11:53:59 +03:00
pstrcpy ( mask , dptr_wcard ( dptr_num ) ) ;
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 ) ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 00:04:30 +03:00
p = smb_buf ( outbuf ) + 3 ;
1999-12-13 16:27:58 +03:00
2007-01-17 00:04:30 +03:00
if ( status_len = = 0 ) {
2007-01-18 09:19:24 +03:00
nt_status = dptr_create ( conn ,
directory ,
True ,
expect_close ,
SVAL ( inbuf , smb_pid ) ,
mask ,
mask_contains_wcard ,
dirtype ,
& conn - > dirptr ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return ERROR_NT ( nt_status ) ;
2007-01-17 00:04:30 +03:00
}
2007-01-18 09:19:24 +03:00
dptr_num = dptr_dnum ( conn - > dirptr ) ;
2007-01-17 00:04:30 +03:00
} else {
dirtype = dptr_attr ( dptr_num ) ;
}
DEBUG ( 4 , ( " dptr_num is %d \n " , dptr_num ) ) ;
if ( ( dirtype & 0x1F ) = = aVOLID ) {
memcpy ( p , status , 21 ) ;
make_dir_struct ( p , " ??????????? " , volume_label ( SNUM ( conn ) ) ,
0 , aVOLID , 0 , ! allow_long_path_components ) ;
dptr_fill ( p + 12 , dptr_num ) ;
if ( dptr_zero ( p + 12 ) & & ( status_len = = 0 ) ) {
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-01-17 00:04:30 +03:00
p + = DIR_STRUCT_SIZE ;
} else {
unsigned int i ;
maxentries = MIN ( maxentries , ( ( BUFFER_SIZE - ( p - 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 + + ) {
finished = ! get_dir_entry ( conn , mask , dirtype , fname , & size , & mode , & date , check_descend ) ;
if ( ! finished ) {
2002-12-04 02:57:45 +03:00
memcpy ( p , status , 21 ) ;
2007-01-17 00:04:30 +03:00
make_dir_struct ( p , mask , fname , size , mode , date ,
! allow_long_path_components ) ;
if ( ! dptr_fill ( p + 12 , dptr_num ) ) {
break ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 00:04:30 +03:00
numentries + + ;
p + = DIR_STRUCT_SIZE ;
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 ! */
2005-01-29 02:17:12 +03:00
if ( dptr_num > = 0 & & CVAL ( 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 ) {
2005-01-29 02:17:12 +03:00
return ERROR_BOTH ( STATUS_NO_MORE_FILES , ERRDOS , ERRnofiles ) ;
}
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_vwv0 , numentries ) ;
SSVAL ( outbuf , smb_vwv1 , 3 + numentries * DIR_STRUCT_SIZE ) ;
SCVAL ( smb_buf ( outbuf ) , 0 , 5 ) ;
SSVAL ( smb_buf ( outbuf ) , 1 , numentries * DIR_STRUCT_SIZE ) ;
2005-03-29 04:36:30 +04:00
/* The replies here are never long name. */
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) & ( ~ FLAGS2_IS_LONG_NAME ) ) ;
if ( ! allow_long_path_components ) {
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) & ( ~ FLAGS2_LONG_PATH_COMPONENTS ) ) ;
}
2005-03-25 22:52:01 +03:00
/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
SSVAL ( outbuf , smb_flg2 , ( SVAL ( outbuf , smb_flg2 ) & ( ~ FLAGS2_UNICODE_STRINGS ) ) ) ;
2002-12-04 02:57:45 +03:00
outsize + = DIR_STRUCT_SIZE * numentries ;
2007-04-20 02:40:32 +04:00
smb_setlen ( inbuf , outbuf , outsize - 4 ) ;
2002-12-04 02:57:45 +03:00
if ( ( ! * directory ) & & dptr_path ( dptr_num ) )
slprintf ( directory , sizeof ( directory ) - 1 , " (%s) " , dptr_path ( dptr_num ) ) ;
2003-10-30 00:28:00 +03:00
DEBUG ( 4 , ( " %s mask=%s path=%s dtype=%d nument=%u of %u \n " ,
2002-12-04 02:57:45 +03:00
smb_fn_name ( CVAL ( inbuf , smb_com ) ) ,
mask , directory , dirtype , numentries , maxentries ) ) ;
END_PROFILE ( SMBsearch ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_fclose ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int outsize = 0 ;
int status_len ;
pstring path ;
char status [ 21 ] ;
int dptr_num = - 2 ;
char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS err ;
2005-10-31 23:11:58 +03:00
BOOL path_contains_wcard = False ;
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 ( ) ) {
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBfclose ) ;
2005-06-23 01:20:41 +04:00
return reply_unknown ( inbuf , outbuf ) ;
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2002-12-04 02:57:45 +03:00
p = smb_buf ( inbuf ) + 1 ;
2005-10-31 23:11:58 +03:00
p + = srvstr_get_path_wcard ( inbuf , path , p , sizeof ( path ) , 0 , STR_TERMINATE , & err , & path_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( err ) ) {
END_PROFILE ( SMBfclose ) ;
return ERROR_NT ( err ) ;
}
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 ) {
END_PROFILE ( SMBfclose ) ;
return ERROR_DOS ( ERRSRV , ERRsrverror ) ;
}
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
2002-12-04 02:57:45 +03:00
SSVAL ( 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 ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_open ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring fname ;
int outsize = 0 ;
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 ;
int oplock_request = CORE_OPLOCK_REQUEST ( inbuf ) ;
2005-07-08 08:51:27 +04:00
int deny_mode ;
uint32 dos_attr = SVAL ( inbuf , smb_vwv1 ) ;
uint32 access_mask ;
uint32 share_mode ;
uint32 create_disposition ;
uint32 create_options = 0 ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopen ) ;
1997-08-21 00:32:23 +04:00
2005-07-08 08:51:27 +04:00
deny_mode = SVAL ( inbuf , smb_vwv0 ) ;
1996-05-04 11:50:46 +04:00
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , fname , smb_buf ( inbuf ) + 1 , sizeof ( fname ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBopen ) ;
return ERROR_NT ( status ) ;
}
2000-03-09 01:14:30 +03:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBopen ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , fname , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBopen ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
2004-06-11 21:54:23 +04:00
}
1996-05-04 11:50:46 +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 ) ) {
END_PROFILE ( SMBopen ) ;
return ERROR_NT ( status ) ;
}
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 ) ) {
END_PROFILE ( SMBopen ) ;
2006-07-11 22:01:26 +04:00
return ERROR_NT ( NT_STATUS_DOS ( ERRDOS , ERRbadaccess ) ) ;
2005-07-08 08:51:27 +04:00
}
2006-07-11 22:01:26 +04:00
status = open_file_ntcreate ( conn , 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 ) ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopen ) ;
2004-06-08 20:14:31 +04:00
if ( open_was_deferred ( SVAL ( inbuf , smb_mid ) ) ) {
/* We have re-scheduled this call. */
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return ERROR_NT ( status ) ;
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 ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopen ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 7 , 0 , True ) ;
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_vwv0 , fsp - > fnum ) ;
2005-07-08 08:51:27 +04:00
SSVAL ( outbuf , smb_vwv1 , fattr ) ;
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2005-11-05 07:21:55 +03:00
srv_put_dos_date3 ( outbuf , smb_vwv2 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2005-11-05 07:21:55 +03:00
srv_put_dos_date3 ( outbuf , smb_vwv2 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
SIVAL ( outbuf , smb_vwv4 , ( uint32 ) size ) ;
2005-10-06 04:21:02 +04:00
SSVAL ( 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 ) ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( 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 ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( 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 ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_open_and_X ( connection_struct * conn , char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring fname ;
2005-07-08 08:51:27 +04:00
uint16 open_flags = SVAL ( inbuf , smb_vwv2 ) ;
int deny_mode = SVAL ( inbuf , smb_vwv3 ) ;
uint32 smb_attr = SVAL ( inbuf , smb_vwv5 ) ;
2002-12-04 02:57:45 +03:00
/* Breakout the oplock request bits so we can set the
reply bits separately . */
2006-05-30 09:24:21 +04:00
int ex_oplock_request = EXTENDED_OPLOCK_REQUEST ( inbuf ) ;
int core_oplock_request = CORE_OPLOCK_REQUEST ( inbuf ) ;
int oplock_request = ex_oplock_request | core_oplock_request ;
1996-05-04 11:50:46 +04:00
#if 0
2002-12-04 02:57:45 +03:00
int smb_sattr = SVAL ( inbuf , smb_vwv4 ) ;
uint32 smb_time = make_unix_date3 ( inbuf + smb_vwv6 ) ;
1996-05-04 11:50:46 +04:00
# endif
2002-12-04 02:57:45 +03:00
int smb_ofun = SVAL ( inbuf , smb_vwv8 ) ;
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 ;
2005-04-05 05:20:32 +04:00
SMB_BIG_UINT allocation_size = ( SMB_BIG_UINT ) IVAL ( inbuf , smb_vwv9 ) ;
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 ;
2005-04-05 05:20:32 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopenX ) ;
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
if ( lp_nt_pipe_support ( ) ) {
END_PROFILE ( SMBopenX ) ;
return reply_open_pipe_and_X ( conn , inbuf , outbuf , length , bufsize ) ;
} else {
END_PROFILE ( SMBopenX ) ;
return ERROR_DOS ( ERRSRV , ERRaccess ) ;
}
}
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 */
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , fname , smb_buf ( inbuf ) , sizeof ( fname ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBopenX ) ;
return ERROR_NT ( status ) ;
}
2000-03-09 01:14:30 +03:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , fname ) ;
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 ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , fname , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBopenX ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
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 ) ) {
END_PROFILE ( SMBopenX ) ;
return ERROR_NT ( status ) ;
}
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 ) ) {
END_PROFILE ( SMBopenX ) ;
2006-07-11 22:01:26 +04:00
return ERROR_NT ( NT_STATUS_DOS ( ERRDOS , ERRbadaccess ) ) ;
2005-04-02 04:13:27 +04:00
}
2006-07-11 22:01:26 +04:00
status = open_file_ntcreate ( conn , 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 ) ;
1996-05-04 11:50:46 +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 ) ;
2004-06-08 20:14:31 +04:00
if ( open_was_deferred ( SVAL ( inbuf , smb_mid ) ) ) {
/* We have re-scheduled this call. */
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return ERROR_NT ( status ) ;
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 ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBopenX ) ;
2005-04-05 05:20:32 +04:00
return ERROR_NT ( NT_STATUS_DISK_FULL ) ;
}
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 ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBopenX ) ;
2005-04-05 05:20:32 +04:00
return ERROR_NT ( NT_STATUS_DISK_FULL ) ;
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 ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopenX ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
/* 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 .
*/
2005-07-08 08:51:27 +04:00
if ( core_oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( 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 ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( 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 ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 19 , 0 , True ) ;
2005-07-08 08:51:27 +04:00
} else {
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 15 , 0 , True ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_vwv2 , fsp - > fnum ) ;
2005-07-08 08:51:27 +04:00
SSVAL ( outbuf , smb_vwv3 , fattr ) ;
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2005-11-05 07:21:55 +03:00
srv_put_dos_date3 ( outbuf , smb_vwv4 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2005-11-05 07:21:55 +03:00
srv_put_dos_date3 ( outbuf , smb_vwv4 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2007-01-03 09:19:11 +03:00
SIVAL ( outbuf , smb_vwv6 , ( uint32 ) sbuf . st_size ) ;
2005-07-08 08:51:27 +04:00
SSVAL ( outbuf , smb_vwv8 , GET_OPENX_MODE ( deny_mode ) ) ;
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_vwv11 , smb_action ) ;
2005-07-08 08:51:27 +04:00
if ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
SIVAL ( outbuf , smb_vwv15 , STD_RIGHT_ALL_ACCESS ) ;
}
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopenX ) ;
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_ulogoffX ( connection_struct * conn , char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
user_struct * vuser = get_valid_user_struct ( vuid ) ;
START_PROFILE ( SMBulogoffX ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( vuser = = 0 )
DEBUG ( 3 , ( " ulogoff, vuser id %d does not map to user. \n " , 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 */
if ( ( vuser ! = 0 ) & & ( lp_security ( ) ! = SEC_SHARE ) )
file_close_user ( vuid ) ;
1996-10-05 14:41:13 +04:00
2002-12-04 02:57:45 +03:00
invalidate_vuid ( vuid ) ;
1996-10-26 00:30:22 +04:00
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 2 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " ulogoffX vuid=%d \n " , vuid ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBulogoffX ) ;
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_mknew ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring fname ;
int com ;
int outsize = 0 ;
2005-07-08 08:51:27 +04:00
uint32 fattr = SVAL ( inbuf , smb_vwv0 ) ;
2007-03-06 02:40:03 +03:00
struct timespec ts [ 2 ] ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
int oplock_request = CORE_OPLOCK_REQUEST ( inbuf ) ;
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 ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcreate ) ;
1997-05-28 00:28:45 +04:00
2002-12-04 02:57:45 +03:00
com = SVAL ( inbuf , smb_com ) ;
2007-03-06 02:40:03 +03:00
ts [ 1 ] = convert_time_t_to_timespec ( srv_make_unix_date3 ( inbuf + smb_vwv1 ) ) ; /* mtime. */
2007-01-03 09:19:11 +03:00
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , fname , smb_buf ( inbuf ) + 1 , sizeof ( fname ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcreate ) ;
return ERROR_NT ( status ) ;
}
2002-12-04 02:57:45 +03:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , fname ) ;
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 ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2002-12-04 02:57:45 +03:00
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , fname , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBcreate ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
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 ) ) {
END_PROFILE ( SMBcreate ) ;
return ERROR_NT ( status ) ;
}
2005-07-08 08:51:27 +04:00
if ( fattr & aVOLID ) {
2002-12-04 02:57:45 +03: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. */
2006-07-11 22:01:26 +04:00
status = open_file_ntcreate ( conn , 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 ) ;
2002-12-04 02:57:45 +03: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 ) ;
2004-06-08 20:14:31 +04:00
if ( open_was_deferred ( SVAL ( inbuf , smb_mid ) ) ) {
/* We have re-scheduled this call. */
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return ERROR_NT ( status ) ;
2002-12-04 02:57:45 +03:00
}
1997-08-21 00:32:23 +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-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2002-12-04 02:57:45 +03:00
SSVAL ( 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 ) ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
1997-09-26 23:26:56 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
1997-09-26 23:26:56 +04:00
2005-07-08 08:51:27 +04:00
DEBUG ( 2 , ( " reply_mknew: file %s \n " , fname ) ) ;
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 ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_ctemp ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring fname ;
int outsize = 0 ;
2005-07-08 08:51:27 +04:00
uint32 fattr = SVAL ( inbuf , smb_vwv0 ) ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
int oplock_request = CORE_OPLOCK_REQUEST ( inbuf ) ;
int tmpfd ;
SMB_STRUCT_STAT sbuf ;
char * p , * s ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2004-04-03 02:11:08 +04:00
unsigned int namelen ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBctemp ) ;
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , fname , smb_buf ( inbuf ) + 1 , sizeof ( fname ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBctemp ) ;
return ERROR_NT ( status ) ;
}
2004-04-03 02:11:08 +04:00
if ( * fname ) {
pstrcat ( fname , " /TMXXXXXX " ) ;
} else {
pstrcat ( fname , " TMXXXXXX " ) ;
}
2002-12-04 02:57:45 +03:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBctemp ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2002-12-04 02:57:45 +03:00
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , fname , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBctemp ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
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
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBctemp ) ;
return ERROR_NT ( status ) ;
}
2002-12-04 02:57:45 +03:00
tmpfd = smb_mkstemp ( fname ) ;
if ( tmpfd = = - 1 ) {
END_PROFILE ( SMBctemp ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
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. */
2006-07-11 22:01:26 +04:00
status = open_file_ntcreate ( conn , 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 ) ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBctemp ) ;
2004-06-08 20:14:31 +04:00
if ( open_was_deferred ( SVAL ( inbuf , smb_mid ) ) ) {
/* We have re-scheduled this call. */
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return ERROR_NT ( status ) ;
2002-12-04 02:57:45 +03:00
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_vwv0 , fsp - > fnum ) ;
/* 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
p = smb_buf ( outbuf ) ;
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
namelen = srvstr_push ( outbuf , p , s , - 1 , STR_ASCII | STR_TERMINATE ) ;
p + = namelen ;
2007-04-20 02:40:32 +04:00
outsize = set_message_end ( inbuf , outbuf , p ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( 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 ) ) {
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_flg , CVAL ( 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 ) ;
return ( outsize ) ;
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 05:14:49 +03:00
static NTSTATUS can_rename ( connection_struct * conn , char * fname , uint16 dirtype , SMB_STRUCT_STAT * pst )
2002-03-23 05:57:44 +03:00
{
files_struct * fsp ;
2005-07-08 08:51:27 +04:00
uint32 fmode ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
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
fmode = dos_mode ( conn , fname , 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
2006-07-11 22:01:26 +04:00
status = open_file_ntcreate ( conn , fname , pst ,
2005-07-08 08:51:27 +04:00
DELETE_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN ,
0 ,
FILE_ATTRIBUTE_NORMAL ,
0 ,
2006-07-11 22:01:26 +04:00
NULL , & fsp ) ;
2002-03-23 05:57:44 +03:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-12-28 03:01:12 +03:00
return status ;
2002-03-23 05:57:44 +03:00
}
2006-02-02 23:44:50 +03:00
close_file ( fsp , NORMAL_CLOSE ) ;
2002-03-23 05:57:44 +03:00
return NT_STATUS_OK ;
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2001-11-17 06:19:17 +03:00
Check if a user is allowed to delete a file .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-17 06:19:17 +03:00
2007-01-15 12:17:11 +03:00
static NTSTATUS can_delete ( connection_struct * conn , char * fname ,
uint32 dirtype , BOOL can_defer )
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
2005-07-08 08:51:27 +04:00
DEBUG ( 10 , ( " can_delete: %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 . */
status = open_file_ntcreate ( conn , fname , & sbuf ,
DELETE_ACCESS ,
FILE_SHARE_NONE ,
FILE_OPEN ,
0 ,
FILE_ATTRIBUTE_NORMAL ,
2007-01-15 12:17:11 +03:00
can_defer ? 0 : INTERNAL_OPEN_ONLY ,
2007-01-02 18:07:27 +03:00
NULL , & fsp ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , NORMAL_CLOSE ) ;
2002-03-23 05:57:44 +03:00
}
2007-01-02 18:07:27 +03:00
return status ;
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-01-15 12:17:11 +03:00
NTSTATUS unlink_internals ( connection_struct * conn , uint32 dirtype ,
char * name , BOOL has_wild , BOOL can_defer )
1996-05-04 11:50:46 +04:00
{
2001-08-27 12:19:43 +04:00
pstring directory ;
pstring mask ;
char * p ;
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 ;
* directory = * mask = 0 ;
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , name , has_wild , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-01-09 18:50:40 +03:00
2001-08-27 12:19:43 +04:00
p = strrchr_m ( name , ' / ' ) ;
if ( ! p ) {
2002-03-19 05:32:39 +03:00
pstrcpy ( directory , " . " ) ;
2001-08-27 12:19:43 +04:00
pstrcpy ( mask , name ) ;
} else {
* p = 0 ;
pstrcpy ( directory , name ) ;
pstrcpy ( mask , p + 1 ) ;
}
/*
* 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-01-13 02:47:16 +03:00
if ( ! VALID_STAT ( sbuf ) & & mangle_is_mangled ( mask , conn - > params ) )
2006-07-11 22:01:26 +04:00
mangle_check_cache ( mask , sizeof ( pstring ) - 1 , conn - > params ) ;
2001-08-27 12:19:43 +04:00
if ( ! has_wild ) {
pstrcat ( directory , " / " ) ;
pstrcat ( directory , mask ) ;
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-01-15 12:17:11 +03:00
status = can_delete ( conn , directory , dirtype , can_defer ) ;
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
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_UNLINK ( conn , directory ) = = 0 ) {
2001-08-27 12:19:43 +04:00
count + + ;
2007-01-31 17:14:57 +03:00
notify_fname ( conn , NOTIFY_ACTION_REMOVED ,
2007-01-31 15:42:24 +03:00
FILE_NOTIFY_CHANGE_FILE_NAME ,
2007-01-31 17:14:57 +03:00
directory ) ;
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 ;
2001-08-27 12:19:43 +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 , " ????????.??? " ) ) {
2005-06-25 07:03:44 +04:00
pstrcpy ( mask , " * " ) ;
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 ) ;
}
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-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 ;
pstring fname ;
pstrcpy ( fname , dname ) ;
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 ".." */
if ( fname [ 0 ] = = ' . ' ) {
if ( ! fname [ 1 ] | | ( fname [ 1 ] = = ' . ' & & ! fname [ 2 ] ) ) {
continue ;
2004-02-25 04:35:14 +03:00
}
2007-01-17 05:09:37 +03:00
}
2004-02-24 04:46:24 +03:00
2007-01-17 05:09:37 +03:00
if ( ! mask_match ( fname , mask , conn - > case_sensitive ) ) {
continue ;
}
2001-08-27 12:19:43 +04:00
2007-01-17 05:09:37 +03:00
slprintf ( fname , sizeof ( fname ) - 1 , " %s/%s " , directory , dname ) ;
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-01-17 05:09:37 +03:00
status = can_delete ( conn , fname , dirtype , can_defer ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
continue ;
2001-08-27 12:19:43 +04:00
}
2007-01-17 19:23:45 +03:00
if ( SMB_VFS_UNLINK ( conn , fname ) = = 0 ) {
2007-01-17 05:09:37 +03:00
count + + ;
2007-01-17 19:23:45 +03:00
DEBUG ( 3 , ( " unlink_internals: succesful unlink "
" [%s] \n " , fname ) ) ;
2007-01-31 19:56:27 +03:00
notify_fname ( conn , NOTIFY_ACTION_REMOVED ,
FILE_NOTIFY_CHANGE_FILE_NAME ,
fname ) ;
2007-01-17 19:23:45 +03:00
}
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-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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 12:19:43 +04:00
int reply_unlink ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size ,
int dum_buffsize )
2000-11-15 00:56:32 +03:00
{
2001-08-27 12:19:43 +04:00
int outsize = 0 ;
pstring name ;
2005-06-25 07:03:44 +04:00
uint32 dirtype ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2005-10-31 23:11:58 +03:00
BOOL path_contains_wcard = False ;
2005-11-02 02:49:40 +03:00
START_PROFILE ( SMBunlink ) ;
2001-08-27 12:19:43 +04:00
dirtype = SVAL ( inbuf , smb_vwv0 ) ;
2005-10-31 23:11:58 +03:00
srvstr_get_path_wcard ( inbuf , name , smb_buf ( inbuf ) + 1 , sizeof ( name ) , 0 , STR_TERMINATE , & status , & path_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBunlink ) ;
2003-08-13 07:28:06 +04:00
return ERROR_NT ( status ) ;
2003-10-09 03:21:36 +04:00
}
2007-03-12 20:55:24 +03:00
status = resolve_dfspath_wcard ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , name , & path_contains_wcard ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBunlink ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " reply_unlink : %s \n " , name ) ) ;
2007-01-15 12:17:11 +03:00
status = unlink_internals ( conn , dirtype , name , path_contains_wcard ,
True ) ;
2004-06-08 20:14:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( open_was_deferred ( SVAL ( inbuf , smb_mid ) ) ) {
/* We have re-scheduled this call. */
return - 1 ;
}
2003-07-29 23:16:59 +04:00
return ERROR_NT ( status ) ;
2004-06-08 20:14:31 +04:00
}
2001-09-04 11:13:01 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlink ) ;
return outsize ;
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
{
pstring errstr ;
2001-11-05 03:02:38 +03:00
slprintf ( errstr , sizeof ( errstr ) - 1 , " FAIL ! reply_readbraw: socket write fail (%s) " ,
2001-09-04 23:10:30 +04:00
strerror ( errno ) ) ;
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-05-16 04:07:38 +04:00
static ssize_t fake_sendfile ( files_struct * fsp , SMB_OFF_T startpos , size_t nread , char * buf , size_t bufsize )
2004-11-25 01:05:59 +03:00
{
2007-05-16 04:07:38 +04:00
size_t tosend = nread ;
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 ) {
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 ) {
return - 1 ;
}
tosend - = cur_read ;
startpos + = cur_read ;
}
2004-11-25 01:05:59 +03:00
return ( ssize_t ) nread ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Use sendfile in readbraw .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void send_file_readbraw ( connection_struct * conn , files_struct * fsp , SMB_OFF_T startpos , size_t nread ,
2004-11-25 01:05:59 +03:00
ssize_t mincount , char * outbuf , int out_buffsize )
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 ) ) ) {
2002-09-25 19:19:00 +04:00
DATA_BLOB header ;
_smb_setlen ( outbuf , nread ) ;
2005-10-18 07:24:00 +04:00
header . data = ( uint8 * ) outbuf ;
2002-09-25 19:19:00 +04:00
header . length = 4 ;
header . free = NULL ;
2005-07-08 08:51:27 +04:00
if ( SMB_VFS_SENDFILE ( smbd_server_fd ( ) , fsp , fsp - > fh - > fd , & header , startpos , nread ) = = - 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_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 " ) ) ;
if ( fake_sendfile ( fsp , startpos , nread , outbuf + 4 , out_buffsize - 4 ) = = - 1 ) {
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
}
2004-12-21 01:01:42 +03:00
normal_readbraw :
2002-09-25 19:19:00 +04:00
# endif
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 ( ) ;
}
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
2004-11-25 01:05:59 +03:00
int reply_readbraw ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int out_buffsize )
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 ;
char * header = outbuf ;
files_struct * fsp ;
START_PROFILE ( SMBreadbraw ) ;
1996-05-04 11:50:46 +04:00
2003-07-18 04:53:34 +04:00
if ( srv_is_signing_active ( ) ) {
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " reply_readbraw: SMB signing is active - raw reads/writes are disallowed. " ) ;
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
2001-09-04 23:10:30 +04:00
fsp = file_fsp ( inbuf , smb_vwv0 ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( ! FNUM_OK ( fsp , conn ) | | ! fsp - > can_read ) {
/*
* fsp could be NULL here so use the value from the packet . JRA .
*/
DEBUG ( 3 , ( " fnum %d not open in readbraw - cache prime? \n " , ( int ) SVAL ( inbuf , smb_vwv0 ) ) ) ;
_smb_setlen ( header , 0 ) ;
if ( write_data ( smbd_server_fd ( ) , header , 4 ) ! = 4 )
fail_readraw ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ( - 1 ) ;
}
1999-12-13 16:27:58 +03:00
2001-09-04 23:10:30 +04:00
CHECK_FSP ( fsp , conn ) ;
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
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv1 ) ;
2001-09-04 23:10:30 +04:00
if ( CVAL ( inbuf , smb_wct ) = = 10 ) {
/*
* This is a large offset ( 64 bit ) read .
*/
1999-12-13 16:27:58 +03:00
# ifdef LARGE_SMB_OFF_T
2001-09-04 23:10:30 +04:00
startpos | = ( ( ( SMB_OFF_T ) IVAL ( 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
2001-09-04 23:10:30 +04:00
if ( IVAL ( inbuf , smb_vwv8 ) ! = 0 ) {
DEBUG ( 0 , ( " readbraw - large offset (%x << 32) used and we don't support \
1999-12-13 16:27:58 +03:00
64 bit offsets . \ n " , (unsigned int)IVAL(inbuf,smb_vwv8) ));
2001-09-04 23:10:30 +04:00
_smb_setlen ( header , 0 ) ;
if ( write_data ( smbd_server_fd ( ) , header , 4 ) ! = 4 )
fail_readraw ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ( - 1 ) ;
}
1999-12-13 16:27:58 +03:00
# endif /* LARGE_SMB_OFF_T */
2001-09-04 23:10:30 +04:00
if ( startpos < 0 ) {
DEBUG ( 0 , ( " readbraw - negative 64 bit readraw offset (%.0f) ! \n " , ( double ) startpos ) ) ;
_smb_setlen ( header , 0 ) ;
if ( write_data ( smbd_server_fd ( ) , header , 4 ) ! = 4 )
fail_readraw ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ( - 1 ) ;
}
}
maxcount = ( SVAL ( inbuf , smb_vwv3 ) & 0xFFFF ) ;
mincount = ( SVAL ( inbuf , smb_vwv4 ) & 0xFFFF ) ;
/* ensure we don't overrun the packet size */
maxcount = MIN ( 65535 , maxcount ) ;
2006-07-11 22:01:26 +04:00
if ( ! is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) maxcount , ( SMB_BIG_UINT ) startpos , READ_LOCK ) ) {
2005-05-09 03:16:28 +04:00
SMB_STRUCT_STAT st ;
SMB_OFF_T size = 0 ;
2001-09-04 23:10:30 +04:00
2005-07-08 08:51:27 +04:00
if ( SMB_VFS_FSTAT ( fsp , fsp - > fh - > fd , & st ) = = 0 ) {
2005-05-09 03:16:28 +04:00
size = st . st_size ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2005-05-09 03:16:28 +04:00
if ( startpos > = size ) {
2001-09-04 23:10:30 +04:00
nread = 0 ;
2005-05-09 03:16:28 +04:00
} else {
2001-09-04 23:10:30 +04:00
nread = MIN ( maxcount , ( size - startpos ) ) ;
2005-05-09 03:16:28 +04:00
}
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
2005-09-30 21:13:37 +04:00
DEBUG ( 3 , ( " 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
2004-11-25 01:05:59 +03:00
send_file_readbraw ( conn , fsp , startpos , nread , mincount , outbuf , out_buffsize ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
DEBUG ( 5 , ( " readbraw finished \n " ) ) ;
END_PROFILE ( SMBreadbraw ) ;
return - 1 ;
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
1998-08-20 23:28:37 +04:00
int reply_lockread ( connection_struct * conn , char * inbuf , char * outbuf , int length , int dum_buffsiz )
1996-05-04 11:50:46 +04:00
{
2001-08-27 12:19:43 +04:00
ssize_t nread = - 1 ;
char * data ;
int outsize = 0 ;
SMB_OFF_T startpos ;
size_t numtoread ;
NTSTATUS status ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
2006-07-18 05:05:51 +04:00
struct byte_range_lock * br_lck = NULL ;
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBlockread ) ;
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_READ ( fsp , inbuf ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
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
2001-08-27 12:19:43 +04:00
numtoread = SVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv2 ) ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 5 , 3 , True ) ;
2001-08-27 12:19:43 +04:00
numtoread = MIN ( BUFFER_SIZE - outsize , numtoread ) ;
data = smb_buf ( outbuf ) + 3 ;
/*
* 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 ,
2006-07-18 01:09:02 +04:00
( uint32 ) SVAL ( inbuf , smb_pid ) ,
( 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 ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlockread ) ;
2001-08-27 12:19:43 +04:00
return ERROR_NT ( status ) ;
}
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 ) {
END_PROFILE ( SMBlockread ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
outsize + = nread ;
SSVAL ( outbuf , smb_vwv0 , nread ) ;
SSVAL ( outbuf , smb_vwv5 , nread + 3 ) ;
SSVAL ( smb_buf ( outbuf ) , 1 , nread ) ;
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 ) ;
return ( outsize ) ;
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
int reply_read ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
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 ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBread ) ;
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_READ ( fsp , inbuf ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
2001-08-27 12:19:43 +04:00
2002-09-25 19:19:00 +04:00
numtoread = SVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv2 ) ;
2001-08-27 12:19:43 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 5 , 3 , True ) ;
2002-09-25 19:19:00 +04:00
numtoread = MIN ( BUFFER_SIZE - outsize , numtoread ) ;
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
2002-09-25 19:19:00 +04:00
data = smb_buf ( outbuf ) + 3 ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) numtoread , ( SMB_BIG_UINT ) startpos , READ_LOCK ) ) {
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
return ERROR_DOS ( ERRDOS , ERRlock ) ;
}
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 ) {
END_PROFILE ( SMBread ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
outsize + = nread ;
SSVAL ( outbuf , smb_vwv0 , nread ) ;
SSVAL ( outbuf , smb_vwv5 , nread + 3 ) ;
SCVAL ( smb_buf ( outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( 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 ) ;
return ( outsize ) ;
1996-05-04 11:50:46 +04:00
}
2007-05-16 04:07:38 +04:00
/****************************************************************************
Setup readX header .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int setup_readX_header ( char * inbuf , char * outbuf , size_t smb_maxcnt )
{
int outsize ;
char * data = smb_buf ( outbuf ) ;
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 ) ;
SCVAL ( outbuf , smb_vwv0 , 0xFF ) ;
outsize = set_message ( inbuf , outbuf , 12 , smb_maxcnt , False ) ;
/* 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-11-25 01:05:59 +03:00
int send_file_readX ( connection_struct * conn , char * inbuf , char * outbuf , int length , int len_outbuf ,
2002-09-25 19:19:00 +04:00
files_struct * fsp , SMB_OFF_T startpos , size_t smb_maxcnt )
{
2007-05-16 04:07:38 +04:00
SMB_STRUCT_STAT sbuf ;
2004-12-14 04:11:22 +03:00
int outsize = 0 ;
2002-09-25 19:19:00 +04:00
ssize_t nread = - 1 ;
char * data = smb_buf ( outbuf ) ;
2007-05-16 04:07:38 +04:00
if ( SMB_VFS_FSTAT ( fsp , fsp - > fh - > fd , & sbuf ) = = - 1 ) {
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
if ( startpos > sbuf . st_size ) {
smb_maxcnt = 0 ;
}
if ( smb_maxcnt > ( sbuf . st_size - startpos ) ) {
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)
/*
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 .
2002-09-25 19:19:00 +04:00
*/
2006-03-20 02:32:50 +03:00
if ( ( chain_size = = 0 ) & & ( CVAL ( inbuf , smb_vwv0 ) = = 0xFF ) & &
lp_use_sendfile ( SNUM ( conn ) ) & & ( fsp - > wcp = = NULL ) ) {
2002-09-25 19:19:00 +04:00
DATA_BLOB header ;
/*
* Set up the packet header before send . We
* assume here the sendfile will work ( get the
* correct amount of data ) .
*/
2007-05-16 04:07:38 +04:00
setup_readX_header ( inbuf , outbuf , smb_maxcnt ) ;
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 12 , smb_maxcnt , False ) ;
2005-10-18 07:24:00 +04:00
header . data = ( uint8 * ) outbuf ;
2002-09-25 19:19:00 +04:00
header . length = data - outbuf ;
header . free = NULL ;
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 " ) ) ;
if ( ( nread = fake_sendfile ( fsp , startpos , smb_maxcnt , data ,
len_outbuf - ( data - outbuf ) ) ) = = - 1 ) {
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 ) ) ;
2004-12-21 01:01:42 +03:00
/* Returning -1 here means successful sendfile. */
return - 1 ;
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 ) ) ;
2004-12-21 01:01:42 +03:00
/* Returning -1 here means successful sendfile. */
2002-09-25 19:19:00 +04:00
return - 1 ;
}
# endif
2007-05-16 04:21:12 +04:00
normal_read :
2007-05-16 04:07:38 +04:00
if ( ( smb_maxcnt & & 0xFF0000 ) > 0x10000 ) {
int sendlen = setup_readX_header ( inbuf , outbuf , smb_maxcnt ) - smb_maxcnt ;
/* Send out the header. */
if ( write_data ( smbd_server_fd ( ) , outbuf , sendlen ) ! = sendlen ) {
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 " ) ;
}
if ( ( nread = fake_sendfile ( fsp , startpos , smb_maxcnt , data ,
len_outbuf - ( data - outbuf ) ) ) = = - 1 ) {
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 " ) ;
}
return - 1 ;
} else {
nread = read_file ( fsp , data , startpos , smb_maxcnt ) ;
2002-09-25 19:19:00 +04:00
2007-05-16 04:07:38 +04:00
if ( nread < 0 ) {
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
2002-09-25 19:19:00 +04:00
2007-05-16 05:36:23 +04:00
outsize = setup_readX_header ( inbuf , 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 ) ) ;
/* Returning the number of bytes we want to send back - including header. */
return outsize ;
}
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
1998-08-14 21:38:29 +04:00
int reply_read_and_X ( connection_struct * conn , char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
2002-09-25 19:19:00 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv2 ) ;
2002-12-03 11:02:41 +03:00
SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv3 ) ;
2002-09-25 19:19:00 +04:00
ssize_t nread = - 1 ;
size_t smb_maxcnt = SVAL ( inbuf , smb_vwv5 ) ;
2007-05-16 04:07:38 +04:00
BOOL big_readX = False ;
2002-09-25 19:19:00 +04:00
#if 0
size_t smb_mincnt = SVAL ( inbuf , smb_vwv6 ) ;
# 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
2002-09-25 19:19:00 +04:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
END_PROFILE ( SMBreadX ) ;
return reply_pipe_read_and_X ( inbuf , outbuf , length , bufsize ) ;
}
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_READ ( fsp , inbuf ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 12 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
2004-11-24 06:42:01 +03:00
if ( global_client_caps & CAP_LARGE_READX ) {
2007-05-16 04:07:38 +04:00
size_t upper_size = SVAL ( inbuf , smb_vwv7 ) ;
smb_maxcnt | = ( upper_size < < 16 ) ;
if ( upper_size > 1 ) {
/* Can't do this on a chained packet. */
if ( ( CVAL ( inbuf , smb_vwv0 ) ! = 0xFF ) ) {
return ERROR_NT ( NT_STATUS_NOT_SUPPORTED ) ;
}
/* We currently don't do this on signed or sealed data. */
if ( srv_is_signing_active ( ) | | srv_encryption_on ( ) ) {
return ERROR_NT ( NT_STATUS_NOT_SUPPORTED ) ;
}
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 ) ) ) {
return ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
}
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
}
2002-09-25 19:19:00 +04:00
if ( CVAL ( inbuf , smb_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 .
*/
startpos | = ( ( ( SMB_OFF_T ) IVAL ( 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
2002-09-25 19:19:00 +04:00
if ( IVAL ( inbuf , smb_vwv10 ) ! = 0 ) {
DEBUG ( 0 , ( " reply_read_and_X - large offset (%x << 32) used and we don't support \
1999-12-13 16:27:58 +03:00
64 bit offsets . \ n " , (unsigned int)IVAL(inbuf,smb_vwv10) ));
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
return ERROR_DOS ( ERRDOS , ERRbadaccess ) ;
}
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
2006-07-11 22:01:26 +04:00
if ( is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) smb_maxcnt , ( SMB_BIG_UINT ) startpos , READ_LOCK ) ) {
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
return ERROR_DOS ( ERRDOS , ERRlock ) ;
}
2001-08-27 12:19:43 +04:00
2007-05-16 04:07:38 +04:00
if ( ! big_readX & & schedule_aio_read_and_X ( conn , inbuf , outbuf , length , bufsize , fsp , startpos , smb_maxcnt ) ) {
2005-06-09 22:15:23 +04:00
END_PROFILE ( SMBreadX ) ;
return - 1 ;
}
2004-11-25 01:05:59 +03:00
nread = send_file_readX ( conn , inbuf , outbuf , length , bufsize , fsp , startpos , smb_maxcnt ) ;
2007-04-10 01:01:46 +04:00
/* Only call chain_reply if not an error. */
if ( nread ! = - 1 & & SVAL ( outbuf , smb_rcls ) = = 0 ) {
2002-09-25 19:19:00 +04:00
nread = chain_reply ( inbuf , outbuf , length , bufsize ) ;
2007-04-10 01:01:46 +04:00
}
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
return nread ;
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
int reply_writebraw ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
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 ;
BOOL write_through ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
int outsize = 0 ;
START_PROFILE ( SMBwritebraw ) ;
1996-05-04 11:50:46 +04:00
2003-07-18 04:53:34 +04:00
if ( srv_is_signing_active ( ) ) {
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " reply_writebraw: SMB signing is active - raw reads/writes are disallowed. " ) ;
2003-07-17 04:53:37 +04:00
}
2001-09-04 23:10:30 +04:00
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
tcount = IVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv3 ) ;
2001-09-04 23:10:30 +04:00
write_through = BITSETW ( 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 ) {
numtowrite = SVAL ( smb_buf ( inbuf ) , - 2 ) ;
data = smb_buf ( inbuf ) ;
} else {
numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
data = smb_base ( inbuf ) + SVAL ( inbuf , smb_vwv11 ) ;
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
/* force the error type */
2002-01-11 22:10:25 +03:00
SCVAL ( inbuf , smb_com , SMBwritec ) ;
SCVAL ( outbuf , smb_com , SMBwritec ) ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) tcount , ( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBwritebraw ) ;
return ( ERROR_DOS ( ERRDOS , ERRlock ) ) ;
}
if ( numtowrite > 0 )
nwritten = write_file ( fsp , data , startpos , numtowrite ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
DEBUG ( 3 , ( " writebraw1 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 ) {
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBwritebraw ) ;
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
}
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
2001-09-04 23:10:30 +04:00
/* Return a message to the redirector to tell it to send more bytes */
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_com , SMBwritebraw ) ;
2001-09-04 23:10:30 +04:00
SSVALS ( outbuf , smb_vwv0 , - 1 ) ;
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , Protocol > PROTOCOL_COREPLUS ? 1 : 0 , 0 , True ) ;
2005-06-09 22:15:23 +04:00
show_msg ( outbuf ) ;
2001-09-04 23:10:30 +04:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " reply_writebraw: send_smb failed. " ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
/* Now read the raw data into the buffer and write it */
if ( read_smb_length ( smbd_server_fd ( ) , inbuf , 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
2001-09-04 23:10:30 +04:00
/* Even though this is not an smb message, smb_len returns the generic length of an smb message */
numtowrite = smb_len ( inbuf ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
/* Set up outbuf to return the correct return */
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_com , SMBwritec ) ;
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
2001-09-04 23:10:30 +04:00
if ( numtowrite > BUFFER_SIZE ) {
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write raw requested (%u). Terminating \n " ,
( 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 ) {
DEBUG ( 3 , ( " Client overestimated the write %d %d %d \n " ,
( int ) tcount , ( int ) nwritten , ( int ) numtowrite ) ) ;
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( read_data ( smbd_server_fd ( ) , inbuf + 4 , numtowrite ) ! = numtowrite ) {
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write raw read failed (%s). Terminating \n " ,
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
2001-09-04 23:10:30 +04:00
nwritten = write_file ( fsp , inbuf + 4 , startpos + nwritten , numtowrite ) ;
2006-07-25 04:16:45 +04:00
if ( nwritten = = - 1 ) {
END_PROFILE ( SMBwritebraw ) ;
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_rcls , ERRHRD ) ;
2001-09-04 23:10:30 +04:00
SSVAL ( outbuf , smb_err , ERRdiskfull ) ;
}
if ( nwritten > 0 )
total_written + = nwritten ;
}
2005-07-10 20:37:32 +04:00
SSVAL ( outbuf , smb_vwv0 , total_written ) ;
2005-09-03 11:19:28 +04:00
sync_file ( conn , fsp , write_through ) ;
2001-09-04 23:10:30 +04:00
DEBUG ( 3 , ( " writebraw2 fnum=%d start=%.0f num=%d wrote=%d \n " ,
fsp - > fnum , ( double ) startpos , ( int ) numtowrite , ( int ) total_written ) ) ;
/* we won't return a status if write through is not selected - this follows what WfWg does */
END_PROFILE ( SMBwritebraw ) ;
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
* sending a SMBkeepalive . Thanks to DaveCB at Sun for this . JRA .
*/
if ( ! send_keepalive ( smbd_server_fd ( ) ) )
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " reply_writebraw: send of keepalive failed " ) ;
2002-04-11 06:20:56 +04:00
# endif
2001-09-04 23:10:30 +04:00
return ( - 1 ) ;
}
return ( outsize ) ;
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
2001-08-27 12:19:43 +04:00
int reply_writeunlock ( connection_struct * conn , char * inbuf , char * outbuf ,
int size , int dum_buffsize )
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 ;
2001-08-27 12:19:43 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
int outsize = 0 ;
START_PROFILE ( SMBwriteunlock ) ;
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
numtowrite = SVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv2 ) ;
2001-08-27 12:19:43 +04:00
data = smb_buf ( inbuf ) + 3 ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( numtowrite & & is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) numtowrite , ( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBwriteunlock ) ;
return ERROR_DOS ( ERRDOS , ERRlock ) ;
}
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 {
2001-08-27 12:19:43 +04:00
nwritten = write_file ( fsp , data , startpos , numtowrite ) ;
2005-07-08 08:51:27 +04:00
}
2001-08-27 12:19:43 +04:00
2005-09-03 11:19:28 +04:00
sync_file ( conn , fsp , False /* write through */ ) ;
2001-08-27 12:19:43 +04:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
END_PROFILE ( SMBwriteunlock ) ;
2003-01-09 02:49:21 +03:00
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
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 ,
2006-07-11 22:01:26 +04:00
( uint32 ) SVAL ( inbuf , smb_pid ) ,
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 ) ) {
END_PROFILE ( SMBwriteunlock ) ;
return ERROR_NT ( status ) ;
}
2001-08-27 12:19:43 +04:00
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2001-08-27 12:19:43 +04:00
SSVAL ( outbuf , smb_vwv0 , nwritten ) ;
DEBUG ( 3 , ( " writeunlock fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
END_PROFILE ( SMBwriteunlock ) ;
return outsize ;
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
int reply_write ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
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 ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
int outsize = 0 ;
START_PROFILE ( SMBwrite ) ;
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
END_PROFILE ( SMBwrite ) ;
return reply_pipe_write ( inbuf , outbuf , size , dum_buffsize ) ;
}
1999-11-16 01:11:10 +03:00
2001-11-25 05:23:22 +03:00
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
numtowrite = SVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv2 ) ;
2001-11-25 05:23:22 +03:00
data = smb_buf ( inbuf ) + 3 ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) numtowrite , ( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
return ERROR_DOS ( ERRDOS , ERRlock ) ;
}
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 ) {
END_PROFILE ( SMBwrite ) ;
return ERROR_NT ( NT_STATUS_DISK_FULL ) ;
}
nwritten = vfs_set_filelen ( fsp , ( SMB_OFF_T ) startpos ) ;
if ( nwritten < 0 ) {
END_PROFILE ( SMBwrite ) ;
return ERROR_NT ( NT_STATUS_DISK_FULL ) ;
}
} else
nwritten = write_file ( fsp , data , startpos , numtowrite ) ;
1996-05-04 11:50:46 +04:00
2005-09-03 11:19:28 +04:00
sync_file ( conn , fsp , False ) ;
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
END_PROFILE ( SMBwrite ) ;
2003-01-09 02:49:21 +03:00
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
SSVAL ( 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 ) {
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_rcls , ERRHRD ) ;
2001-11-25 05:23:22 +03:00
SSVAL ( outbuf , smb_err , ERRdiskfull ) ;
}
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 ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_write_and_X ( connection_struct * conn , char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv2 ) ;
SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv3 ) ;
size_t numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
BOOL write_through = BITSETW ( inbuf + smb_vwv7 , 0 ) ;
ssize_t nwritten = - 1 ;
unsigned int smb_doff = SVAL ( inbuf , smb_vwv11 ) ;
unsigned int smblen = smb_len ( inbuf ) ;
char * data ;
BOOL large_writeX = ( ( CVAL ( inbuf , smb_wct ) = = 14 ) & & ( smblen > 0xFFFF ) ) ;
START_PROFILE ( SMBwriteX ) ;
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
END_PROFILE ( SMBwriteX ) ;
return reply_pipe_write_and_X ( inbuf , outbuf , length , bufsize ) ;
}
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
2002-12-04 02:57:45 +03:00
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 6 , 0 , True ) ;
2005-06-09 22:15:23 +04:00
2002-12-04 02:57:45 +03:00
/* Deal with possible LARGE_WRITEX */
2005-06-09 22:15:23 +04:00
if ( large_writeX ) {
2002-12-04 02:57:45 +03:00
numtowrite | = ( ( ( ( size_t ) SVAL ( inbuf , smb_vwv9 ) ) & 1 ) < < 16 ) ;
2005-06-09 22:15:23 +04:00
}
2002-12-04 02:57:45 +03:00
if ( smb_doff > smblen | | ( smb_doff + numtowrite > smblen ) ) {
END_PROFILE ( SMBwriteX ) ;
return ERROR_DOS ( ERRDOS , ERRbadmem ) ;
}
data = smb_base ( inbuf ) + smb_doff ;
if ( CVAL ( inbuf , smb_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 .
*/
startpos | = ( ( ( SMB_OFF_T ) IVAL ( 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
2002-12-04 02:57:45 +03:00
if ( IVAL ( inbuf , smb_vwv12 ) ! = 0 ) {
DEBUG ( 0 , ( " reply_write_and_X - large offset (%x << 32) used and we don't support \
1999-12-13 16:27:58 +03:00
64 bit offsets . \ n " , (unsigned int)IVAL(inbuf,smb_vwv12) ));
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
return ERROR_DOS ( ERRDOS , ERRbadaccess ) ;
}
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
}
2006-07-11 22:01:26 +04:00
if ( is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) numtowrite , ( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
return ERROR_DOS ( ERRDOS , ERRlock ) ;
}
/* 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 {
if ( schedule_aio_write_and_X ( conn , inbuf , outbuf , length , bufsize ,
fsp , data , startpos , numtowrite ) ) {
END_PROFILE ( SMBwriteX ) ;
return - 1 ;
}
2002-12-04 02:57:45 +03:00
nwritten = write_file ( fsp , data , startpos , numtowrite ) ;
2005-06-09 22:15:23 +04:00
}
2002-12-04 02:57:45 +03:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
END_PROFILE ( SMBwriteX ) ;
2003-01-09 02:49:21 +03:00
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
2002-12-04 02:57:45 +03:00
}
SSVAL ( outbuf , smb_vwv2 , nwritten ) ;
if ( large_writeX )
SSVAL ( outbuf , smb_vwv4 , ( nwritten > > 16 ) & 1 ) ;
if ( nwritten < ( ssize_t ) numtowrite ) {
SCVAL ( outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( outbuf , smb_err , ERRdiskfull ) ;
}
DEBUG ( 3 , ( " writeX fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
2005-09-03 11:19:28 +04:00
sync_file ( conn , fsp , write_through ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
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
int reply_lseek ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
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 ;
int outsize = 0 ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBlseek ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
CHECK_FSP ( fsp , conn ) ;
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
2002-12-04 02:57:45 +03:00
mode = SVAL ( inbuf , smb_vwv1 ) & 3 ;
/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
startpos = ( SMB_OFF_T ) IVALS ( 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 ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
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 ) {
END_PROFILE ( SMBlseek ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
}
1998-10-19 02:06:35 +04:00
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos = res ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 2 , 0 , True ) ;
2002-12-04 02:57:45 +03:00
SIVAL ( 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 ) ;
return ( outsize ) ;
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
int reply_flush ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
2003-08-19 05:26:43 +04:00
uint16 fnum = SVAL ( inbuf , smb_vwv0 ) ;
2001-08-24 08:56:33 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBflush ) ;
1996-05-04 11:50:46 +04:00
2003-08-19 05:26:43 +04:00
if ( fnum ! = 0xFFFF )
CHECK_FSP ( fsp , conn ) ;
2001-08-24 08:56:33 +04:00
if ( ! fsp ) {
file_sync_all ( conn ) ;
} else {
2005-09-03 11:19:28 +04:00
sync_file ( conn , fsp , True ) ;
2001-08-24 08:56:33 +04:00
}
DEBUG ( 3 , ( " flush \n " ) ) ;
END_PROFILE ( SMBflush ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_exit ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2000-10-06 07:21:49 +04:00
int outsize ;
START_PROFILE ( SMBexit ) ;
2003-08-19 05:53:45 +04:00
2006-03-16 01:52:59 +03:00
file_close_pid ( SVAL ( inbuf , smb_pid ) , SVAL ( inbuf , smb_uid ) ) ;
2003-08-19 05:53:45 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
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 ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
1999-12-13 16:27:58 +03:00
int reply_close ( connection_struct * conn , char * inbuf , char * outbuf , int size ,
int dum_buffsize )
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
int outsize = 0 ;
files_struct * fsp = NULL ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBclose ) ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
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 ) ) {
END_PROFILE ( SMBclose ) ;
1998-08-14 21:38:29 +04:00
return reply_pipe_close ( conn , inbuf , outbuf ) ;
2000-10-06 07:21:49 +04:00
}
1997-10-30 04:05:13 +03:00
1998-08-17 07:52:05 +04:00
fsp = file_fsp ( 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 ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2001-08-27 12:19:43 +04:00
return ERROR_DOS ( ERRDOS , ERRbadfid ) ;
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-03-06 02:40:03 +03:00
fsp_set_pending_modtime ( fsp ,
convert_time_t_to_timespec ( srv_make_unix_date3 ( 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-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-02-07 00:05:34 +03:00
return ERROR_NT ( status ) ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_writeclose ( connection_struct * conn ,
1999-12-13 16:27:58 +03:00
char * inbuf , char * outbuf , int size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
1998-09-11 05:24:30 +04:00
size_t numtowrite ;
ssize_t nwritten = - 1 ;
1998-08-14 21:38:29 +04:00
int outsize = 0 ;
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 ;
1998-08-17 07:52:05 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBwriteclose ) ;
1998-08-14 21:38:29 +04:00
1998-08-15 11:27:34 +04:00
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
1998-08-14 21:38:29 +04:00
numtowrite = SVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv2 ) ;
2007-03-06 02:40:03 +03:00
mtime = convert_time_t_to_timespec ( srv_make_unix_date3 ( inbuf + smb_vwv4 ) ) ;
1998-08-14 21:38:29 +04:00
data = smb_buf ( inbuf ) + 1 ;
2006-07-11 22:01:26 +04:00
if ( numtowrite & & is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) numtowrite , ( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2001-08-27 12:19:43 +04:00
return ERROR_DOS ( ERRDOS , ERRlock ) ;
2000-10-06 07:21:49 +04:00
}
1999-12-13 16:27:58 +03:00
nwritten = write_file ( 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 ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2003-01-09 02:49:21 +03:00
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
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 ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2007-02-07 00:05:34 +03:00
return ERROR_NT ( close_status ) ;
1999-12-13 16:27:58 +03:00
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
SSVAL ( outbuf , smb_vwv0 , nwritten ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_lock ( connection_struct * conn ,
1998-08-20 23:28:37 +04:00
char * inbuf , char * outbuf , int length , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
2000-04-11 23:44:54 +04:00
SMB_BIG_UINT count , offset ;
2001-08-27 12:19:43 +04:00
NTSTATUS status ;
1998-08-17 07:52:05 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
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
1998-08-15 11:27:34 +04:00
CHECK_FSP ( fsp , conn ) ;
1996-05-04 11:50:46 +04:00
2000-11-16 03:59:18 +03:00
release_level_2_oplocks_on_change ( fsp ) ;
2000-04-11 23:44:54 +04:00
count = ( SMB_BIG_UINT ) IVAL ( inbuf , smb_vwv1 ) ;
offset = ( SMB_BIG_UINT ) IVAL ( 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 ,
2006-07-18 01:09:02 +04:00
( uint32 ) SVAL ( inbuf , smb_pid ) ,
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 ) ) {
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlock ) ;
return ERROR_NT ( status ) ;
2000-10-06 07:21:49 +04:00
}
1998-08-01 02:39:15 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlock ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
2001-08-27 12:19:43 +04:00
int reply_unlock ( connection_struct * conn , char * inbuf , char * outbuf , int size ,
int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
2001-08-27 12:19:43 +04:00
SMB_BIG_UINT count , offset ;
NTSTATUS status ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBunlock ) ;
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
CHECK_FSP ( fsp , conn ) ;
count = ( SMB_BIG_UINT ) IVAL ( inbuf , smb_vwv1 ) ;
offset = ( SMB_BIG_UINT ) IVAL ( inbuf , smb_vwv3 ) ;
2007-05-14 17:01:28 +04:00
status = do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2006-07-11 22:01:26 +04:00
( uint32 ) SVAL ( inbuf , smb_pid ) ,
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 ) ) {
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
return ERROR_NT ( status ) ;
}
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 ) ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_tdis ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1998-08-14 21:38:29 +04:00
uint16 vuid ;
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
vuid = SVAL ( inbuf , smb_uid ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( ! conn ) {
DEBUG ( 4 , ( " Invalid connection in tdis \n " ) ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtdis ) ;
2001-08-27 12:19:43 +04:00
return ERROR_DOS ( ERRSRV , ERRinvnid ) ;
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
1998-08-14 21:38:29 +04:00
close_cnum ( conn , vuid ) ;
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtdis ) ;
1998-08-14 21:38:29 +04:00
return outsize ;
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
1998-08-14 21:38:29 +04:00
int reply_echo ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
int smb_reverb = SVAL ( inbuf , smb_vwv0 ) ;
int seq_num ;
2000-04-27 20:53:31 +04:00
unsigned int data_len = smb_buflen ( inbuf ) ;
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 1 , data_len , True ) ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBecho ) ;
2000-04-27 20:53:31 +04:00
2003-10-16 22:17:44 +04:00
if ( data_len > BUFFER_SIZE ) {
DEBUG ( 0 , ( " reply_echo: data_len too large. \n " ) ) ;
END_PROFILE ( SMBecho ) ;
return - 1 ;
}
2000-04-27 20:53:31 +04:00
1998-08-14 21:38:29 +04:00
/* copy any incoming data back out */
if ( data_len > 0 )
memcpy ( smb_buf ( outbuf ) , smb_buf ( 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 + + ) {
SSVAL ( outbuf , smb_vwv0 , seq_num ) ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
smb_setlen ( inbuf , outbuf , outsize - 4 ) ;
1996-05-04 11:50:46 +04:00
2005-06-09 22:15:23 +04:00
show_msg ( outbuf ) ;
2001-06-09 05:38:54 +04:00
if ( ! send_smb ( smbd_server_fd ( ) , 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
1999-12-13 16:27:58 +03:00
smb_echo_count + + ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBecho ) ;
1998-08-14 21:38:29 +04:00
return - 1 ;
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
1998-08-14 21:38:29 +04:00
int reply_printopen ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
int outsize = 0 ;
files_struct * fsp ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplopen ) ;
1998-08-14 21:38:29 +04:00
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
END_PROFILE ( SMBsplopen ) ;
2001-08-27 12:19:43 +04:00
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
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 ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2006-07-11 22:01:26 +04:00
return ( ERROR_NT ( status ) ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
1998-08-15 11:27:34 +04:00
SSVAL ( 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 ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_printclose ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1998-08-17 07:52:05 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
2007-02-07 00:05:34 +03:00
NTSTATUS status ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplclose ) ;
1996-05-04 11:50:46 +04:00
1998-08-15 11:27:34 +04:00
CHECK_FSP ( fsp , conn ) ;
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
END_PROFILE ( SMBsplclose ) ;
2007-01-02 19:40:41 +03:00
return ERROR_NT ( NT_STATUS_DOS ( ERRSRV , ERRerror ) ) ;
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 ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-02-07 00:05:34 +03:00
return ERROR_NT ( status ) ;
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 ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_printqueue ( connection_struct * conn ,
char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 2 , 3 , True ) ;
1998-08-14 21:38:29 +04:00
int max_count = SVAL ( inbuf , smb_vwv0 ) ;
int start_index = SVAL ( inbuf , smb_vwv1 ) ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplretq ) ;
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 ) ) {
END_PROFILE ( SMBsplretq ) ;
2001-08-27 12:19:43 +04:00
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
2000-10-06 07:21:49 +04:00
}
1998-08-14 21:38:29 +04:00
SSVAL ( outbuf , smb_vwv0 , 0 ) ;
SSVAL ( outbuf , smb_vwv1 , 0 ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( smb_buf ( outbuf ) , 0 , 1 ) ;
1998-08-14 21:38:29 +04:00
SSVAL ( smb_buf ( 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 ;
1998-08-14 21:38:29 +04:00
char * p = smb_buf ( outbuf ) + 3 ;
2001-12-29 12:52:24 +03:00
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 + + ) {
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 ) ;
2002-03-15 11:14:10 +03:00
srvstr_push ( outbuf , p + 12 , queue [ i ] . fs_user , 16 , STR_ASCII ) ;
1998-08-14 21:38:29 +04:00
p + = 28 ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( count > 0 ) {
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 2 , 28 * count + 3 , False ) ;
1998-08-14 21:38:29 +04:00
SSVAL ( outbuf , smb_vwv0 , count ) ;
SSVAL ( outbuf , smb_vwv1 , ( max_count > 0 ? first + count : first - 1 ) ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( smb_buf ( outbuf ) , 0 , 1 ) ;
1998-08-14 21:38:29 +04:00
SSVAL ( smb_buf ( outbuf ) , 1 , 28 * count ) ;
}
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 ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
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
1998-08-14 21:38:29 +04:00
int reply_printwrite ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int numtowrite ;
2007-04-20 02:40:32 +04:00
int outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
2002-12-04 02:57:45 +03:00
char * data ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBsplwr ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( ! CAN_PRINT ( conn ) ) {
END_PROFILE ( SMBsplwr ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
numtowrite = SVAL ( smb_buf ( inbuf ) , 1 ) ;
data = smb_buf ( inbuf ) + 3 ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( write_file ( fsp , data , - 1 , numtowrite ) ! = numtowrite ) {
END_PROFILE ( SMBsplwr ) ;
2003-01-09 02:49:21 +03:00
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
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 ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
return ( outsize ) ;
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
2000-07-25 17:15:16 +04:00
int reply_mkdir ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
{
2001-08-31 02:20:02 +04:00
pstring directory ;
int outsize ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2005-03-15 04:19:58 +03:00
SMB_STRUCT_STAT sbuf ;
2001-08-31 02:20:02 +04:00
START_PROFILE ( SMBmkdir ) ;
2000-07-25 17:15:16 +04:00
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , directory , smb_buf ( inbuf ) + 1 , sizeof ( directory ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBmkdir ) ;
return ERROR_NT ( status ) ;
}
2000-07-25 17:15:16 +04:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBmkdir ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2002-08-17 19:27:10 +04:00
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , directory , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-06 21:59:02 +03:00
END_PROFILE ( SMBmkdir ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
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 ) ) {
END_PROFILE ( SMBmkdir ) ;
return ERROR_NT ( status ) ;
}
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 ) ;
}
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBmkdir ) ;
2001-11-17 06:19:17 +03:00
return ERROR_NT ( status ) ;
2003-10-09 03:21:36 +04:00
}
2001-09-04 11:13:01 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1998-08-01 02:39:15 +04:00
2001-08-31 02:20:02 +04:00
DEBUG ( 3 , ( " mkdir %s ret=%d \n " , directory , outsize ) ) ;
1998-08-01 02:39:15 +04:00
2001-08-31 02:20:02 +04:00
END_PROFILE ( SMBmkdir ) ;
return ( outsize ) ;
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
2000-02-03 08:17:25 +03:00
static BOOL recursive_rmdir ( 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-01-05 20:42:54 +03: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 ) ) ) {
2001-08-31 02:20:02 +04:00
pstring fullname ;
SMB_STRUCT_STAT st ;
1997-09-17 05:29:53 +04:00
2001-08-31 02:20:02 +04:00
if ( ( strcmp ( dname , " . " ) = = 0 ) | | ( strcmp ( dname , " .. " ) = = 0 ) )
continue ;
1997-09-17 05:29:53 +04:00
2005-02-01 21:33:50 +03:00
if ( ! is_visible_file ( conn , directory , dname , & st , False ) )
continue ;
2001-08-31 02:20:02 +04:00
/* Construct the full name. */
if ( strlen ( directory ) + strlen ( dname ) + 1 > = sizeof ( fullname ) ) {
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
2001-08-31 02:20:02 +04:00
pstrcpy ( fullname , directory ) ;
pstrcat ( fullname , " / " ) ;
pstrcat ( fullname , dname ) ;
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-01-05 20:42:54 +03:00
if ( ! recursive_rmdir ( conn , fullname ) ) {
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 ;
}
}
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-02-07 00:05:34 +03:00
NTSTATUS rmdir_internals ( 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 ) ) ) {
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 ) ) ) {
pstring fullname ;
1999-12-13 16:27:58 +03:00
2007-01-05 20:42:54 +03:00
if ( ( strcmp ( dname , " . " ) = = 0 ) | | ( strcmp ( dname , " .. " ) = = 0 ) )
continue ;
if ( ! is_visible_file ( conn , directory , dname , & st , False ) )
continue ;
2001-08-31 02:20:02 +04:00
2007-01-05 20:42:54 +03:00
/* Construct the full name. */
if ( strlen ( directory ) + strlen ( dname ) + 1 > = sizeof ( fullname ) ) {
errno = ENOMEM ;
break ;
}
pstrcpy ( fullname , directory ) ;
pstrcat ( fullname , " / " ) ;
pstrcat ( fullname , dname ) ;
2007-01-13 02:47:16 +03:00
2007-01-05 20:42:54 +03:00
if ( SMB_VFS_LSTAT ( conn , fullname , & st ) ! = 0 )
break ;
if ( st . st_mode & S_IFDIR ) {
if ( lp_recursive_veto_delete ( SNUM ( conn ) ) ) {
if ( ! recursive_rmdir ( conn , fullname ) )
2001-08-31 02:20:02 +04:00
break ;
}
2007-01-05 20:42:54 +03:00
if ( SMB_VFS_RMDIR ( conn , fullname ) ! = 0 )
break ;
} else if ( SMB_VFS_UNLINK ( conn , fullname ) ! = 0 )
break ;
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
1998-08-14 21:38:29 +04:00
int reply_rmdir ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
pstring directory ;
int outsize = 0 ;
SMB_STRUCT_STAT sbuf ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBrmdir ) ;
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , directory , smb_buf ( inbuf ) + 1 , sizeof ( directory ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBrmdir ) ;
return ERROR_NT ( status ) ;
}
2002-12-04 02:57:45 +03:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2002-12-04 02:57:45 +03:00
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , directory , False , NULL , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-11 21:54:23 +04:00
END_PROFILE ( SMBrmdir ) ;
2007-01-13 02:47:16 +03:00
return ERROR_NT ( status ) ;
2004-06-11 21:54:23 +04:00
}
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-16 23:49:51 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-01-17 05:09:37 +03:00
return ERROR_NT ( status ) ;
2002-12-04 02:57:45 +03:00
}
2007-01-16 23:49:51 +03:00
dptr_closepath ( directory , SVAL ( inbuf , smb_pid ) ) ;
2007-02-07 00:05:34 +03:00
status = rmdir_internals ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-02-07 00:05:34 +03:00
return ERROR_NT ( status ) ;
2002-12-04 02:57:45 +03:00
}
1997-08-21 00:32:23 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " rmdir %s \n " , directory ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBrmdir ) ;
return ( outsize ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2002-09-25 19:19:00 +04:00
Resolve wildcards in a filename rename .
2004-03-12 17:37:37 +03:00
Note that name is in UNIX charset and thus potentially can be more
than fstring buffer ( 255 bytes ) especially in default UTF - 8 case .
Therefore , we use pstring inside and all calls should ensure that
name2 is at least pstring - long ( they do already )
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2003-04-12 03:48:24 +04:00
static BOOL resolve_wildcards ( const char * name1 , char * name2 )
1996-05-04 11:50:46 +04:00
{
2004-03-12 17:37:37 +03:00
pstring root1 , root2 ;
pstring ext1 , ext2 ;
2003-04-12 03:48:24 +04:00
char * p , * p2 , * pname1 , * pname2 ;
2004-03-12 17:37:37 +03:00
int available_space , actual_space ;
2003-04-12 03:48:24 +04:00
pname1 = strrchr_m ( name1 , ' / ' ) ;
pname2 = strrchr_m ( name2 , ' / ' ) ;
2002-12-04 02:57:45 +03:00
2003-04-12 03:48:24 +04:00
if ( ! pname1 | | ! pname2 )
2002-12-04 02:57:45 +03:00
return ( False ) ;
2004-03-12 17:37:37 +03:00
pstrcpy ( root1 , pname1 ) ;
pstrcpy ( root2 , pname2 ) ;
2002-12-04 02:57:45 +03:00
p = strrchr_m ( root1 , ' . ' ) ;
if ( p ) {
* p = 0 ;
2004-03-12 17:37:37 +03:00
pstrcpy ( ext1 , p + 1 ) ;
2002-12-04 02:57:45 +03:00
} else {
2004-03-12 17:37:37 +03:00
pstrcpy ( ext1 , " " ) ;
2002-12-04 02:57:45 +03:00
}
p = strrchr_m ( root2 , ' . ' ) ;
if ( p ) {
* p = 0 ;
2004-03-12 17:37:37 +03:00
pstrcpy ( ext2 , p + 1 ) ;
2002-12-04 02:57:45 +03:00
} else {
2004-03-12 17:37:37 +03:00
pstrcpy ( ext2 , " " ) ;
2002-12-04 02:57:45 +03:00
}
p = root1 ;
p2 = root2 ;
while ( * p2 ) {
if ( * p2 = = ' ? ' ) {
* p2 = * p ;
p2 + + ;
2004-04-03 05:21:13 +04:00
} else if ( * p2 = = ' * ' ) {
pstrcpy ( p2 , p ) ;
break ;
2002-12-04 02:57:45 +03:00
} else {
p2 + + ;
}
if ( * p )
p + + ;
}
p = ext1 ;
p2 = ext2 ;
while ( * p2 ) {
if ( * p2 = = ' ? ' ) {
* p2 = * p ;
p2 + + ;
2004-04-03 05:21:13 +04:00
} else if ( * p2 = = ' * ' ) {
pstrcpy ( p2 , p ) ;
break ;
2002-12-04 02:57:45 +03:00
} else {
p2 + + ;
}
if ( * p )
p + + ;
}
2003-04-12 03:48:24 +04:00
available_space = sizeof ( pstring ) - PTR_DIFF ( pname2 , name2 ) ;
2002-12-04 02:57:45 +03:00
if ( ext2 [ 0 ] ) {
2004-03-12 17:37:37 +03:00
actual_space = snprintf ( pname2 , available_space - 1 , " %s.%s " , root2 , ext2 ) ;
if ( actual_space > = available_space - 1 ) {
DEBUG ( 1 , ( " resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes) \n " ,
actual_space - available_space ) ) ;
}
2003-04-14 03:45:35 +04:00
} else {
2003-04-23 17:27:35 +04:00
pstrcpy_base ( pname2 , root2 , name2 ) ;
2002-12-04 02:57:45 +03:00
}
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-14 20:46:29 +03:00
static void rename_open_files ( connection_struct * conn , struct share_mode_lock * lck ,
SMB_DEV_T dev , SMB_INO_T inode , const char * newname )
2003-08-16 06:34:03 +04:00
{
files_struct * fsp ;
BOOL did_rename = False ;
for ( fsp = file_find_di_first ( dev , inode ) ; 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 ;
}
2003-08-16 06:34:03 +04:00
DEBUG ( 10 , ( " rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s \n " ,
fsp - > fnum , ( unsigned int ) fsp - > dev , ( double ) fsp - > inode ,
fsp - > fsp_name , newname ) ) ;
string_set ( & fsp - > fsp_name , newname ) ;
did_rename = True ;
}
2005-12-13 21:11:50 +03:00
if ( ! did_rename ) {
2003-08-16 06:34:03 +04:00
DEBUG ( 10 , ( " rename_open_files: no open files on dev %x, inode %.0f for %s \n " ,
( unsigned int ) dev , ( double ) inode , 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 > .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL rename_path_prefix_equal ( const char * src , const char * dest )
{
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 ] = = ' / ' ) ;
}
2003-08-16 06:34:03 +04:00
/****************************************************************************
Rename an open file - given an fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-01-30 21:16:51 +03:00
NTSTATUS rename_internals_fsp ( connection_struct * conn , files_struct * fsp , pstring newname , uint32 attrs , BOOL replace_if_exists )
2003-08-16 06:34:03 +04:00
{
SMB_STRUCT_STAT sbuf ;
pstring newname_last_component ;
2007-01-13 02:47:16 +03:00
NTSTATUS status = NT_STATUS_OK ;
2003-08-16 06:34:03 +04:00
BOOL dest_exists ;
2005-12-14 20:46:29 +03:00
struct share_mode_lock * lck = NULL ;
2003-08-16 06:34:03 +04:00
ZERO_STRUCT ( sbuf ) ;
2007-01-13 02:47:16 +03:00
status = unix_convert ( conn , newname , False , newname_last_component , & sbuf ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-02-28 03:56:42 +03:00
}
2004-02-25 04:35: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
status = check_name ( conn , newname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2003-08-16 06:34:03 +04:00
/* Ensure newname contains a '/' */
if ( strrchr_m ( newname , ' / ' ) = = 0 ) {
pstring tmpstr ;
pstrcpy ( tmpstr , " ./ " ) ;
pstrcat ( tmpstr , newname ) ;
pstrcpy ( newname , tmpstr ) ;
}
/*
* 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 ;
pstring newname_modified_last_component ;
/*
* Get the last component of the modified name .
* Note that we guarantee that newname contains a ' / '
* character above .
*/
p = strrchr_m ( newname , ' / ' ) ;
pstrcpy ( newname_modified_last_component , p + 1 ) ;
if ( strcsequal ( newname_modified_last_component ,
newname_last_component ) = = False ) {
/*
* Replace the modified last component with
* the original .
*/
pstrcpy ( p + 1 , newname_last_component ) ;
}
}
/*
* 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 ;
}
dest_exists = vfs_object_exist ( conn , newname , NULL ) ;
if ( ! replace_if_exists & & dest_exists ) {
DEBUG ( 3 , ( " rename_internals_fsp: dest exists doing rename %s -> %s \n " ,
fsp - > fsp_name , newname ) ) ;
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2007-01-13 02:47:16 +03:00
status = can_rename ( conn , newname , attrs , & sbuf ) ;
2003-08-16 06:34:03 +04:00
2007-01-13 02:47:16 +03:00
if ( dest_exists & & ! NT_STATUS_IS_OK ( status ) ) {
2003-08-16 06:34:03 +04:00
DEBUG ( 3 , ( " rename_internals: 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 ;
}
2005-12-14 20:46:29 +03:00
lck = get_share_mode_lock ( NULL , fsp - > dev , fsp - > inode , NULL , NULL ) ;
2003-08-16 06:34:03 +04:00
if ( SMB_VFS_RENAME ( conn , fsp - > fsp_name , newname ) = = 0 ) {
DEBUG ( 3 , ( " rename_internals_fsp: succeeded doing rename on %s -> %s \n " ,
fsp - > fsp_name , newname ) ) ;
2005-12-14 20:46:29 +03:00
rename_open_files ( conn , lck , fsp - > dev , fsp - > inode , newname ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2003-08-16 06:34:03 +04:00
return NT_STATUS_OK ;
}
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
}
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
}
2007-01-31 17:24:29 +03:00
/*
* Do the notify calls from a rename
*/
static void notify_rename ( connection_struct * conn , BOOL is_dir ,
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 ) ;
}
}
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
code .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-05 00:11: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
NTSTATUS rename_internals ( connection_struct * conn ,
pstring name ,
pstring newname ,
uint32 attrs ,
BOOL replace_if_exists ,
BOOL src_has_wild ,
BOOL dest_has_wild )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
pstring directory ;
pstring mask ;
2004-03-03 23:55:59 +03:00
pstring last_component_src ;
pstring last_component_dest ;
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 ;
2005-12-14 20:46:29 +03:00
struct share_mode_lock * lck = NULL ;
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 ;
pstring destname ;
1998-08-14 21:38:29 +04:00
* directory = * mask = 0 ;
2003-08-16 06:34:03 +04:00
ZERO_STRUCT ( sbuf1 ) ;
ZERO_STRUCT ( sbuf2 ) ;
2004-03-03 23:55:59 +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 = unix_convert ( conn , name , src_has_wild , 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
}
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 = unix_convert ( conn , newname , dest_has_wild , 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
1999-12-13 16:27:58 +03:00
* strings . Note that unix_convert may have stripped off a
1998-08-14 21:38:29 +04:00
* leading . / from both name and newname if the rename is
* 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 ) {
pstrcpy ( directory , " . " ) ;
pstrcpy ( mask , name ) ;
} else {
* p = 0 ;
pstrcpy ( directory , name ) ;
pstrcpy ( mask , p + 1 ) ;
* 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 ) ) {
2006-07-11 22:01:26 +04:00
mangle_check_cache ( mask , sizeof ( pstring ) - 1 , conn - > params ) ;
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 ) {
1998-08-14 21:38:29 +04:00
/*
* No wildcards - just process the one file .
*/
2006-07-11 22:01:26 +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. */
pstrcat ( directory , " / " ) ;
pstrcat ( directory , mask ) ;
/* Ensure newname contains a '/' also */
2001-07-04 11:36:09 +04:00
if ( strrchr_m ( newname , ' / ' ) = = 0 ) {
1998-08-14 21:38:29 +04:00
pstring tmpstr ;
pstrcpy ( tmpstr , " ./ " ) ;
pstrcat ( tmpstr , newname ) ;
pstrcpy ( newname , tmpstr ) ;
}
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, "
" last_component_dest = %s, is_8_3 = %d \n " ,
conn - > case_sensitive , conn - > case_preserve ,
conn - > short_case_preserve , directory ,
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
/* Ensure the source name is valid for us to access. */
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/* The dest name still may have wildcards. */
if ( dest_has_wild ) {
if ( ! resolve_wildcards ( directory , newname ) ) {
DEBUG ( 6 , ( " rename_internals: resolve_wildcards %s %s failed \n " ,
directory , newname ) ) ;
return NT_STATUS_NO_MEMORY ;
}
}
1998-08-14 21:38:29 +04:00
/*
* Check for special case with case preserving and not
* case sensitive , if directory and newname are identical ,
* and 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 ) & &
1998-08-14 21:38:29 +04:00
( is_short_name = = False ) ) | |
2004-05-07 22:37:47 +04:00
( ( conn - > short_case_preserve = = True ) & &
1998-08-14 21:38:29 +04:00
( is_short_name = = True ) ) ) & &
strcsequal ( directory , newname ) ) {
2004-03-03 23:55:59 +03:00
pstring modified_last_component ;
1998-08-14 21:38:29 +04:00
/*
* Get the last component of the modified name .
* Note that we guarantee that newname contains a ' / '
* character above .
*/
2001-07-04 11:36:09 +04:00
p = strrchr_m ( newname , ' / ' ) ;
2004-03-03 23:55:59 +03:00
pstrcpy ( modified_last_component , p + 1 ) ;
1998-08-14 21:38:29 +04:00
2004-03-03 23:55:59 +03:00
if ( strcsequal ( modified_last_component ,
last_component_dest ) = = False ) {
1998-08-14 21:38:29 +04:00
/*
* Replace the modified last component with
* the original .
*/
2004-03-03 23:55:59 +03:00
pstrcpy ( p + 1 , last_component_dest ) ;
1998-08-14 21:38:29 +04:00
}
}
2002-01-05 00:11: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
/* Ensure the dest name is valid for us to access. */
status = check_name ( conn , newname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2002-01-05 00:11:35 +03:00
/*
* The source object must exist .
*/
2000-11-15 00:56:32 +03:00
2002-03-23 05:57:44 +03:00
if ( ! vfs_object_exist ( conn , directory , & sbuf1 ) ) {
2007-01-31 15:55:39 +03:00
DEBUG ( 3 , ( " rename_internals: source doesn't exist "
" doing rename %s -> %s \n " ,
2002-01-05 00:11:35 +03:00
directory , newname ) ) ;
2007-01-31 15:55:39 +03:00
if ( errno = = ENOTDIR | | errno = = EISDIR
| | errno = = ENOENT ) {
2002-01-05 00:11:35 +03:00
/*
2007-01-31 15:55:39 +03:00
* Must return different errors depending on
* whether the parent directory existed or
* not .
2002-01-05 00:11:35 +03:00
*/
p = strrchr_m ( directory , ' / ' ) ;
if ( ! p )
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
* p = ' \0 ' ;
if ( vfs_object_exist ( conn , directory , NULL ) )
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
}
2007-01-13 02:47:16 +03:00
status = map_nt_error_from_unix ( errno ) ;
2007-01-31 15:55:39 +03:00
DEBUG ( 3 , ( " rename_internals: Error %s rename %s -> "
" %s \n " , nt_errstr ( status ) , directory ,
newname ) ) ;
1997-01-13 22:41:08 +03:00
2007-01-13 02:47:16 +03:00
return status ;
2004-02-28 03:56:42 +03:00
}
2007-01-13 02:47:16 +03:00
status = can_rename ( conn , directory , attrs , & sbuf1 ) ;
2002-01-05 00:11:35 +03:00
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-31 15:55:39 +03:00
DEBUG ( 3 , ( " rename_internals: Error %s rename %s -> "
" %s \n " , nt_errstr ( status ) , directory ,
newname ) ) ;
2007-01-13 02:47:16 +03:00
return status ;
2002-01-05 00:11:35 +03:00
}
/*
* If the src and dest names are identical - including case ,
* don ' t do the rename , just return success .
*/
if ( strcsequal ( directory , newname ) ) {
2007-01-31 15:55:39 +03:00
rename_open_files ( conn , NULL , sbuf1 . st_dev ,
sbuf1 . st_ino , newname ) ;
DEBUG ( 3 , ( " rename_internals: identical names in "
" rename %s - returning success \n " ,
directory ) ) ;
2002-01-05 00:11:35 +03:00
return NT_STATUS_OK ;
1998-08-14 21:38:29 +04:00
}
2002-01-05 00:11:35 +03:00
if ( ! replace_if_exists & & vfs_object_exist ( conn , newname , NULL ) ) {
2007-01-31 15:55:39 +03:00
DEBUG ( 3 , ( " rename_internals: dest exists doing "
" rename %s -> %s \n " , directory , newname ) ) ;
2002-01-05 00:11:35 +03:00
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2005-09-27 21:42:11 +04:00
if ( rename_path_prefix_equal ( directory , newname ) ) {
return NT_STATUS_SHARING_VIOLATION ;
}
2007-01-31 15:55:39 +03:00
lck = get_share_mode_lock ( NULL , sbuf1 . st_dev , sbuf1 . st_ino ,
NULL , NULL ) ;
2005-12-14 20:46:29 +03:00
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_RENAME ( conn , directory , newname ) = = 0 ) {
2007-01-31 15:55:39 +03:00
DEBUG ( 3 , ( " rename_internals: succeeded doing rename "
" on %s -> %s \n " , directory , newname ) ) ;
rename_open_files ( conn , lck , sbuf1 . st_dev ,
sbuf1 . st_ino , newname ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2007-01-31 17:24:29 +03:00
notify_rename ( conn , S_ISDIR ( sbuf1 . st_mode ) ,
directory , newname ) ;
2002-01-05 00:11:35 +03:00
return NT_STATUS_OK ;
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2007-01-17 05:09:37 +03:00
if ( errno = = ENOTDIR | | errno = = EISDIR ) {
2007-01-13 02:47:16 +03:00
status = NT_STATUS_OBJECT_NAME_COLLISION ;
2007-01-17 05:09:37 +03:00
} else {
2007-01-13 02:47:16 +03:00
status = map_nt_error_from_unix ( errno ) ;
2007-01-17 05:09:37 +03:00
}
2002-01-05 00:11:35 +03:00
DEBUG ( 3 , ( " rename_internals: Error %s rename %s -> %s \n " ,
2007-01-13 02:47:16 +03:00
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 , " ????????.??? " ) ) {
pstrcpy ( mask , " * " ) ;
}
2005-06-25 07:03:44 +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-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
dir_hnd = OpenDir ( conn , directory , mask , attrs ) ;
if ( dir_hnd = = NULL ) {
return map_nt_error_from_unix ( errno ) ;
}
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
status = NT_STATUS_NO_SUCH_FILE ;
/*
* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
* - gentest fix . JRA
*/
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
while ( ( dname = ReadDirName ( dir_hnd , & offset ) ) ) {
pstring fname ;
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
pstrcpy ( fname , dname ) ;
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
/* Quick check for "." and ".." */
if ( fname [ 0 ] = = ' . ' ) {
if ( ! fname [ 1 ] | | ( fname [ 1 ] = = ' . ' & & ! fname [ 2 ] ) ) {
if ( attrs & aDIR ) {
sysdir_entry = True ;
} else {
continue ;
2004-02-25 04:35:14 +03:00
}
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
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 ( ! mask_match ( fname , mask , conn - > case_sensitive ) ) {
continue ;
}
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
if ( sysdir_entry ) {
status = NT_STATUS_OBJECT_NAME_INVALID ;
break ;
}
2004-03-03 23:55:59 +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 = NT_STATUS_ACCESS_DENIED ;
slprintf ( fname , sizeof ( fname ) - 1 , " %s/%s " , directory , dname ) ;
/* Ensure the source name is valid for us to access. */
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! vfs_object_exist ( conn , fname , & sbuf1 ) ) {
status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
DEBUG ( 6 , ( " rename %s failed. Error %s \n " ,
fname , nt_errstr ( status ) ) ) ;
continue ;
}
status = can_rename ( conn , fname , attrs , & sbuf1 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 6 , ( " rename %s refused \n " , fname ) ) ;
continue ;
}
pstrcpy ( destname , newname ) ;
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
if ( ! resolve_wildcards ( fname , destname ) ) {
DEBUG ( 6 , ( " resolve_wildcards %s %s failed \n " ,
fname , destname ) ) ;
continue ;
}
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
/* Ensure the dest name is valid for us to access. */
status = check_name ( conn , destname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-04-02 23:51: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
if ( strcsequal ( fname , destname ) ) {
rename_open_files ( conn , NULL , sbuf1 . st_dev ,
sbuf1 . st_ino , newname ) ;
DEBUG ( 3 , ( " rename_internals: identical names "
" in wildcard rename %s - success \n " ,
fname ) ) ;
count + + ;
status = NT_STATUS_OK ;
continue ;
}
if ( ! replace_if_exists & & vfs_file_exist ( conn , destname , NULL ) ) {
DEBUG ( 6 , ( " file_exist %s \n " , destname ) ) ;
status = NT_STATUS_OBJECT_NAME_COLLISION ;
continue ;
}
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
if ( rename_path_prefix_equal ( fname , destname ) ) {
return NT_STATUS_SHARING_VIOLATION ;
}
2005-09-27 21:42:11 +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
lck = get_share_mode_lock ( NULL , sbuf1 . st_dev ,
sbuf1 . st_ino , NULL , NULL ) ;
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
if ( ! SMB_VFS_RENAME ( conn , fname , destname ) ) {
rename_open_files ( conn , lck , sbuf1 . st_dev ,
sbuf1 . st_ino , newname ) ;
count + + ;
status = NT_STATUS_OK ;
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
TALLOC_FREE ( lck ) ;
DEBUG ( 3 , ( " rename_internals: doing rename on %s -> "
" %s \n " , fname , 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-01-13 02:47:16 +03:00
return status ;
1998-07-11 04:28:34 +04:00
}
/****************************************************************************
Reply to a mv .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-04 11:13:01 +04:00
int reply_mv ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size ,
int dum_buffsize )
1998-07-11 04:28:34 +04:00
{
2001-09-04 11:13:01 +04:00
int outsize = 0 ;
pstring name ;
pstring newname ;
char * p ;
2005-06-25 07:03:44 +04:00
uint32 attrs = SVAL ( inbuf , smb_vwv0 ) ;
2001-09-04 11:13:01 +04:00
NTSTATUS 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
BOOL src_has_wcard = False ;
BOOL dest_has_wcard = False ;
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
2001-09-04 11:13:01 +04:00
p = smb_buf ( inbuf ) + 1 ;
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
p + = srvstr_get_path_wcard ( inbuf , name , p , sizeof ( name ) , 0 , STR_TERMINATE , & status , & src_has_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBmv ) ;
return ERROR_NT ( status ) ;
}
2001-09-04 11:13:01 +04:00
p + + ;
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
p + = srvstr_get_path_wcard ( inbuf , newname , p , sizeof ( newname ) , 0 , STR_TERMINATE , & status , & dest_has_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBmv ) ;
return ERROR_NT ( status ) ;
}
2001-09-04 11:13:01 +04:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath_wcard ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , name , & src_has_wcard ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBmv ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
status = resolve_dfspath_wcard ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , newname , & dest_has_wcard ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBmv ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2001-09-04 11:13:01 +04:00
DEBUG ( 3 , ( " reply_mv : %s -> %s \n " , name , 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 = rename_internals ( conn , name , newname , attrs , False , src_has_wcard , dest_has_wcard ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBmv ) ;
2004-06-08 20:14:31 +04:00
if ( open_was_deferred ( SVAL ( inbuf , smb_mid ) ) ) {
/* We have re-scheduled this call. */
return - 1 ;
}
2001-09-04 11:13:01 +04:00
return ERROR_NT ( status ) ;
}
2000-09-20 23:00:21 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 11:13:01 +04:00
END_PROFILE ( SMBmv ) ;
return ( outsize ) ;
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
*/
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
NTSTATUS copy_file ( connection_struct * conn ,
char * src ,
char * dest1 ,
int ofun ,
int count ,
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 ;
pstring dest ;
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 ;
2004-04-02 22:46:19 +04:00
2001-09-04 23:10:30 +04:00
pstrcpy ( dest , dest1 ) ;
if ( target_is_directory ) {
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
}
2001-09-04 23:10:30 +04:00
pstrcat ( dest , " / " ) ;
pstrcat ( dest , p ) ;
}
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-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-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
2006-07-11 22:01:26 +04:00
status = open_file_ntcreate ( conn , 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-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
2006-07-11 22:01:26 +04:00
status = open_file_ntcreate ( conn , 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
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 ;
}
}
1996-05-04 11:50:46 +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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_copy ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int outsize = 0 ;
pstring name ;
pstring directory ;
pstring mask , newname ;
char * p ;
int count = 0 ;
int error = ERRnoaccess ;
int err = 0 ;
int tid2 = SVAL ( inbuf , smb_vwv0 ) ;
int ofun = SVAL ( inbuf , smb_vwv1 ) ;
int flags = SVAL ( inbuf , smb_vwv2 ) ;
BOOL target_is_directory = False ;
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
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 ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcopy ) ;
* directory = * mask = 0 ;
p = smb_buf ( inbuf ) ;
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
p + = srvstr_get_path_wcard ( inbuf , name , p , sizeof ( name ) , 0 , STR_TERMINATE , & status , & source_has_wild ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_NT ( 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
p + = srvstr_get_path_wcard ( inbuf , newname , p , sizeof ( newname ) , 0 , STR_TERMINATE , & status , & dest_has_wild ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_NT ( status ) ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " reply_copy : %s -> %s \n " , name , newname ) ) ;
1996-05-04 11:50:46 +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 " ) ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBcopy ) ;
2002-12-04 02:57:45 +03:00
return ERROR_DOS ( ERRSRV , ERRinvdevice ) ;
1999-12-13 16:27:58 +03:00
}
1996-05-04 11:50:46 +04:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath_wcard ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , name , & source_has_wild ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBcopy ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
status = resolve_dfspath_wcard ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , newname , & dest_has_wild ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( SMBcopy ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
1996-05-04 11:50:46 +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 = unix_convert ( conn , name , source_has_wild , NULL , & sbuf1 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_NT ( 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
status = unix_convert ( conn , newname , dest_has_wild , NULL , & sbuf2 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_NT ( status ) ;
}
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 ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_DOS ( ERRDOS , ERRbadfile ) ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( ( flags & 2 ) & & ! target_is_directory ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_DOS ( ERRDOS , ERRbadpath ) ;
}
if ( ( flags & ( 1 < < 5 ) ) & & VALID_STAT_OF_DIR ( sbuf1 ) ) {
/* wants a tree copy! XXXX */
DEBUG ( 3 , ( " Rejecting tree copy \n " ) ) ;
END_PROFILE ( SMBcopy ) ;
return ERROR_DOS ( ERRSRV , ERRerror ) ;
}
p = strrchr_m ( name , ' / ' ) ;
if ( ! p ) {
pstrcpy ( directory , " ./ " ) ;
pstrcpy ( mask , name ) ;
} else {
* p = 0 ;
pstrcpy ( directory , name ) ;
pstrcpy ( mask , p + 1 ) ;
}
/*
* 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 ) ) {
2006-07-11 22:01:26 +04:00
mangle_check_cache ( mask , sizeof ( pstring ) - 1 , conn - > params ) ;
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 ) {
2002-12-04 02:57:45 +03:00
pstrcat ( directory , " / " ) ;
pstrcat ( directory , 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 ) {
if ( ! resolve_wildcards ( directory , newname ) ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
}
}
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-01-05 16:13:15 +03:00
return ERROR_NT ( status ) ;
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 , newname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ERROR_NT ( status ) ;
}
status = copy_file ( conn , directory , newname , ofun ,
count , target_is_directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcopy ) ;
return ERROR_NT ( status ) ;
} 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 ;
2003-03-18 01:56:13 +03:00
const char * dname ;
2007-01-17 05:09:37 +03:00
long offset = 0 ;
2002-12-04 02:57:45 +03:00
pstring destname ;
2005-06-25 07:03:44 +04:00
if ( strequal ( mask , " ????????.??? " ) )
pstrcpy ( mask , " * " ) ;
2007-01-17 05:09:37 +03:00
status = check_name ( conn , directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ERROR_NT ( status ) ;
}
dir_hnd = OpenDir ( conn , directory , mask , 0 ) ;
if ( dir_hnd = = NULL ) {
status = map_nt_error_from_unix ( errno ) ;
return ERROR_NT ( status ) ;
}
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 ) ) ) {
pstring fname ;
pstrcpy ( fname , dname ) ;
2002-12-04 02:57:45 +03:00
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-01-17 05:09:37 +03:00
if ( ! mask_match ( fname , mask , conn - > case_sensitive ) ) {
continue ;
}
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
error = ERRnoaccess ;
slprintf ( fname , sizeof ( fname ) - 1 , " %s/%s " , directory , dname ) ;
pstrcpy ( destname , 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
if ( ! resolve_wildcards ( fname , destname ) ) {
continue ;
}
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ERROR_NT ( status ) ;
}
status = check_name ( conn , destname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ERROR_NT ( status ) ;
}
DEBUG ( 3 , ( " reply_copy : doing copy on %s -> %s \n " , fname , destname ) ) ;
status = copy_file ( conn , fname , destname , ofun ,
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-01-17 05:09:37 +03:00
CloseDir ( dir_hnd ) ;
2002-12-04 02:57:45 +03:00
}
if ( count = = 0 ) {
if ( err ) {
/* Error on close... */
errno = err ;
END_PROFILE ( SMBcopy ) ;
return ( UNIXERROR ( ERRHRD , ERRgeneral ) ) ;
}
2007-01-13 02:47:16 +03:00
END_PROFILE ( SMBcopy ) ;
return ERROR_DOS ( ERRDOS , error ) ;
2002-12-04 02:57:45 +03:00
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2002-12-04 02:57:45 +03:00
SSVAL ( outbuf , smb_vwv0 , count ) ;
END_PROFILE ( SMBcopy ) ;
return ( outsize ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a setdir .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
1998-08-14 21:38:29 +04:00
int reply_setdir ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int snum ;
int outsize = 0 ;
pstring newdir ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( pathworks_setdir ) ;
snum = SNUM ( conn ) ;
if ( ! CAN_SETDIR ( snum ) ) {
END_PROFILE ( pathworks_setdir ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
2005-10-31 23:11:58 +03:00
srvstr_get_path ( inbuf , newdir , smb_buf ( inbuf ) + 1 , sizeof ( newdir ) , 0 , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( pathworks_setdir ) ;
return ERROR_NT ( status ) ;
}
2002-12-04 02:57:45 +03:00
2007-03-12 20:55:24 +03:00
status = resolve_dfspath ( conn , SVAL ( inbuf , smb_flg2 ) & FLAGS2_DFS_PATHNAMES , newdir ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-08 01:12:58 +03:00
END_PROFILE ( pathworks_setdir ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
return ERROR_BOTH ( NT_STATUS_PATH_NOT_COVERED , ERRSRV , ERRbadpath ) ;
}
return ERROR_NT ( status ) ;
2007-03-08 01:12:58 +03:00
}
2005-03-16 02:17:03 +03:00
2007-01-16 23:53:50 +03:00
if ( strlen ( newdir ) ! = 0 ) {
if ( ! vfs_directory_exist ( conn , newdir , NULL ) ) {
END_PROFILE ( pathworks_setdir ) ;
return ERROR_DOS ( ERRDOS , ERRbadpath ) ;
}
set_conn_connectpath ( conn , newdir ) ;
2002-12-04 02:57:45 +03:00
}
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
2002-12-04 02:57:45 +03:00
SCVAL ( outbuf , smb_reh , CVAL ( inbuf , smb_reh ) ) ;
DEBUG ( 3 , ( " setdir %s \n " , newdir ) ) ;
END_PROFILE ( pathworks_setdir ) ;
return ( outsize ) ;
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-11 22:01:26 +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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-11 23:44:54 +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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-11 23:44:54 +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
2005-09-30 21:13:37 +04:00
int reply_lockingX ( connection_struct * conn , char * inbuf , char * outbuf ,
int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
2001-08-27 12:19:43 +04:00
files_struct * fsp = file_fsp ( inbuf , smb_vwv2 ) ;
unsigned char locktype = CVAL ( inbuf , smb_vwv3 ) ;
unsigned char oplocklevel = CVAL ( inbuf , smb_vwv3 + 1 ) ;
uint16 num_ulocks = SVAL ( inbuf , smb_vwv6 ) ;
uint16 num_locks = SVAL ( inbuf , smb_vwv7 ) ;
SMB_BIG_UINT count = 0 , offset = 0 ;
2006-07-11 22:01:26 +04:00
uint32 lock_pid ;
2001-08-27 12:19:43 +04:00
int32 lock_timeout = IVAL ( inbuf , smb_vwv4 ) ;
int i ;
char * data ;
2005-09-30 21:13:37 +04:00
BOOL large_file_format =
( locktype & LOCKING_ANDX_LARGE_FILES ) ? True : False ;
2001-08-27 12:19:43 +04:00
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 ) ;
CHECK_FSP ( fsp , conn ) ;
data = smb_buf ( 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 ) */
2006-07-11 22:01:26 +04:00
return ERROR_NT ( NT_STATUS_DOS ( ERRDOS , ERRnoatomiclocks ) ) ;
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. */
BOOL break_to_none = ( oplocklevel = = 0 ) ;
2005-09-30 21:13:37 +04:00
BOOL result ;
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 ) ;
return - 1 ;
} else {
END_PROFILE ( SMBlockingX ) ;
return ERROR_DOS ( ERRDOS , ERRlock ) ;
}
}
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 . */
if ( CVAL ( 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 " ,
2001-08-27 12:19:43 +04:00
( unsigned int ) CVAL ( inbuf , smb_vwv0 ) ) ) ;
END_PROFILE ( SMBlockingX ) ;
return - 1 ;
}
}
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 ) ;
/* 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 ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
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 ) ;
return ERROR_NT ( status ) ;
}
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 ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
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 ) ;
return ERROR_NT ( NT_STATUS_DOS ( ERRDOS , ERRcancelviolation ) ) ;
}
}
/* Remove a matching pending lock. */
status = do_lock_cancel ( fsp ,
lock_pid ,
count ,
offset ,
WINDOWS_LOCK ) ;
} else {
2006-07-18 05:05:51 +04:00
BOOL blocking_lock = lock_timeout ? True : False ;
BOOL defer_lock = False ;
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 ,
inbuf , length ,
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 ) ;
return - 1 ;
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 ) ;
return ERROR_NT ( status ) ;
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 ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
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 ) ;
return ERROR_NT ( status ) ;
}
1998-09-11 05:24:30 +04:00
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 2 , 0 , True ) ;
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 ) ;
2001-08-27 12:19:43 +04:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
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 .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-19 04:56:03 +04:00
1998-08-14 21:38:29 +04:00
int reply_readbmpx ( connection_struct * conn , char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
2001-10-19 04:56:03 +04:00
ssize_t nread = - 1 ;
ssize_t total_read ;
char * data ;
SMB_OFF_T startpos ;
int outsize ;
size_t maxcount ;
int max_per_packet ;
size_t tcount ;
int pad ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBreadBmpx ) ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
/* this function doesn't seem to work - disable by default */
if ( ! lp_readbmpx ( ) ) {
END_PROFILE ( SMBreadBmpx ) ;
return ERROR_DOS ( ERRSRV , ERRuseSTD ) ;
}
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 8 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_READ ( fsp , inbuf ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv1 ) ;
2001-10-19 04:56:03 +04:00
maxcount = SVAL ( inbuf , smb_vwv3 ) ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
data = smb_buf ( outbuf ) ;
pad = ( ( long ) data ) % 4 ;
if ( pad )
pad = 4 - pad ;
data + = pad ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
max_per_packet = bufsize - ( outsize + pad ) ;
tcount = maxcount ;
total_read = 0 ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) maxcount , ( SMB_BIG_UINT ) startpos , READ_LOCK ) ) {
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBreadBmpx ) ;
return ERROR_DOS ( ERRDOS , ERRlock ) ;
}
2000-10-06 07:21:49 +04:00
2001-10-19 04:56:03 +04:00
do {
size_t N = MIN ( max_per_packet , tcount - total_read ) ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
nread = read_file ( fsp , data , startpos , N ) ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
if ( nread < = 0 )
nread = 0 ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
if ( nread < ( ssize_t ) N )
tcount = total_read + nread ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
set_message ( inbuf , outbuf , 8 , nread + pad , False ) ;
2001-10-19 04:56:03 +04:00
SIVAL ( outbuf , smb_vwv0 , startpos ) ;
SSVAL ( outbuf , smb_vwv2 , tcount ) ;
SSVAL ( outbuf , smb_vwv6 , nread ) ;
SSVAL ( outbuf , smb_vwv7 , smb_offset ( data , outbuf ) ) ;
1996-05-04 11:50:46 +04:00
2005-06-09 22:15:23 +04:00
show_msg ( outbuf ) ;
2001-10-19 04:56:03 +04:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " reply_readbmpx: send_smb failed. " ) ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
total_read + = nread ;
startpos + = nread ;
} while ( total_read < ( ssize_t ) tcount ) ;
1996-05-04 11:50:46 +04:00
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBreadBmpx ) ;
return ( - 1 ) ;
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
int reply_setattrE ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2007-03-06 02:40:03 +03:00
struct timespec ts [ 2 ] ;
2002-03-20 03:46:53 +03:00
int outsize = 0 ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBsetattrE ) ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 0 , 0 , False ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
2005-12-26 14:44:15 +03:00
END_PROFILE ( SMBsetattrE ) ;
2002-03-20 03:46:53 +03:00
return ERROR_DOS ( ERRDOS , ERRbadfid ) ;
}
1996-05-04 11:50:46 +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-03-06 02:40:03 +03:00
ts [ 0 ] = convert_time_t_to_timespec ( srv_make_unix_date2 ( inbuf + smb_vwv3 ) ) ; /* atime. */
ts [ 1 ] = convert_time_t_to_timespec ( srv_make_unix_date2 ( inbuf + smb_vwv5 ) ) ; /* mtime. */
1996-05-04 11:50:46 +04:00
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 ) ;
return ( outsize ) ;
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 ) ) {
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBsetattrE ) ;
return ERROR_DOS ( ERRDOS , ERRnoaccess ) ;
}
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 ) ;
return ( outsize ) ;
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int reply_writebmpx ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
{
size_t numtowrite ;
ssize_t nwritten = - 1 ;
int outsize = 0 ;
SMB_OFF_T startpos ;
size_t tcount ;
BOOL write_through ;
int smb_doff ;
char * data ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBwriteBmpx ) ;
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
2005-04-02 03:11:28 +04:00
if ( HAS_CACHED_ERROR ( fsp ) ) {
return ( CACHED_ERROR ( fsp ) ) ;
}
2001-10-19 04:56:03 +04:00
tcount = SVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv3 ) ;
2001-10-19 04:56:03 +04:00
write_through = BITSETW ( inbuf + smb_vwv7 , 0 ) ;
numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
smb_doff = SVAL ( inbuf , smb_vwv11 ) ;
data = smb_base ( inbuf ) + smb_doff ;
/* If this fails we need to send an SMBwriteC response,
not an SMBwritebmpx - set this up now so we don ' t forget */
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_com , SMBwritec ) ;
2001-10-19 04:56:03 +04:00
2006-07-11 22:01:26 +04:00
if ( is_locked ( fsp , ( uint32 ) SVAL ( inbuf , smb_pid ) , ( SMB_BIG_UINT ) tcount , ( SMB_BIG_UINT ) startpos , WRITE_LOCK ) ) {
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBmpx ) ;
return ( ERROR_DOS ( ERRDOS , ERRlock ) ) ;
}
nwritten = write_file ( fsp , data , startpos , numtowrite ) ;
2005-09-03 11:19:28 +04:00
sync_file ( conn , fsp , write_through ) ;
2001-10-19 04:56:03 +04:00
if ( nwritten < ( ssize_t ) numtowrite ) {
END_PROFILE ( SMBwriteBmpx ) ;
return ( UNIXERROR ( ERRHRD , ERRdiskfull ) ) ;
}
/* If the maximum to be written to this file
is greater than what we just wrote then set
up a secondary struct to be attached to this
fd , we will use this to cache error messages etc . */
if ( ( ssize_t ) tcount > nwritten ) {
write_bmpx_struct * wbms ;
if ( fsp - > wbmpx_ptr ! = NULL )
wbms = fsp - > wbmpx_ptr ; /* Use an existing struct */
else
2004-12-07 21:25:53 +03:00
wbms = SMB_MALLOC_P ( write_bmpx_struct ) ;
2001-10-19 04:56:03 +04:00
if ( ! wbms ) {
DEBUG ( 0 , ( " Out of memory in reply_readmpx \n " ) ) ;
END_PROFILE ( SMBwriteBmpx ) ;
return ( ERROR_DOS ( ERRSRV , ERRnoresource ) ) ;
}
wbms - > wr_mode = write_through ;
wbms - > wr_discard = False ; /* No errors yet */
wbms - > wr_total_written = nwritten ;
wbms - > wr_errclass = 0 ;
wbms - > wr_error = 0 ;
fsp - > wbmpx_ptr = wbms ;
}
/* We are returning successfully, set the message type back to
SMBwritebmpx */
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_com , SMBwriteBmpx ) ;
2001-10-19 04:56:03 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2001-10-19 04:56:03 +04:00
SSVALS ( outbuf , smb_vwv0 , - 1 ) ; /* We don't support smb_remaining */
DEBUG ( 3 , ( " writebmpx fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
if ( write_through & & tcount = = nwritten ) {
/* We need to send both a primary and a secondary response */
2007-04-20 02:40:32 +04:00
smb_setlen ( inbuf , outbuf , outsize - 4 ) ;
2005-06-09 22:15:23 +04:00
show_msg ( outbuf ) ;
2001-10-19 04:56:03 +04:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " reply_writebmpx: send_smb failed. " ) ;
2001-10-19 04:56:03 +04:00
/* Now the secondary */
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_com , SMBwritec ) ;
2001-10-19 04:56:03 +04:00
SSVAL ( outbuf , smb_vwv0 , nwritten ) ;
}
END_PROFILE ( SMBwriteBmpx ) ;
return ( outsize ) ;
}
/****************************************************************************
Reply to a SMBwritebs ( write block multiplex secondary ) request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int reply_writebs ( connection_struct * conn , char * inbuf , char * outbuf , int dum_size , int dum_buffsize )
{
size_t numtowrite ;
ssize_t nwritten = - 1 ;
int outsize = 0 ;
SMB_OFF_T startpos ;
size_t tcount ;
BOOL write_through ;
int smb_doff ;
char * data ;
write_bmpx_struct * wbms ;
BOOL send_response = False ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBwriteBs ) ;
CHECK_FSP ( fsp , conn ) ;
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
return ( ERROR_DOS ( ERRDOS , ERRbadaccess ) ) ;
}
2001-10-19 04:56:03 +04:00
tcount = SVAL ( inbuf , smb_vwv1 ) ;
2002-12-03 11:02:41 +03:00
startpos = IVAL_TO_SMB_OFF_T ( inbuf , smb_vwv2 ) ;
2001-10-19 04:56:03 +04:00
numtowrite = SVAL ( inbuf , smb_vwv6 ) ;
smb_doff = SVAL ( inbuf , smb_vwv7 ) ;
data = smb_base ( inbuf ) + smb_doff ;
/* We need to send an SMBwriteC response, not an SMBwritebs */
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , smb_com , SMBwritec ) ;
2001-10-19 04:56:03 +04:00
/* This fd should have an auxiliary struct attached,
check that it does */
wbms = fsp - > wbmpx_ptr ;
if ( ! wbms ) {
END_PROFILE ( SMBwriteBs ) ;
return ( - 1 ) ;
}
/* If write through is set we can return errors, else we must cache them */
write_through = wbms - > wr_mode ;
/* Check for an earlier error */
if ( wbms - > wr_discard ) {
END_PROFILE ( SMBwriteBs ) ;
return - 1 ; /* Just discard the packet */
}
nwritten = write_file ( fsp , data , startpos , numtowrite ) ;
2005-09-03 11:19:28 +04:00
sync_file ( conn , fsp , write_through ) ;
2001-10-19 04:56:03 +04:00
if ( nwritten < ( ssize_t ) numtowrite ) {
if ( write_through ) {
/* We are returning an error - we can delete the aux struct */
if ( wbms )
free ( ( char * ) wbms ) ;
fsp - > wbmpx_ptr = NULL ;
END_PROFILE ( SMBwriteBs ) ;
return ( ERROR_DOS ( ERRHRD , ERRdiskfull ) ) ;
}
2005-04-02 03:11:28 +04:00
wbms - > wr_errclass = ERRHRD ;
wbms - > wr_error = ERRdiskfull ;
wbms - > wr_status = NT_STATUS_DISK_FULL ;
wbms - > wr_discard = True ;
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBs ) ;
2005-04-02 03:11:28 +04:00
return - 1 ;
2001-10-19 04:56:03 +04:00
}
/* Increment the total written, if this matches tcount
we can discard the auxiliary struct ( hurrah ! ) and return a writeC */
wbms - > wr_total_written + = nwritten ;
if ( wbms - > wr_total_written > = tcount ) {
if ( write_through ) {
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 1 , 0 , True ) ;
2001-10-19 04:56:03 +04:00
SSVAL ( outbuf , smb_vwv0 , wbms - > wr_total_written ) ;
send_response = True ;
}
free ( ( char * ) wbms ) ;
fsp - > wbmpx_ptr = NULL ;
}
if ( send_response ) {
END_PROFILE ( SMBwriteBs ) ;
return ( outsize ) ;
}
END_PROFILE ( SMBwriteBs ) ;
return ( - 1 ) ;
}
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
int reply_getattrE ( connection_struct * conn , char * inbuf , char * outbuf , int size , int dum_buffsize )
1996-05-04 11:50:46 +04:00
{
2002-03-20 03:46:53 +03:00
SMB_STRUCT_STAT sbuf ;
int outsize = 0 ;
int mode ;
files_struct * fsp = file_fsp ( inbuf , smb_vwv0 ) ;
START_PROFILE ( SMBgetattrE ) ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
outsize = set_message ( inbuf , outbuf , 11 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
END_PROFILE ( SMBgetattrE ) ;
return ERROR_DOS ( ERRDOS , ERRbadfid ) ;
}
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 ) ) {
END_PROFILE ( SMBgetattrE ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
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 .
*/
2005-11-05 07:21:55 +03:00
srv_put_dos_date2 ( outbuf , smb_vwv0 , get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
srv_put_dos_date2 ( outbuf , smb_vwv2 , sbuf . st_atime ) ;
2005-03-10 04:30:14 +03:00
/* Should we check pending modtime here ? JRA */
2005-11-05 07:21:55 +03:00
srv_put_dos_date2 ( outbuf , smb_vwv4 , sbuf . st_mtime ) ;
2002-03-20 03:46:53 +03:00
if ( mode & aDIR ) {
SIVAL ( outbuf , smb_vwv6 , 0 ) ;
SIVAL ( outbuf , smb_vwv8 , 0 ) ;
} else {
2005-03-03 07:03:36 +03:00
uint32 allocation_size = get_allocation_size ( conn , fsp , & sbuf ) ;
2002-03-20 03:46:53 +03:00
SIVAL ( outbuf , smb_vwv6 , ( uint32 ) sbuf . st_size ) ;
2003-06-06 09:32:36 +04:00
SIVAL ( outbuf , smb_vwv8 , allocation_size ) ;
2002-03-20 03:46:53 +03:00
}
SSVAL ( 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 ) ;
return ( outsize ) ;
1996-05-04 11:50:46 +04:00
}