2007-09-12 03:57:59 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Main SMB reply routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
2001-09-16 10:35:35 +04:00
Copyright ( C ) Andrew Bartlett 2001
2007-01-13 02:47:16 +03:00
Copyright ( C ) Jeremy Allison 1992 - 2007.
2007-08-02 22:28:41 +04:00
Copyright ( C ) Volker Lendecke 2007
2001-09-16 10:35:35 +04:00
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2007-09-12 03:57:59 +04:00
1996-05-04 11:50:46 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2007-09-12 03:57:59 +04:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 11:50:46 +04:00
*/
/*
This file handles most of the reply_ calls that the server
makes to handle specific protocols
*/
# include "includes.h"
2009-01-08 14:03:45 +03:00
# include "smbd/globals.h"
1996-05-04 11:50:46 +04:00
2005-03-25 01:32:52 +03:00
/****************************************************************************
Ensure we check the path in * exactly * the same way as W2K for a findfirst / findnext
path or anything including wildcards .
We ' re assuming here that ' / ' is not the second byte in any multibyte char
set ( a safe assumption ) . ' \\ ' * may * be the second byte in a multibyte char
set .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-12 20:55:24 +03:00
/* Custom version for processing POSIX paths. */
# define IS_PATH_SEP(c,posix_only) ((c) == ' / ' || (!(posix_only) && (c) == '\\'))
2007-06-16 22:07:44 +04:00
static NTSTATUS check_path_syntax_internal ( char * path ,
2007-10-19 04:40:25 +04:00
bool posix_path ,
bool * p_last_component_contains_wcard )
2005-03-25 01:32:52 +03:00
{
2007-06-16 22:07:44 +04:00
char * d = path ;
const char * s = path ;
2005-03-25 01:32:52 +03:00
NTSTATUS ret = NT_STATUS_OK ;
2007-10-19 04:40:25 +04:00
bool start_of_name_component = True ;
2008-12-02 00:22:55 +03:00
bool stream_started = false ;
2005-03-25 01:32:52 +03:00
2007-01-13 23:26:53 +03:00
* p_last_component_contains_wcard = False ;
2005-10-31 23:11:58 +03:00
2005-03-25 01:32:52 +03:00
while ( * s ) {
2008-12-02 00:22:55 +03:00
if ( stream_started ) {
switch ( * s ) {
case ' / ' :
case ' \\ ' :
return NT_STATUS_OBJECT_NAME_INVALID ;
case ' : ' :
if ( s [ 1 ] = = ' \0 ' ) {
return NT_STATUS_OBJECT_NAME_INVALID ;
}
if ( strchr_m ( & s [ 1 ] , ' : ' ) ) {
return NT_STATUS_OBJECT_NAME_INVALID ;
}
break ;
}
}
2009-11-16 00:22:38 +03:00
if ( ( * s = = ' : ' ) & & ! posix_path & & ! stream_started ) {
2008-12-02 00:22:55 +03:00
if ( * p_last_component_contains_wcard ) {
return NT_STATUS_OBJECT_NAME_INVALID ;
}
2009-03-19 06:00:28 +03:00
/* Stream names allow more characters than file names.
We ' re overloading posix_path here to allow a wider
range of characters . If stream_started is true this
is still a Windows path even if posix_path is true .
JRA .
*/
2008-12-02 00:22:55 +03:00
stream_started = true ;
start_of_name_component = false ;
posix_path = true ;
if ( s [ 1 ] = = ' \0 ' ) {
return NT_STATUS_OBJECT_NAME_INVALID ;
}
}
if ( ! stream_started & & IS_PATH_SEP ( * s , posix_path ) ) {
2005-03-25 01:32:52 +03:00
/*
2007-01-14 14:25:42 +03:00
* Safe to assume is not the second part of a mb char
* as this is handled below .
2005-03-25 01:32:52 +03:00
*/
/* Eat multiple '/' or '\\' */
2007-03-12 20:55:24 +03:00
while ( IS_PATH_SEP ( * s , posix_path ) ) {
2005-03-25 01:32:52 +03:00
s + + ;
}
2007-06-16 22:07:44 +04:00
if ( ( d ! = path ) & & ( * s ! = ' \0 ' ) ) {
2005-03-25 01:32:52 +03:00
/* We only care about non-leading or trailing '/' or '\\' */
* d + + = ' / ' ;
}
start_of_name_component = True ;
2007-01-13 02:47:16 +03:00
/* New component. */
2007-01-13 23:26:53 +03:00
* p_last_component_contains_wcard = False ;
2005-03-25 01:32:52 +03:00
continue ;
}
if ( start_of_name_component ) {
2007-03-12 20:55:24 +03:00
if ( ( s [ 0 ] = = ' . ' ) & & ( s [ 1 ] = = ' . ' ) & & ( IS_PATH_SEP ( s [ 2 ] , posix_path ) | | s [ 2 ] = = ' \0 ' ) ) {
2005-03-25 01:32:52 +03:00
/* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
/*
* No mb char starts with ' . ' so we ' re safe checking the directory separator here .
*/
/* If we just added a '/' - delete it */
2007-06-16 22:07:44 +04:00
if ( ( d > path ) & & ( * ( d - 1 ) = = ' / ' ) ) {
2005-03-25 01:32:52 +03:00
* ( d - 1 ) = ' \0 ' ;
d - - ;
}
/* Are we at the start ? Can't go back further if so. */
2007-06-16 22:07:44 +04:00
if ( d < = path ) {
2005-03-25 01:32:52 +03:00
ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD ;
break ;
}
/* Go back one level... */
/* We know this is safe as '/' cannot be part of a mb sequence. */
/* NOTE - if this assumption is invalid we are not in good shape... */
/* Decrement d first as d points to the *next* char to write into. */
2007-06-16 22:07:44 +04:00
for ( d - - ; d > path ; d - - ) {
2005-03-25 01:32:52 +03:00
if ( * d = = ' / ' )
break ;
}
s + = 2 ; /* Else go past the .. */
/* We're still at the start of a name component, just the previous one. */
continue ;
2007-03-12 20:55:24 +03:00
} else if ( ( s [ 0 ] = = ' . ' ) & & ( ( s [ 1 ] = = ' \0 ' ) | | IS_PATH_SEP ( s [ 1 ] , posix_path ) ) ) {
if ( posix_path ) {
2007-01-13 02:47:16 +03:00
/* Eat the '.' */
s + + ;
continue ;
}
2004-09-04 00:05:29 +04:00
}
2007-01-13 02:47:16 +03:00
2005-03-25 01:32:52 +03:00
}
if ( ! ( * s & 0x80 ) ) {
2007-03-12 20:55:24 +03:00
if ( ! posix_path ) {
2008-12-02 00:01:09 +03:00
if ( * s < = 0x1f | | * s = = ' | ' ) {
2007-01-13 02:47:16 +03:00
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 ' ;
2008-01-20 01:25:36 +03:00
2004-03-03 23:55:59 +03:00
return ret ;
2003-08-13 07:28:06 +04:00
}
2005-05-06 17:26:54 +04:00
/****************************************************************************
2007-01-13 02:47:16 +03:00
Ensure we check the path in * exactly * the same way as W2K for regular pathnames .
No wildcards allowed .
2005-05-06 17:26:54 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-16 22:07:44 +04:00
NTSTATUS check_path_syntax ( char * path )
2005-05-06 17:26:54 +04:00
{
2007-10-19 04:40:25 +04:00
bool ignore ;
2007-06-16 22:07:44 +04:00
return check_path_syntax_internal ( path , False , & ignore ) ;
2007-01-13 02:47:16 +03:00
}
2005-05-06 17:26:54 +04:00
2007-01-13 02:47:16 +03:00
/****************************************************************************
Ensure we check the path in * exactly * the same way as W2K for regular pathnames .
Wildcards allowed - p_contains_wcard returns true if the last component contained
a wildcard .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-06 17:26:54 +04:00
2007-10-19 04:40:25 +04:00
NTSTATUS check_path_syntax_wcard ( char * path , bool * p_contains_wcard )
2007-01-13 02:47:16 +03:00
{
2007-06-16 22:07:44 +04:00
return check_path_syntax_internal ( path , False , p_contains_wcard ) ;
2007-01-13 02:47:16 +03:00
}
2005-05-06 17:26:54 +04:00
2007-01-13 02:47:16 +03:00
/****************************************************************************
Check the path for a POSIX client .
We ' re assuming here that ' / ' is not the second byte in any multibyte char
set ( a safe assumption ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-06 17:26:54 +04:00
2007-06-16 22:19:42 +04:00
NTSTATUS check_path_syntax_posix ( char * path )
2007-01-13 02:47:16 +03:00
{
2007-10-19 04:40:25 +04:00
bool ignore ;
2007-06-16 22:07:44 +04:00
return check_path_syntax_internal ( path , True , & ignore ) ;
2005-05-06 17:26:54 +04:00
}
2005-10-31 23:11:58 +03:00
/****************************************************************************
Pull a string and check the path allowing a wilcard - provide for error return .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-12 03:57:59 +04:00
size_t srvstr_get_path_wcard ( TALLOC_CTX * ctx ,
2008-11-02 03:27:41 +03:00
const char * base_ptr ,
2007-09-12 03:57:59 +04:00
uint16 smb_flags2 ,
char * * pp_dest ,
const char * src ,
size_t src_len ,
int flags ,
NTSTATUS * err ,
2007-10-19 04:40:25 +04:00
bool * contains_wcard )
2005-10-31 23:11:58 +03:00
{
size_t ret ;
2007-09-12 03:57:59 +04:00
* pp_dest = NULL ;
2005-10-31 23:11:58 +03:00
2008-11-02 03:27:41 +03:00
ret = srvstr_pull_talloc ( ctx , base_ptr , smb_flags2 , pp_dest , src ,
src_len , flags ) ;
2007-09-12 03:57:59 +04:00
if ( ! * pp_dest ) {
* err = NT_STATUS_INVALID_PARAMETER ;
return ret ;
2005-10-31 23:11:58 +03:00
}
* contains_wcard = False ;
2007-07-06 20:39:58 +04:00
if ( smb_flags2 & FLAGS2_DFS_PATHNAMES ) {
2007-09-12 03:57:59 +04:00
/*
2007-03-12 20:55:24 +03:00
* For a DFS path the function parse_dfs_path ( )
* will do the path processing , just make a copy .
*/
* err = NT_STATUS_OK ;
return ret ;
}
2005-10-31 23:11:58 +03:00
if ( lp_posix_pathnames ( ) ) {
2007-09-12 03:57:59 +04:00
* err = check_path_syntax_posix ( * pp_dest ) ;
2005-10-31 23:11:58 +03:00
} else {
2007-09-12 03:57:59 +04:00
* err = check_path_syntax_wcard ( * pp_dest , contains_wcard ) ;
2005-10-31 23:11:58 +03:00
}
2006-07-11 22:01:26 +04:00
2005-10-31 23:11:58 +03:00
return ret ;
}
2003-10-09 03:21:36 +04:00
/****************************************************************************
Pull a string and check the path - provide for error return .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-12 03:57:59 +04:00
size_t srvstr_get_path ( TALLOC_CTX * ctx ,
2008-11-02 03:27:41 +03:00
const char * base_ptr ,
2007-09-12 03:57:59 +04:00
uint16 smb_flags2 ,
char * * pp_dest ,
const char * src ,
size_t src_len ,
int flags ,
NTSTATUS * err )
2003-10-09 03:21:36 +04:00
{
2008-11-02 02:59:03 +03:00
bool ignore ;
2008-11-02 03:27:41 +03:00
return srvstr_get_path_wcard ( ctx , base_ptr , smb_flags2 , pp_dest , src ,
2008-11-02 02:59:03 +03:00
src_len , flags , err , & ignore ) ;
}
2007-03-12 20:55:24 +03:00
2008-11-02 02:59:03 +03:00
size_t srvstr_get_path_req_wcard ( TALLOC_CTX * mem_ctx , struct smb_request * req ,
char * * pp_dest , const char * src , int flags ,
NTSTATUS * err , bool * contains_wcard )
{
return srvstr_get_path_wcard ( mem_ctx , ( char * ) req - > inbuf , req - > flags2 ,
2008-11-02 03:21:53 +03:00
pp_dest , src , smbreq_bufrem ( req , src ) ,
2008-11-02 02:59:03 +03:00
flags , err , contains_wcard ) ;
}
2006-07-11 22:01:26 +04:00
2008-11-02 02:59:03 +03:00
size_t srvstr_get_path_req ( TALLOC_CTX * mem_ctx , struct smb_request * req ,
char * * pp_dest , const char * src , int flags ,
NTSTATUS * err )
{
bool ignore ;
return srvstr_get_path_req_wcard ( mem_ctx , req , pp_dest , src ,
flags , err , & ignore ) ;
2003-10-09 03:21:36 +04:00
}
2007-08-02 23:50:56 +04:00
/****************************************************************************
2007-09-08 00:57:01 +04:00
Check if we have a correct fsp pointing to a file . Basic check for open fsp .
2007-08-02 23:50:56 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 05:45:26 +04:00
2007-10-19 04:40:25 +04:00
bool check_fsp_open ( connection_struct * conn , struct smb_request * req ,
2008-06-19 18:31:59 +04:00
files_struct * fsp )
2007-08-02 23:50:56 +04:00
{
if ( ! ( fsp ) | | ! ( conn ) ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return False ;
}
2008-06-19 18:31:59 +04:00
if ( ( ( conn ) ! = ( fsp ) - > conn ) | | req - > vuid ! = ( fsp ) - > vuid ) {
2007-08-02 23:50:56 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return False ;
}
2007-09-08 00:57:01 +04:00
return True ;
}
/****************************************************************************
2008-10-08 14:56:04 +04:00
Check if we have a correct fsp pointing to a file .
2007-09-08 00:57:01 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool check_fsp ( connection_struct * conn , struct smb_request * req ,
2008-06-19 18:31:59 +04:00
files_struct * fsp )
2007-09-08 00:57:01 +04:00
{
2008-06-19 18:31:59 +04:00
if ( ! check_fsp_open ( conn , req , fsp ) ) {
2007-09-08 00:57:01 +04:00
return False ;
}
2007-08-02 23:50:56 +04:00
if ( ( fsp ) - > is_directory ) {
reply_nterror ( req , NT_STATUS_INVALID_DEVICE_REQUEST ) ;
return False ;
}
if ( ( fsp ) - > fh - > fd = = - 1 ) {
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return False ;
}
( fsp ) - > num_smb_operations + + ;
return True ;
}
2008-06-19 20:46:57 +04:00
/****************************************************************************
Check if we have a correct fsp pointing to a quota fake file . Replacement for
the CHECK_NTQUOTA_HANDLE_OK macro .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool check_fsp_ntquota_handle ( connection_struct * conn , struct smb_request * req ,
files_struct * fsp )
{
if ( ! check_fsp_open ( conn , req , fsp ) ) {
return false ;
}
if ( fsp - > is_directory ) {
return false ;
}
if ( fsp - > fake_file_handle = = NULL ) {
return false ;
}
if ( fsp - > fake_file_handle - > type ! = FAKE_FILE_TYPE_QUOTA ) {
return false ;
}
if ( fsp - > fake_file_handle - > private_data = = NULL ) {
return false ;
}
return true ;
}
2007-08-13 23:58:28 +04:00
/****************************************************************************
Check if we have a correct fsp . Replacement for the FSP_BELONGS_CONN macro
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool fsp_belongs_conn ( connection_struct * conn , struct smb_request * req ,
2008-06-19 18:31:59 +04:00
files_struct * fsp )
2007-08-13 23:58:28 +04:00
{
if ( ( fsp ) & & ( conn ) & & ( ( conn ) = = ( fsp ) - > conn )
2008-06-19 18:31:59 +04:00
& & ( req - > vuid = = ( fsp ) - > vuid ) ) {
2007-08-13 23:58:28 +04:00
return True ;
}
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return False ;
}
2009-04-12 16:31:53 +04:00
static bool netbios_session_retarget ( const char * name , int name_type )
{
char * trim_name ;
char * trim_name_type ;
const char * retarget_parm ;
char * retarget ;
char * p ;
int retarget_type = 0x20 ;
int retarget_port = 139 ;
struct sockaddr_storage retarget_addr ;
struct sockaddr_in * in_addr ;
bool ret = false ;
uint8_t outbuf [ 10 ] ;
if ( get_socket_port ( smbd_server_fd ( ) ) ! = 139 ) {
return false ;
}
trim_name = talloc_strdup ( talloc_tos ( ) , name ) ;
if ( trim_name = = NULL ) {
goto fail ;
}
trim_char ( trim_name , ' ' , ' ' ) ;
trim_name_type = talloc_asprintf ( trim_name , " %s#%2.2x " , trim_name ,
name_type ) ;
if ( trim_name_type = = NULL ) {
goto fail ;
}
retarget_parm = lp_parm_const_string ( - 1 , " netbios retarget " ,
trim_name_type , NULL ) ;
if ( retarget_parm = = NULL ) {
retarget_parm = lp_parm_const_string ( - 1 , " netbios retarget " ,
trim_name , NULL ) ;
}
if ( retarget_parm = = NULL ) {
goto fail ;
}
retarget = talloc_strdup ( trim_name , retarget_parm ) ;
if ( retarget = = NULL ) {
goto fail ;
}
DEBUG ( 10 , ( " retargeting %s to %s \n " , trim_name_type , retarget ) ) ;
p = strchr ( retarget , ' : ' ) ;
if ( p ! = NULL ) {
* p + + = ' \0 ' ;
retarget_port = atoi ( p ) ;
}
p = strchr_m ( retarget , ' # ' ) ;
if ( p ! = NULL ) {
* p + + = ' \0 ' ;
sscanf ( p , " %x " , & retarget_type ) ;
}
2009-07-28 22:51:58 +04:00
ret = resolve_name ( retarget , & retarget_addr , retarget_type , false ) ;
2009-04-12 16:31:53 +04:00
if ( ! ret ) {
DEBUG ( 10 , ( " could not resolve %s \n " , retarget ) ) ;
goto fail ;
}
if ( retarget_addr . ss_family ! = AF_INET ) {
DEBUG ( 10 , ( " Retarget target not an IPv4 addr \n " ) ) ;
goto fail ;
}
2009-05-14 13:47:25 +04:00
in_addr = ( struct sockaddr_in * ) ( void * ) & retarget_addr ;
2009-04-12 16:31:53 +04:00
_smb_setlen ( outbuf , 6 ) ;
SCVAL ( outbuf , 0 , 0x84 ) ;
* ( uint32_t * ) ( outbuf + 4 ) = in_addr - > sin_addr . s_addr ;
* ( uint16_t * ) ( outbuf + 8 ) = htons ( retarget_port ) ;
if ( ! srv_send_smb ( smbd_server_fd ( ) , ( char * ) outbuf , false , 0 , false ,
NULL ) ) {
exit_server_cleanly ( " netbios_session_regarget: srv_send_smb "
" failed. " ) ;
}
ret = true ;
fail :
TALLOC_FREE ( trim_name ) ;
return ret ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2007-07-23 13:36:09 +04:00
Reply to a ( netbios - level ) special message .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-07-23 13:36:09 +04:00
void reply_special ( char * inbuf )
1996-05-04 11:50:46 +04:00
{
1997-09-18 11:05:43 +04:00
int msg_type = CVAL ( inbuf , 0 ) ;
int msg_flags = CVAL ( inbuf , 1 ) ;
2004-03-13 03:28:53 +03:00
fstring name1 , name2 ;
2009-04-12 13:59:18 +04:00
char name_type1 , name_type2 ;
2009-05-26 17:21:16 +04:00
struct smbd_server_connection * sconn = smbd_server_conn ;
2007-07-23 13:36:09 +04:00
/*
* We only really use 4 bytes of the outbuf , but for the smb_setlen
2008-01-04 23:56:23 +03:00
* calculation & friends ( srv_send_smb uses that ) we need the full smb
2007-07-23 13:36:09 +04:00
* header .
*/
char outbuf [ smb_size ] ;
2008-10-19 17:30:12 +04:00
1997-09-18 11:05:43 +04:00
* name1 = * name2 = 0 ;
2008-10-19 17:30:12 +04:00
2007-07-23 13:36:09 +04:00
memset ( outbuf , ' \0 ' , sizeof ( outbuf ) ) ;
1998-08-04 05:01:26 +04:00
2007-10-11 00:34:30 +04:00
smb_setlen ( outbuf , 0 ) ;
2008-10-19 17:30:12 +04:00
1997-09-18 11:05:43 +04:00
switch ( msg_type ) {
1997-10-28 09:07:07 +03:00
case 0x81 : /* session request */
2008-10-19 17:30:12 +04:00
2009-05-26 17:20:36 +04:00
if ( sconn - > nbt . 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
}
2008-10-19 17:30:12 +04:00
2002-01-11 22:10:25 +03:00
SCVAL ( outbuf , 0 , 0x82 ) ;
SCVAL ( outbuf , 3 , 0 ) ;
1997-10-28 09:07:07 +03:00
if ( name_len ( inbuf + 4 ) > 50 | |
name_len ( inbuf + 4 + name_len ( inbuf + 4 ) ) > 50 ) {
DEBUG ( 0 , ( " Invalid name length in session request \n " ) ) ;
2007-07-23 13:36:09 +04:00
return ;
1997-10-28 09:07:07 +03:00
}
2009-04-12 13:59:18 +04:00
name_type1 = name_extract ( inbuf , 4 , name1 ) ;
name_type2 = name_extract ( inbuf , 4 + name_len ( inbuf + 4 ) , name2 ) ;
DEBUG ( 2 , ( " netbios connect: name1=%s0x%x name2=%s0x%x \n " ,
name1 , name_type1 , name2 , name_type2 ) ) ;
1997-09-26 22:55:29 +04:00
2009-04-12 16:31:53 +04:00
if ( netbios_session_retarget ( name1 , name_type1 ) ) {
exit_server_cleanly ( " retargeted client " ) ;
}
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 ( ) ,
2009-04-12 13:59:18 +04:00
name_type2 ) ) ;
2001-06-24 00:01:23 +04:00
2009-04-12 13:59:18 +04:00
if ( name_type2 = = ' R ' ) {
1997-10-28 09:07:07 +03:00
/* 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 ) {
2009-05-26 18:38:45 +04:00
add_session_user ( sconn , 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
2009-05-26 17:20:36 +04:00
sconn - > nbt . got_session = true ;
1997-10-28 09:07:07 +03:00
break ;
2008-10-19 17:30:12 +04:00
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 ;
2008-10-19 17:30:12 +04:00
1997-09-18 11:05:43 +04:00
case 0x82 : /* positive session response */
case 0x83 : /* negative session response */
case 0x84 : /* retarget session response */
DEBUG ( 0 , ( " Unexpected session response \n " ) ) ;
break ;
2008-10-19 17:30:12 +04:00
2001-10-21 03:34:40 +04:00
case SMBkeepalive : /* session keepalive */
1997-09-18 11:05:43 +04:00
default :
2007-07-23 13:36:09 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2008-10-19 17:30:12 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 5 , ( " init msg_type=0x%x msg_flags=0x%x \n " ,
msg_type , msg_flags ) ) ;
2007-07-23 13:36:09 +04:00
2009-03-09 11:47:59 +03:00
srv_send_smb ( smbd_server_fd ( ) , outbuf , false , 0 , false , NULL ) ;
2007-07-23 13:36:09 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a tcon .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_tcon ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-08-17 19:27:10 +04:00
const char * service ;
2007-07-13 05:22:09 +04:00
char * service_buf = NULL ;
char * password = NULL ;
char * dev = NULL ;
1998-08-14 21:38:29 +04:00
int pwlen = 0 ;
2001-09-24 03:07:53 +04:00
NTSTATUS nt_status ;
2008-11-01 19:35:48 +03:00
const char * p ;
2001-10-31 13:46:25 +03:00
DATA_BLOB password_blob ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2010-06-12 13:40:37 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2007-07-13 05:22:09 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBtcon ) ;
1998-08-14 21:38:29 +04:00
2008-11-01 18:24:42 +03:00
if ( req - > buflen < 4 ) {
2007-08-17 05:55:58 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBtcon ) ;
return ;
}
2007-08-15 14:29:47 +04:00
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 03:07:46 +03:00
p + = srvstr_pull_req_talloc ( ctx , req , & service_buf , p , STR_TERMINATE ) ;
p + = 1 ;
pwlen = srvstr_pull_req_talloc ( ctx , req , & password , p , STR_TERMINATE ) ;
p + = pwlen + 1 ;
p + = srvstr_pull_req_talloc ( ctx , req , & dev , p , STR_TERMINATE ) ;
p + = 1 ;
1998-08-14 21:38:29 +04:00
2007-07-13 05:22:09 +04:00
if ( service_buf = = NULL | | password = = NULL | | dev = = NULL ) {
2007-08-15 14:29:47 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
2007-07-13 05:22:09 +04:00
}
2002-08-17 19:27:10 +04:00
p = strrchr_m ( service_buf , ' \\ ' ) ;
2001-03-13 09:55:47 +03:00
if ( p ) {
2002-08-17 19:27:10 +04:00
service = p + 1 ;
} else {
service = service_buf ;
2001-03-13 09:55:47 +03:00
}
2001-10-31 13:46:25 +03:00
password_blob = data_blob ( password , pwlen + 1 ) ;
2009-05-26 18:38:45 +04:00
conn = make_connection ( sconn , service , password_blob , dev ,
req - > vuid , & nt_status ) ;
2008-01-04 23:56:23 +03:00
req - > conn = conn ;
2001-10-31 15:28:40 +03:00
2001-11-01 08:02:41 +03:00
data_blob_clear_free ( & password_blob ) ;
2007-07-13 05:22:09 +04:00
1998-08-14 21:38:29 +04:00
if ( ! conn ) {
2007-08-15 14:29:47 +04:00
reply_nterror ( req , nt_status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
2007-07-13 05:22:09 +04:00
2007-08-15 14:29:47 +04:00
reply_outbuf ( req , 2 , 0 ) ;
2009-05-26 16:56:08 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , sconn - > smb1 . negprot . max_recv ) ;
2007-08-15 14:29:47 +04:00
SSVAL ( req - > outbuf , smb_vwv1 , conn - > cnum ) ;
SSVAL ( req - > outbuf , smb_tid , conn - > cnum ) ;
2007-07-13 05:22:09 +04:00
2007-08-25 23:47:57 +04:00
DEBUG ( 3 , ( " tcon service=%s cnum=%d \n " ,
2001-09-15 16:55:59 +04:00
service , conn - > cnum ) ) ;
2007-07-13 05:22:09 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a tcon and X .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-06-22 04:57:59 +04:00
2008-01-05 02:37:24 +03:00
void reply_tcon_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2008-11-01 19:35:48 +03:00
const char * service = NULL ;
2001-10-31 13:46:25 +03:00
DATA_BLOB password ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-03-28 01:27:53 +03:00
/* what the cleint thinks the device is */
2007-07-13 05:22:09 +04:00
char * client_devicetype = NULL ;
2003-03-28 01:27:53 +03:00
/* what the server tells the client the share represents */
const char * server_devicetype ;
2001-09-24 03:07:53 +04:00
NTSTATUS nt_status ;
2007-07-23 15:38:29 +04:00
int passlen ;
2007-07-13 05:22:09 +04:00
char * path = NULL ;
2008-11-01 19:35:48 +03:00
const char * p , * q ;
2007-07-23 15:38:29 +04:00
uint16 tcon_flags ;
2010-06-12 13:41:00 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2001-10-31 13:46:25 +03:00
2007-07-13 05:22:09 +04:00
START_PROFILE ( SMBtconX ) ;
1998-06-10 23:45:13 +04:00
2007-07-23 15:38:29 +04:00
if ( req - > wct < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
2008-11-02 14:20:47 +03:00
passlen = SVAL ( req - > vwv + 3 , 0 ) ;
tcon_flags = SVAL ( req - > vwv + 2 , 0 ) ;
2007-07-23 15:38:29 +04:00
1998-08-14 21:38:29 +04:00
/* we might have to close an old one */
2007-07-23 15:38:29 +04:00
if ( ( tcon_flags & 0x1 ) & & conn ) {
2009-08-06 15:22:33 +04:00
close_cnum ( conn , req - > vuid ) ;
2008-01-04 23:56:23 +03:00
req - > conn = NULL ;
2008-01-05 02:37:24 +03:00
conn = NULL ;
1998-08-14 21:38:29 +04:00
}
1998-06-10 23:45:13 +04:00
2008-11-01 18:24:42 +03:00
if ( ( passlen > MAX_PASS_LEN ) | | ( passlen > = req - > buflen ) ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRDOS , ERRbuftoosmall ) ;
2007-07-23 15:38:29 +04:00
END_PROFILE ( SMBtconX ) ;
return ;
1998-08-14 21:38:29 +04:00
}
2007-07-13 05:22:09 +04:00
2009-05-26 14:48:58 +04:00
if ( sconn - > smb1 . negprot . encrypted_passwords ) {
2008-11-01 19:35:48 +03:00
password = data_blob_talloc ( talloc_tos ( ) , req - > buf , passlen ) ;
2007-04-17 06:14:28 +04:00
if ( lp_security ( ) = = SEC_SHARE ) {
/*
* Security = share always has a pad byte
* after the password .
*/
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + passlen + 1 ;
2007-04-17 06:14:28 +04:00
} else {
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + passlen ;
2007-04-17 06:14:28 +04:00
}
2001-10-31 13:46:25 +03:00
} else {
2008-11-01 19:35:48 +03:00
password = data_blob_talloc ( talloc_tos ( ) , req - > buf , passlen + 1 ) ;
2001-10-31 13:46:25 +03:00
/* Ensure correct termination */
2007-04-17 06:14:28 +04:00
password . data [ passlen ] = 0 ;
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + passlen + 1 ;
2001-10-31 13:46:25 +03:00
}
2008-11-02 03:07:46 +03:00
p + = srvstr_pull_req_talloc ( ctx , req , & path , p , STR_TERMINATE ) ;
2007-07-13 05:22:09 +04:00
if ( path = = NULL ) {
2007-07-23 15:38:29 +04:00
data_blob_clear_free ( & password ) ;
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2007-07-13 05:22:09 +04:00
}
1996-05-04 11:50:46 +04:00
2001-08-22 17:08:01 +04:00
/*
* the service name can be either : \ \ server \ share
* or share directly like on the DELL PowerVault 705
*/
2007-07-13 05:22:09 +04:00
if ( * path = = ' \\ ' ) {
2001-08-22 17:08:01 +04:00
q = strchr_m ( path + 2 , ' \\ ' ) ;
if ( ! q ) {
2007-07-23 15:38:29 +04:00
data_blob_clear_free ( & password ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_BAD_NETWORK_NAME ) ;
2001-08-22 17:08:01 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2001-08-22 17:08:01 +04:00
}
2007-07-13 05:22:09 +04:00
service = q + 1 ;
} else {
service = path ;
}
2007-07-23 15:38:29 +04:00
p + = srvstr_pull_talloc ( ctx , req - > inbuf , req - > flags2 ,
& client_devicetype , p ,
2008-11-02 03:21:53 +03:00
MIN ( 6 , smbreq_bufrem ( req , p ) ) , STR_ASCII ) ;
2007-07-13 05:22:09 +04:00
if ( client_devicetype = = NULL ) {
2007-07-23 15:38:29 +04:00
data_blob_clear_free ( & password ) ;
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1999-12-13 16:27:58 +03:00
2003-03-28 01:27:53 +03:00
DEBUG ( 4 , ( " Client requested device type [%s] for share [%s] \n " , client_devicetype , service ) ) ;
1998-12-01 01:42:13 +03:00
2009-05-26 18:38:45 +04:00
conn = make_connection ( sconn , service , password , client_devicetype ,
2007-07-23 15:38:29 +04:00
req - > vuid , & nt_status ) ;
2008-01-04 23:56:23 +03:00
req - > conn = conn ;
2007-07-13 05:22:09 +04:00
2001-10-31 15:28:40 +03:00
data_blob_clear_free ( & password ) ;
2001-11-01 08:02:41 +03:00
2000-10-06 07:21:49 +04:00
if ( ! conn ) {
2007-07-23 15:38:29 +04:00
reply_nterror ( req , nt_status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1997-08-31 18:14:22 +04:00
2003-03-28 01:27:53 +03:00
if ( IS_IPC ( conn ) )
server_devicetype = " IPC " ;
else if ( IS_PRINT ( conn ) )
2003-04-12 03:28:15 +04:00
server_devicetype = " LPT1: " ;
2007-07-13 05:22:09 +04:00
else
2003-03-28 01:27:53 +03:00
server_devicetype = " A: " ;
2009-11-23 18:33:26 +03:00
if ( get_Protocol ( ) < PROTOCOL_NT1 ) {
2007-07-23 15:38:29 +04:00
reply_outbuf ( req , 2 , 0 ) ;
if ( message_push_string ( & req - > outbuf , server_devicetype ,
STR_TERMINATE | STR_ASCII ) = = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
1998-08-14 21:38:29 +04:00
} else {
2001-03-13 06:45:09 +03:00
/* NT sets the fstype of IPC$ to the null string */
2003-04-23 15:11:02 +04:00
const char * fstype = IS_IPC ( conn ) ? " " : lp_fstype ( SNUM ( conn ) ) ;
2007-07-13 05:22:09 +04:00
2007-04-07 09:49:24 +04:00
if ( tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE ) {
/* Return permissions. */
uint32 perm1 = 0 ;
uint32 perm2 = 0 ;
2007-07-23 15:38:29 +04:00
reply_outbuf ( req , 7 , 0 ) ;
2007-04-07 09:49:24 +04:00
if ( IS_IPC ( conn ) ) {
perm1 = FILE_ALL_ACCESS ;
perm2 = FILE_ALL_ACCESS ;
} else {
perm1 = CAN_WRITE ( conn ) ?
SHARE_ALL_ACCESS :
SHARE_READ_ONLY ;
}
2007-07-23 15:38:29 +04:00
SIVAL ( req - > outbuf , smb_vwv3 , perm1 ) ;
SIVAL ( req - > outbuf , smb_vwv5 , perm2 ) ;
2007-04-07 09:49:24 +04:00
} else {
2007-07-23 15:38:29 +04:00
reply_outbuf ( req , 3 , 0 ) ;
2007-04-07 09:49:24 +04:00
}
1997-08-31 18:14:22 +04:00
2007-07-23 15:38:29 +04:00
if ( ( message_push_string ( & req - > outbuf , server_devicetype ,
STR_TERMINATE | STR_ASCII ) = = - 1 )
| | ( message_push_string ( & req - > outbuf , fstype ,
STR_TERMINATE ) = = - 1 ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
2007-07-13 05:22:09 +04:00
1998-09-20 19:48:10 +04:00
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
2007-07-23 15:38:29 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , SMB_SUPPORT_SEARCH_BITS |
( lp_csc_policy ( SNUM ( conn ) ) < < 2 ) ) ;
2007-07-13 05:22:09 +04:00
2008-10-18 21:41:12 +04:00
if ( lp_msdfs_root ( SNUM ( conn ) ) & & lp_host_msdfs ( ) ) {
DEBUG ( 2 , ( " Serving %s as a Dfs root \n " ,
lp_servicename ( SNUM ( conn ) ) ) ) ;
SSVAL ( req - > outbuf , smb_vwv2 ,
SMB_SHARE_IN_DFS | SVAL ( req - > outbuf , smb_vwv2 ) ) ;
}
1998-08-14 21:38:29 +04:00
}
2000-03-09 01:14:30 +03:00
2007-07-13 05:22:09 +04:00
2001-09-15 16:55:59 +04:00
DEBUG ( 3 , ( " tconX service=%s \n " ,
service ) ) ;
2007-07-13 05:22:09 +04:00
1998-08-14 21:38:29 +04:00
/* set the incoming and outgoing tid to the just created one */
2007-07-23 15:38:29 +04:00
SSVAL ( req - > inbuf , smb_tid , conn - > cnum ) ;
SSVAL ( req - > outbuf , smb_tid , conn - > cnum ) ;
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
2009-07-16 00:59:11 +04:00
req - > tid = conn - > cnum ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2007-07-23 15:38:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an unknown type .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-07-23 13:36:09 +04:00
void reply_unknown_new ( struct smb_request * req , uint8 type )
{
DEBUG ( 0 , ( " unknown command type (%s): type=%d (0x%X) \n " ,
smb_fn_name ( type ) , type , type ) ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRunknownsmb ) ;
2007-07-23 13:36:09 +04:00
return ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an ioctl .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_ioctl ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-15 01:13:05 +04:00
uint16 device ;
uint16 function ;
uint32 ioctl_code ;
int replysize ;
1999-12-13 16:27:58 +03:00
char * p ;
2007-08-15 01:13:05 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBioctl ) ;
1999-12-13 16:27:58 +03:00
2007-08-15 01:13:05 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBioctl ) ;
return ;
}
2008-11-02 14:20:47 +03:00
device = SVAL ( req - > vwv + 1 , 0 ) ;
function = SVAL ( req - > vwv + 2 , 0 ) ;
2007-08-15 01:13:05 +04:00
ioctl_code = ( device < < 16 ) + function ;
1999-12-13 16:27:58 +03:00
DEBUG ( 4 , ( " Received IOCTL (code 0x%x) \n " , ioctl_code ) ) ;
2002-09-25 19:19:00 +04:00
switch ( ioctl_code ) {
1999-12-13 16:27:58 +03:00
case IOCTL_QUERY_JOB_INFO :
2007-08-15 01:13:05 +04:00
replysize = 32 ;
break ;
1999-12-13 16:27:58 +03:00
default :
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRnosupport ) ;
2007-08-15 01:13:05 +04:00
END_PROFILE ( SMBioctl ) ;
return ;
1999-12-13 16:27:58 +03:00
}
2007-08-15 01:13:05 +04:00
reply_outbuf ( req , 8 , replysize + 1 ) ;
SSVAL ( req - > outbuf , smb_vwv1 , replysize ) ; /* Total data bytes returned */
SSVAL ( req - > outbuf , smb_vwv5 , replysize ) ; /* Data bytes this buffer */
SSVAL ( req - > outbuf , smb_vwv6 , 52 ) ; /* Offset to data */
2007-09-08 00:57:01 +04:00
p = smb_buf ( req - > outbuf ) ;
memset ( p , ' \0 ' , replysize + 1 ) ; /* valgrind-safe. */
p + = 1 ; /* Allow for alignment */
1999-12-13 16:27:58 +03:00
2002-09-25 19:19:00 +04:00
switch ( ioctl_code ) {
case IOCTL_QUERY_JOB_INFO :
{
2008-10-09 17:25:17 +04:00
files_struct * fsp = file_fsp (
2008-11-02 14:20:47 +03:00
req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2003-09-09 00:27:28 +04:00
if ( ! fsp ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2003-09-09 00:27:28 +04:00
END_PROFILE ( SMBioctl ) ;
2007-08-15 01:13:05 +04:00
return ;
2003-09-09 00:27:28 +04:00
}
2010-04-24 01:26:33 +04:00
/* Job number */
if ( fsp - > print_file ) {
SSVAL ( p , 0 , fsp - > print_file - > rap_jobid ) ;
} else {
SSVAL ( p , 0 , 0 ) ;
}
2007-08-15 01:13:05 +04:00
srvstr_push ( ( char * ) req - > outbuf , req - > flags2 , p + 2 ,
2007-08-02 21:37:38 +04:00
global_myname ( ) , 15 ,
STR_TERMINATE | STR_ASCII ) ;
2004-05-22 09:01:25 +04:00
if ( conn ) {
2007-08-15 01:13:05 +04:00
srvstr_push ( ( char * ) req - > outbuf , req - > flags2 ,
2007-08-02 21:37:38 +04:00
p + 18 , lp_servicename ( SNUM ( conn ) ) ,
13 , STR_TERMINATE | STR_ASCII ) ;
2007-09-08 00:57:01 +04:00
} else {
2007-08-15 01:13:05 +04:00
memset ( p + 18 , 0 , 13 ) ;
}
2002-09-25 19:19:00 +04:00
break ;
}
1999-12-13 16:27:58 +03:00
}
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBioctl ) ;
2007-08-15 01:13:05 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2007-01-14 01:10:18 +03:00
Strange checkpath NTSTATUS mapping .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-11-03 00:20:48 +03:00
static NTSTATUS map_checkpath_error ( uint16_t flags2 , NTSTATUS status )
2007-01-14 01:10:18 +03:00
{
/* Strange DOS error code semantics only for checkpath... */
2008-11-03 00:20:48 +03:00
if ( ! ( flags2 & FLAGS2_32_BIT_ERROR_CODES ) ) {
2007-01-14 01:10:18 +03:00
if ( NT_STATUS_EQUAL ( NT_STATUS_OBJECT_NAME_INVALID , status ) ) {
/* We need to map to ERRbadpath */
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
}
}
return status ;
}
2007-09-12 03:57:59 +04:00
2007-01-14 01:10:18 +03:00
/****************************************************************************
Reply to a checkpath .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_checkpath ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * name = NULL ;
2003-08-13 07:28:06 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-08-13 07:28:06 +04:00
2007-01-14 01:10:18 +03:00
START_PROFILE ( SMBcheckpath ) ;
2001-03-13 06:45:09 +03:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & name , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-11-03 00:20:48 +03:00
status = map_checkpath_error ( req - > flags2 , status ) ;
2007-07-23 16:03:58 +04:00
reply_nterror ( req , status ) ;
2007-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2003-08-13 07:28:06 +04:00
2009-06-19 00:13:38 +04:00
DEBUG ( 3 , ( " reply_checkpath %s mode=%d \n " , name , ( int ) SVAL ( req - > vwv + 0 , 0 ) ) ) ;
status = filename_convert ( ctx ,
conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
name ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2009-06-19 00:13:38 +04:00
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2007-03-12 20:55:24 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2007-03-12 20:55:24 +03:00
}
goto path_err ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) & &
2009-06-23 02:26:56 +04:00
( SMB_VFS_STAT ( conn , smb_fname ) ! = 0 ) ) {
DEBUG ( 3 , ( " reply_checkpath: stat of %s failed (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) , strerror ( errno ) ) ) ;
2007-01-17 05:09:37 +03:00
status = map_nt_error_from_unix ( errno ) ;
goto path_err ;
}
1997-10-04 00:36:06 +04:00
2009-05-14 17:34:42 +04:00
if ( ! S_ISDIR ( smb_fname - > st . st_ex_mode ) ) {
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_NOT_A_DIRECTORY ,
ERRDOS , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-09-25 19:19:00 +04:00
}
1998-08-01 02:39:15 +04:00
2007-07-23 16:03:58 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2007-01-17 05:09:37 +03:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
path_err :
2007-01-17 05:09:37 +03:00
/* 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 .
*/
2008-11-03 00:20:48 +03:00
status = map_checkpath_error ( req - > flags2 , status ) ;
2007-07-23 16:03:58 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
2007-01-17 05:09:37 +03:00
/*
* Windows returns different error codes if
* the parent directory is valid but not the
* last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
* for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
* if the path is invalid .
*/
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpath ) ;
2009-06-23 02:26:56 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
2007-07-23 16:03:58 +04:00
reply_nterror ( req , status ) ;
2009-06-23 02:26:56 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
END_PROFILE ( SMBcheckpath ) ;
return ;
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
2008-01-05 02:37:24 +03:00
void reply_getatr ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
int mode = 0 ;
SMB_OFF_T size = 0 ;
time_t mtime = 0 ;
2008-11-01 19:35:48 +03:00
const char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2009-07-09 04:51:35 +04:00
bool ask_sharemode = lp_parm_bool ( SNUM ( conn ) , " smbd " , " search ask sharemode " , true ) ;
2003-10-09 03:21:36 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBgetatr ) ;
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req ( ctx , req , & fname , p , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird ! */
2007-09-11 22:31:29 +04:00
if ( * fname = = ' \0 ' ) {
2002-12-04 02:57:45 +03:00
mode = aHIDDEN | aDIR ;
2007-01-14 01:22:32 +03:00
if ( ! CAN_WRITE ( conn ) ) {
2002-12-04 02:57:45 +03:00
mode | = aRONLY ;
2007-01-14 01:22:32 +03:00
}
2002-12-04 02:57:45 +03:00
size = 0 ;
mtime = 0 ;
} else {
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx ,
conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
fname ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-19 00:13:38 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) & &
2009-06-23 02:26:56 +04:00
( SMB_VFS_STAT ( conn , smb_fname ) ! = 0 ) ) {
DEBUG ( 3 , ( " reply_getatr: stat of %s failed (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) ,
strerror ( errno ) ) ) ;
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 05:09:37 +03:00
2009-07-08 23:24:03 +04:00
mode = dos_mode ( conn , smb_fname ) ;
2009-05-14 17:34:42 +04:00
size = smb_fname - > st . st_ex_size ;
2009-07-09 04:51:35 +04:00
if ( ask_sharemode ) {
struct timespec write_time_ts ;
struct file_id fileid ;
ZERO_STRUCT ( write_time_ts ) ;
fileid = vfs_file_id_from_sbuf ( conn , & smb_fname - > st ) ;
get_file_infos ( fileid , NULL , & write_time_ts ) ;
if ( ! null_timespec ( write_time_ts ) ) {
2009-07-09 05:05:30 +04:00
update_stat_ex_mtime ( & smb_fname - > st , write_time_ts ) ;
2009-07-09 04:51:35 +04:00
}
}
2009-05-14 17:34:42 +04:00
mtime = convert_timespec_to_time_t ( smb_fname - > st . st_ex_mtime ) ;
2007-01-17 05:09:37 +03:00
if ( mode & aDIR ) {
size = 0 ;
}
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 19:09:49 +04:00
reply_outbuf ( req , 10 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , mode ) ;
2005-11-05 07:21:55 +03:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-08-14 19:09:49 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv1 , mtime & ~ 1 ) ;
2005-11-05 07:21:55 +03:00
} else {
2007-08-14 19:09:49 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv1 , mtime ) ;
2005-11-05 07:21:55 +03:00
}
2007-08-14 19:09:49 +04:00
SIVAL ( req - > outbuf , smb_vwv3 , ( uint32 ) size ) ;
1996-05-04 11:50:46 +04:00
2009-11-23 18:33:26 +03:00
if ( get_Protocol ( ) > = PROTOCOL_NT1 ) {
2007-08-14 19:09:49 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 ) | FLAGS2_IS_LONG_NAME ) ;
2005-11-05 07:21:55 +03:00
}
2008-10-19 17:30:12 +04:00
2009-06-23 02:26:56 +04:00
DEBUG ( 3 , ( " reply_getatr: name=%s mode=%d size=%u \n " ,
smb_fname_str_dbg ( smb_fname ) , mode , ( unsigned int ) size ) ) ;
2007-09-12 03:57:59 +04:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_fname ) ;
2009-06-23 02:26:56 +04:00
TALLOC_FREE ( fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBgetatr ) ;
2007-08-14 19:09:49 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a setatr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_setatr ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2009-01-24 01:40:19 +03:00
struct smb_file_time ft ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
int mode ;
time_t mtime ;
2008-11-01 19:35:48 +03:00
const char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBsetatr ) ;
2009-01-24 01:40:19 +03:00
ZERO_STRUCT ( ft ) ;
2008-03-12 17:39:38 +03:00
2007-08-14 19:26:54 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-14 19:26:54 +04:00
}
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req ( ctx , req , & fname , p , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx ,
conn ,
2007-09-11 22:31:29 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 19:26:54 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-09-12 03:57:59 +04:00
2009-07-03 00:39:20 +04:00
if ( smb_fname - > base_name [ 0 ] = = ' . ' & &
smb_fname - > base_name [ 1 ] = = ' \0 ' ) {
2007-01-03 15:01:17 +03:00
/*
* Not sure here is the right place to catch this
* condition . Might be moved to somewhere else later - - vl
*/
2007-08-14 19:26:54 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-01-03 15:01:17 +03:00
}
2008-11-02 14:20:47 +03:00
mode = SVAL ( req - > vwv + 0 , 0 ) ;
mtime = srv_make_unix_date3 ( req - > vwv + 1 ) ;
2007-09-14 02:08:59 +04:00
2009-01-24 01:40:19 +03:00
ft . mtime = convert_time_t_to_timespec ( mtime ) ;
2009-07-03 00:39:20 +04:00
status = smb_set_file_time ( conn , NULL , smb_fname , & ft , true ) ;
2008-03-12 17:39:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2008-02-06 09:10:50 +03:00
}
2003-08-15 03:15:02 +04:00
if ( mode ! = FILE_ATTRIBUTE_NORMAL ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
if ( VALID_STAT_OF_DIR ( smb_fname - > st ) )
2003-08-15 03:15:02 +04:00
mode | = aDIR ;
else
mode & = ~ aDIR ;
2009-07-07 01:36:16 +04:00
if ( file_set_dosmode ( conn , smb_fname , mode , NULL ,
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
false ) ! = 0 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
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-08-14 19:26:54 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2008-10-19 17:30:12 +04:00
2009-07-03 00:39:20 +04:00
DEBUG ( 3 , ( " setatr name=%s mode=%d \n " , smb_fname_str_dbg ( smb_fname ) ,
mode ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a dskattr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_dskattr ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2008-10-14 03:59:36 +04:00
uint64_t dfree , dsize , bsize ;
2002-07-15 14:35:28 +04:00
START_PROFILE ( SMBdskattr ) ;
2008-10-14 03:59:36 +04:00
if ( get_dfree_info ( conn , " . " , True , & bsize , & dfree , & dsize ) = = ( uint64_t ) - 1 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2005-03-16 04:41:21 +03:00
END_PROFILE ( SMBdskattr ) ;
2007-07-30 14:30:19 +04:00
return ;
2005-03-16 04:41:21 +03:00
}
2007-07-30 14:30:19 +04:00
reply_outbuf ( req , 5 , 0 ) ;
2008-10-19 17:30:12 +04:00
2009-11-23 18:33:26 +03:00
if ( get_Protocol ( ) < = PROTOCOL_LANMAN2 ) {
2002-07-15 14:35:28 +04:00
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
2008-10-14 03:59:36 +04:00
dsize = ( uint64_t ) ( ( total_space + 63 * 512 ) / ( 64 * 512 ) ) ;
dfree = ( uint64_t ) ( ( free_space + 63 * 512 ) / ( 64 * 512 ) ) ;
2008-10-19 17:30:12 +04:00
2002-07-15 14:35:28 +04:00
if ( dsize > 0xFFFF ) dsize = 0xFFFF ;
if ( dfree > 0xFFFF ) dfree = 0xFFFF ;
2007-07-30 14:30:19 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , dsize ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 64 ) ; /* this must be 64 for dos systems */
SSVAL ( req - > outbuf , smb_vwv2 , 512 ) ; /* and this must be 512 */
SSVAL ( req - > outbuf , smb_vwv3 , dfree ) ;
2002-07-15 14:35:28 +04:00
} else {
2007-07-30 14:30:19 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , dsize ) ;
SSVAL ( req - > outbuf , smb_vwv1 , bsize / 512 ) ;
SSVAL ( req - > outbuf , smb_vwv2 , 512 ) ;
SSVAL ( req - > outbuf , smb_vwv3 , dfree ) ;
2002-07-15 14:35:28 +04:00
}
DEBUG ( 3 , ( " dskattr dfree=%d \n " , ( unsigned int ) dfree ) ) ;
END_PROFILE ( SMBdskattr ) ;
2007-07-30 14:30:19 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2009-06-11 03:02:00 +04:00
/*
* Utility function to split the filename from the directory .
*/
static NTSTATUS split_fname_dir_mask ( TALLOC_CTX * ctx , const char * fname_in ,
char * * fname_dir_out ,
char * * fname_mask_out )
{
const char * p = NULL ;
char * fname_dir = NULL ;
char * fname_mask = NULL ;
p = strrchr_m ( fname_in , ' / ' ) ;
if ( ! p ) {
fname_dir = talloc_strdup ( ctx , " . " ) ;
fname_mask = talloc_strdup ( ctx , fname_in ) ;
} else {
fname_dir = talloc_strndup ( ctx , fname_in ,
PTR_DIFF ( p , fname_in ) ) ;
fname_mask = talloc_strdup ( ctx , p + 1 ) ;
}
if ( ! fname_dir | | ! fname_mask ) {
TALLOC_FREE ( fname_dir ) ;
TALLOC_FREE ( fname_mask ) ;
return NT_STATUS_NO_MEMORY ;
}
* fname_dir_out = fname_dir ;
* fname_mask_out = fname_mask ;
return NT_STATUS_OK ;
}
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
2008-01-05 02:37:24 +03:00
void reply_search ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-19 02:07:14 +04:00
char * path = NULL ;
2008-11-01 19:35:48 +03:00
const char * mask = NULL ;
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2009-07-21 22:35:17 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-13 01:48:20 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
SMB_OFF_T size ;
2005-06-25 07:03:44 +04:00
uint32 mode ;
2009-05-14 17:34:42 +04:00
struct timespec date ;
2005-06-25 07:03:44 +04:00
uint32 dirtype ;
2003-10-30 00:28:00 +03:00
unsigned int numentries = 0 ;
unsigned int maxentries = 0 ;
2007-10-19 04:40:25 +04:00
bool finished = False ;
2008-11-01 19:35:48 +03:00
const char * p ;
2002-12-04 02:57:45 +03:00
int status_len ;
char status [ 21 ] ;
int dptr_num = - 1 ;
2007-10-19 04:40:25 +04:00
bool check_descend = False ;
bool expect_close = False ;
2003-10-09 03:21:36 +04:00
NTSTATUS nt_status ;
2007-10-19 04:40:25 +04:00
bool mask_contains_wcard = False ;
bool allow_long_path_components = ( req - > flags2 & FLAGS2_LONG_PATH_COMPONENTS ) ? True : False ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2008-04-07 11:21:19 +04:00
bool ask_sharemode = lp_parm_bool ( SNUM ( conn ) , " smbd " , " search ask sharemode " , true ) ;
2009-08-07 11:31:45 +04:00
struct dptr_struct * dirptr = NULL ;
2010-06-12 13:41:22 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2005-03-29 04:36:30 +04:00
2006-05-05 11:15:45 +04:00
START_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-08-15 01:32:52 +04:00
}
2005-06-23 01:20:41 +04:00
if ( lp_posix_pathnames ( ) ) {
2008-11-03 00:33:20 +03:00
reply_unknown_new ( req , req - > cmd ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2005-06-23 01:20:41 +04:00
}
2002-12-04 02:57:45 +03:00
/* If we were called as SMBffirst then we must expect close. */
2008-11-03 00:33:20 +03:00
if ( req - > cmd = = SMBffirst ) {
2002-12-04 02:57:45 +03:00
expect_close = True ;
2007-01-17 00:04:30 +03:00
}
2007-08-15 01:32:52 +04:00
reply_outbuf ( req , 1 , 3 ) ;
2008-11-02 14:20:47 +03:00
maxentries = SVAL ( req - > vwv + 0 , 0 ) ;
dirtype = SVAL ( req - > vwv + 1 , 0 ) ;
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req_wcard ( ctx , req , & path , p , STR_TERMINATE ,
& nt_status , & mask_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , nt_status ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2003-10-09 03:21:36 +04: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 ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
/* dirtype &= ~aDIR; */
if ( status_len = = 0 ) {
2009-07-25 05:38:40 +04:00
nt_status = filename_convert ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
path ,
UCF_ALWAYS_ALLOW_WCARD_LCOMP ,
& mask_contains_wcard ,
& smb_fname ) ;
2009-06-19 02:07:14 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2009-06-19 02:07:14 +04:00
}
reply_nterror ( req , nt_status ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2009-06-19 02:07:14 +04:00
}
2009-07-21 22:35:17 +04:00
directory = smb_fname - > base_name ;
2002-12-04 02:57:45 +03:00
p = strrchr_m ( directory , ' / ' ) ;
2008-11-01 19:28:25 +03:00
if ( ( p ! = NULL ) & & ( * directory ! = ' / ' ) ) {
mask = p + 1 ;
directory = talloc_strndup ( ctx , directory ,
PTR_DIFF ( p , directory ) ) ;
} else {
2007-09-13 01:48:20 +04:00
mask = directory ;
directory = talloc_strdup ( ctx , " . " ) ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
2008-11-01 19:28:25 +03:00
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-01-17 00:04:30 +03:00
}
2008-11-01 19:28:25 +03:00
2002-12-04 02:57:45 +03:00
memset ( ( char * ) status , ' \0 ' , 21 ) ;
SCVAL ( status , 0 , ( dirtype & 0x1F ) ) ;
2007-09-08 00:57:01 +04:00
nt_status = dptr_create ( conn ,
directory ,
True ,
expect_close ,
req - > smbpid ,
mask ,
mask_contains_wcard ,
dirtype ,
2009-08-07 11:31:45 +04:00
& dirptr ) ;
2007-09-08 00:57:01 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
reply_nterror ( req , nt_status ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-09-08 00:57:01 +04:00
}
2009-08-07 11:31:45 +04:00
dptr_num = dptr_dnum ( dirptr ) ;
2002-12-04 02:57:45 +03:00
} else {
int status_dirtype ;
2009-08-07 11:31:45 +04:00
const char * dirpath ;
2002-12-04 02:57:45 +03:00
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
2009-08-06 14:15:51 +04:00
dirptr = dptr_fetch ( sconn , status + 12 , & dptr_num ) ;
2009-08-07 11:31:45 +04:00
if ( ! dirptr ) {
2002-12-04 02:57:45 +03:00
goto SearchEmpty ;
2007-01-17 00:04:30 +03:00
}
2009-08-06 14:15:51 +04:00
dirpath = dptr_path ( sconn , dptr_num ) ;
2009-08-07 11:31:45 +04:00
directory = talloc_strdup ( ctx , dirpath ) ;
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
2009-08-06 14:15:51 +04:00
mask = dptr_wcard ( sconn , dptr_num ) ;
2007-09-13 01:48:20 +04:00
if ( ! mask ) {
goto SearchEmpty ;
}
2007-03-09 05:40:49 +03:00
/*
* For a ' continue ' search we have no string . So
* check from the initial saved string .
*/
mask_contains_wcard = ms_has_wild ( mask ) ;
2009-08-06 14:15:51 +04:00
dirtype = dptr_attr ( sconn , dptr_num ) ;
2007-01-17 00:04:30 +03:00
}
DEBUG ( 4 , ( " dptr_num is %d \n " , dptr_num ) ) ;
2009-02-03 08:37:51 +03:00
/* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
2009-08-07 11:31:45 +04:00
dptr_init_search_op ( dirptr ) ;
2009-02-03 08:37:51 +03:00
2007-08-15 01:32:52 +04:00
if ( ( dirtype & 0x1F ) = = aVOLID ) {
char buf [ DIR_STRUCT_SIZE ] ;
memcpy ( buf , status , 21 ) ;
2007-09-13 01:48:20 +04:00
if ( ! make_dir_struct ( ctx , buf , " ??????????? " , volume_label ( SNUM ( conn ) ) ,
0 , aVOLID , 0 , ! allow_long_path_components ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-09-13 01:48:20 +04:00
}
2009-08-06 14:15:51 +04:00
dptr_fill ( sconn , buf + 12 , dptr_num ) ;
2007-08-15 01:32:52 +04:00
if ( dptr_zero ( buf + 12 ) & & ( status_len = = 0 ) ) {
2007-01-17 00:04:30 +03:00
numentries = 1 ;
2002-12-05 01:48:13 +03:00
} else {
2007-01-17 00:04:30 +03:00
numentries = 0 ;
2002-12-04 02:57:45 +03:00
}
2007-08-15 01:32:52 +04:00
if ( message_push_blob ( & req - > outbuf ,
data_blob_const ( buf , sizeof ( buf ) ) )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-08-15 01:32:52 +04:00
}
2007-01-17 00:04:30 +03:00
} else {
unsigned int i ;
2007-08-15 01:32:52 +04:00
maxentries = MIN (
maxentries ,
( ( BUFFER_SIZE -
( ( uint8 * ) smb_buf ( req - > outbuf ) + 3 - req - > outbuf ) )
/ DIR_STRUCT_SIZE ) ) ;
2002-12-04 02:57:45 +03:00
2007-01-17 00:04:30 +03:00
DEBUG ( 8 , ( " dirpath=<%s> dontdescend=<%s> \n " ,
2009-08-07 11:31:45 +04:00
directory , lp_dontdescend ( SNUM ( conn ) ) ) ) ;
if ( in_list ( directory , lp_dontdescend ( SNUM ( conn ) ) , True ) ) {
2007-01-17 00:04:30 +03:00
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 + + ) {
2008-04-07 11:21:19 +04:00
finished = ! get_dir_entry ( ctx ,
2009-08-07 11:31:45 +04:00
dirptr ,
2008-04-07 11:21:19 +04:00
mask ,
dirtype ,
& fname ,
& size ,
& mode ,
& date ,
check_descend ,
ask_sharemode ) ;
2007-01-17 00:04:30 +03:00
if ( ! finished ) {
2007-08-15 01:32:52 +04:00
char buf [ DIR_STRUCT_SIZE ] ;
memcpy ( buf , status , 21 ) ;
2007-09-13 01:48:20 +04:00
if ( ! make_dir_struct ( ctx ,
buf ,
mask ,
fname ,
size ,
mode ,
2009-05-14 17:34:42 +04:00
convert_timespec_to_time_t ( date ) ,
2007-09-13 01:48:20 +04:00
! allow_long_path_components ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-09-13 01:48:20 +04:00
}
2009-08-06 14:15:51 +04:00
if ( ! dptr_fill ( sconn , buf + 12 , dptr_num ) ) {
2007-01-17 00:04:30 +03:00
break ;
2002-12-04 02:57:45 +03:00
}
2007-08-15 01:32:52 +04:00
if ( message_push_blob ( & req - > outbuf ,
data_blob_const ( buf , sizeof ( buf ) ) )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-08-15 01:32:52 +04:00
}
2007-01-17 00:04:30 +03:00
numentries + + ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
SearchEmpty :
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
/* If we were called as SMBffirst with smb_search_id == NULL
and no entries were found then return error and close dirptr
( X / Open spec ) */
2007-01-17 00:04:30 +03:00
if ( numentries = = 0 ) {
2009-08-06 14:15:51 +04:00
dptr_close ( sconn , & 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 */
2009-08-06 14:15:51 +04:00
dptr_close ( sconn , & dptr_num ) ;
2002-12-04 02:57:45 +03:00
}
/* If we were called as SMBfunique, then we can close the dirptr now ! */
2008-11-03 00:33:20 +03:00
if ( dptr_num > = 0 & & req - > cmd = = SMBfunique ) {
2009-08-06 14:15:51 +04:00
dptr_close ( sconn , & dptr_num ) ;
2005-01-29 02:17:12 +03:00
}
2005-10-31 23:11:58 +03:00
if ( ( numentries = = 0 ) & & ! mask_contains_wcard ) {
2007-08-15 01:32:52 +04:00
reply_botherror ( req , STATUS_NO_MORE_FILES , ERRDOS , ERRnofiles ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2005-01-29 02:17:12 +03:00
}
2002-12-04 02:57:45 +03:00
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , numentries ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 3 + numentries * DIR_STRUCT_SIZE ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 5 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , numentries * DIR_STRUCT_SIZE ) ;
2002-12-04 02:57:45 +03:00
2005-03-29 04:36:30 +04:00
/* The replies here are never long name. */
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 ) & ( ~ FLAGS2_IS_LONG_NAME ) ) ;
2005-03-29 04:36:30 +04:00
if ( ! allow_long_path_components ) {
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 )
& ( ~ FLAGS2_LONG_PATH_COMPONENTS ) ) ;
2005-03-29 04:36:30 +04:00
}
2005-03-25 22:52:01 +03:00
/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
( SVAL ( req - > outbuf , smb_flg2 ) & ( ~ FLAGS2_UNICODE_STRINGS ) ) ) ;
2002-12-04 02:57:45 +03:00
2007-09-08 00:57:01 +04:00
DEBUG ( 4 , ( " %s mask=%s path=%s dtype=%d nument=%u of %u \n " ,
2008-11-03 00:33:20 +03:00
smb_fn_name ( req - > cmd ) ,
2007-09-08 00:57:01 +04:00
mask ,
2009-08-07 11:31:45 +04:00
directory ,
2007-09-08 00:57:01 +04:00
dirtype ,
numentries ,
maxentries ) ) ;
2009-07-21 22:35:17 +04:00
out :
2009-08-07 11:31:45 +04:00
TALLOC_FREE ( directory ) ;
2009-07-21 22:35:17 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a fclose ( stop directory search ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_fclose ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int status_len ;
char status [ 21 ] ;
int dptr_num = - 2 ;
2008-11-01 19:35:48 +03:00
const char * p ;
2007-09-12 03:57:59 +04:00
char * path = NULL ;
2003-10-09 03:21:36 +04:00
NTSTATUS err ;
2007-10-19 04:40:25 +04:00
bool path_contains_wcard = False ;
2007-09-12 03:57:59 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2010-06-12 13:41:40 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
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 ( ) ) {
2008-11-03 00:33:20 +03:00
reply_unknown_new ( req , req - > cmd ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2005-06-23 01:20:41 +04:00
}
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req_wcard ( ctx , req , & path , p , STR_TERMINATE ,
& err , & path_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( err ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , err ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
p + + ;
status_len = SVAL ( p , 0 ) ;
p + = 2 ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( status_len = = 0 ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRsrverror ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
memcpy ( status , p , 21 ) ;
1996-05-04 11:50:46 +04:00
2009-08-06 14:15:51 +04:00
if ( dptr_fetch ( sconn , status + 12 , & dptr_num ) ) {
2002-12-04 02:57:45 +03:00
/* Close the dptr - we know it's gone */
2009-08-06 14:15:51 +04:00
dptr_close ( sconn , & dptr_num ) ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 01:32:52 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , 0 ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " search close \n " ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an open .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-23 04:58:28 +04:00
2008-01-05 02:37:24 +03:00
void reply_open ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2005-07-08 08:51:27 +04:00
uint32 fattr = 0 ;
2002-12-04 02:57:45 +03:00
SMB_OFF_T size = 0 ;
time_t mtime = 0 ;
2005-07-08 08:51:27 +04:00
int info ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 17:57:36 +04:00
int oplock_request ;
2005-07-08 08:51:27 +04:00
int deny_mode ;
2007-08-14 17:57:36 +04:00
uint32 dos_attr ;
2005-07-08 08:51:27 +04:00
uint32 access_mask ;
uint32 share_mode ;
uint32 create_disposition ;
uint32 create_options = 0 ;
2010-03-06 02:10:30 +03:00
uint32_t private_flags = 0 ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2009-07-09 04:51:35 +04:00
bool ask_sharemode = lp_parm_bool ( SNUM ( conn ) , " smbd " , " search ask sharemode " , true ) ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-07-05 20:26:27 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopen ) ;
2007-07-05 20:26:27 +04:00
2007-08-14 18:31:55 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-14 17:57:36 +04:00
}
2007-09-11 22:31:29 +04:00
2007-08-14 18:31:55 +04:00
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
2008-11-02 14:20:47 +03:00
deny_mode = SVAL ( req - > vwv + 0 , 0 ) ;
dos_attr = SVAL ( req - > vwv + 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:31:55 +04:00
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2000-03-09 01:14:30 +03:00
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx ,
2009-06-17 04:23:54 +04:00
conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
fname ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2009-06-17 04:23:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
goto out ;
2005-07-08 08:51:27 +04:00
}
2009-07-21 20:29:59 +04:00
if ( ! map_open_params_to_ntcreate ( smb_fname , deny_mode ,
OPENX_FILE_EXISTS_OPEN , & access_mask ,
& share_mode , & create_disposition ,
2010-03-06 02:10:30 +03:00
& create_options , & private_flags ) ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRDOS , ERRbadaccess ) ;
2009-06-17 04:23:54 +04:00
goto out ;
}
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_mode , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
dos_attr , /* file_attributes */
oplock_request , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
private_flags ,
2008-10-21 04:43:45 +04:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2009-06-12 23:54:11 +04:00
& info ) ; /* pinfo */
2002-12-04 02:57:45 +03:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:31:55 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-16 04:37:07 +04:00
}
2007-08-16 21:42:34 +04:00
reply_openerror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2009-06-05 05:39:55 +04:00
size = smb_fname - > st . st_ex_size ;
2009-07-08 23:24:03 +04:00
fattr = dos_mode ( conn , smb_fname ) ;
2009-07-09 04:51:35 +04:00
/* Deal with other possible opens having a modified
write time . JRA . */
if ( ask_sharemode ) {
struct timespec write_time_ts ;
ZERO_STRUCT ( write_time_ts ) ;
get_file_infos ( fsp - > file_id , NULL , & write_time_ts ) ;
if ( ! null_timespec ( write_time_ts ) ) {
2009-07-09 05:05:30 +04:00
update_stat_ex_mtime ( & smb_fname - > st , write_time_ts ) ;
2009-07-09 04:51:35 +04:00
}
}
2009-06-05 05:39:55 +04:00
mtime = convert_timespec_to_time_t ( smb_fname - > st . st_ex_mtime ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( fattr & aDIR ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 3 , ( " attempt to open a directory %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
2008-10-09 18:27:49 +04:00
close_file ( req , fsp , ERROR_CLOSE ) ;
2009-12-21 22:05:25 +03:00
reply_botherror ( req , NT_STATUS_ACCESS_DENIED ,
ERRDOS , ERRnoaccess ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 18:31:55 +04:00
reply_outbuf ( req , 7 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
SSVAL ( req - > outbuf , smb_vwv1 , fattr ) ;
2005-07-08 08:51:27 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-08-14 18:31:55 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv2 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2007-08-14 18:31:55 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv2 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 18:31:55 +04:00
SIVAL ( req - > outbuf , smb_vwv4 , ( uint32 ) size ) ;
SSVAL ( req - > outbuf , smb_vwv6 , deny_mode ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 18:31:55 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2008-10-19 17:30:12 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 18:31:55 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2009-06-05 05:39:55 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an open and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_open_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2007-07-23 13:54:36 +04:00
uint16 open_flags ;
int deny_mode ;
uint32 smb_attr ;
2002-12-04 02:57:45 +03:00
/* Breakout the oplock request bits so we can set the
reply bits separately . */
2007-07-23 13:54:36 +04:00
int ex_oplock_request ;
int core_oplock_request ;
int oplock_request ;
1996-05-04 11:50:46 +04:00
#if 0
2008-11-02 14:20:47 +03:00
int smb_sattr = SVAL ( req - > vwv + 4 , 0 ) ;
uint32 smb_time = make_unix_date3 ( req - > vwv + 6 ) ;
1996-05-04 11:50:46 +04:00
# endif
2007-07-23 13:54:36 +04:00
int smb_ofun ;
2005-07-08 08:51:27 +04:00
uint32 fattr = 0 ;
int mtime = 0 ;
2002-12-04 02:57:45 +03:00
int smb_action = 0 ;
files_struct * fsp ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2008-10-14 03:59:36 +04:00
uint64_t allocation_size ;
2005-04-05 05:20:32 +04:00
ssize_t retval = - 1 ;
2005-07-08 08:51:27 +04:00
uint32 access_mask ;
uint32 share_mode ;
uint32 create_disposition ;
uint32 create_options = 0 ;
2010-03-06 02:10:30 +03:00
uint32_t private_flags = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-04-05 05:20:32 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
if ( req - > wct < 15 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-07-23 13:54:36 +04:00
}
2008-11-02 14:20:47 +03:00
open_flags = SVAL ( req - > vwv + 2 , 0 ) ;
deny_mode = SVAL ( req - > vwv + 3 , 0 ) ;
smb_attr = SVAL ( req - > vwv + 5 , 0 ) ;
2007-07-23 13:54:36 +04:00
ex_oplock_request = EXTENDED_OPLOCK_REQUEST ( req - > inbuf ) ;
core_oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
oplock_request = ex_oplock_request | core_oplock_request ;
2008-11-02 14:20:47 +03:00
smb_ofun = SVAL ( req - > vwv + 8 , 0 ) ;
allocation_size = ( uint64_t ) IVAL ( req - > vwv + 9 , 0 ) ;
2007-07-05 20:26:27 +04:00
2002-12-04 02:57:45 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
if ( lp_nt_pipe_support ( ) ) {
2007-07-23 13:54:36 +04:00
reply_open_pipe_and_X ( conn , req ) ;
2002-12-04 02:57:45 +03:00
} else {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NETWORK_ACCESS_DENIED ) ;
2002-12-04 02:57:45 +03:00
}
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
1996-08-15 19:11:34 +04:00
2002-12-04 02:57:45 +03:00
/* XXXX we need to handle passed times, sattr and flags */
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-23 13:54:36 +04:00
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2000-03-09 01:14:30 +03:00
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx ,
2009-06-17 04:23:54 +04:00
conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
fname ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2009-06-17 04:23:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
}
2009-07-21 20:29:59 +04:00
if ( ! map_open_params_to_ntcreate ( smb_fname , deny_mode , smb_ofun ,
& access_mask , & share_mode ,
& create_disposition ,
2010-03-06 02:10:30 +03:00
& create_options ,
& private_flags ) ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRDOS , ERRbadaccess ) ;
2009-06-17 04:23:54 +04:00
goto out ;
}
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_mode , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
smb_attr , /* file_attributes */
oplock_request , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
private_flags ,
2008-10-21 04:43:45 +04:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2009-06-12 23:54:11 +04:00
& smb_action ) ; /* pinfo */
2007-08-16 21:42:34 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-23 13:54:36 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-15 17:44:34 +04:00
}
2007-08-16 21:42:34 +04:00
reply_openerror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
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 ) {
2008-10-09 18:27:49 +04:00
close_file ( req , fsp , ERROR_CLOSE ) ;
2007-07-23 13:54:36 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2005-04-05 05:20:32 +04:00
}
retval = vfs_set_filelen ( fsp , ( SMB_OFF_T ) allocation_size ) ;
if ( retval < 0 ) {
2008-10-09 18:27:49 +04:00
close_file ( req , fsp , ERROR_CLOSE ) ;
2007-07-23 13:54:36 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2005-04-01 04:21:55 +04:00
}
2009-06-05 05:39:55 +04:00
smb_fname - > st . st_ex_size =
SMB_VFS_GET_ALLOC_SIZE ( conn , fsp , & smb_fname - > st ) ;
2005-04-01 04:21:55 +04:00
}
2009-07-08 23:24:03 +04:00
fattr = dos_mode ( conn , smb_fname ) ;
2009-06-05 05:39:55 +04:00
mtime = convert_timespec_to_time_t ( smb_fname - > st . st_ex_mtime ) ;
2005-07-08 08:51:27 +04:00
if ( fattr & aDIR ) {
2008-10-09 18:27:49 +04:00
close_file ( req , fsp , ERROR_CLOSE ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
/* If the caller set the extended oplock request bit
and we granted one ( by whatever means ) - set the
correct bit for extended oplock reply .
*/
2005-07-08 08:51:27 +04:00
if ( ex_oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2002-12-04 02:57:45 +03:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( ex_oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2002-12-04 02:57:45 +03:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
/* If the caller set the core oplock request bit
and we granted one ( by whatever means ) - set the
correct bit for core oplock reply .
*/
2007-07-23 13:54:36 +04:00
if ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
reply_outbuf ( req , 19 , 0 ) ;
} else {
reply_outbuf ( req , 15 , 0 ) ;
}
2005-07-08 08:51:27 +04:00
if ( core_oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-07-23 13:54:36 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( core_oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-07-23 13:54:36 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2007-07-23 13:54:36 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , fsp - > fnum ) ;
SSVAL ( req - > outbuf , smb_vwv3 , fattr ) ;
2005-07-08 08:51:27 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-07-23 13:54:36 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2007-07-23 13:54:36 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2009-06-05 05:39:55 +04:00
SIVAL ( req - > outbuf , smb_vwv6 , ( uint32 ) smb_fname - > st . st_ex_size ) ;
2007-07-23 13:54:36 +04:00
SSVAL ( req - > outbuf , smb_vwv8 , GET_OPENX_MODE ( deny_mode ) ) ;
SSVAL ( req - > outbuf , smb_vwv11 , smb_action ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
2010-06-03 12:36:05 +04:00
SIVAL ( req - > outbuf , smb_vwv15 , SEC_STD_ALL ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2009-06-05 05:39:55 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a SMBulogoffX .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_ulogoffX ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2010-06-12 13:42:06 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2007-07-30 23:53:57 +04:00
user_struct * vuser ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBulogoffX ) ;
1996-05-04 11:50:46 +04:00
2009-05-26 18:38:45 +04:00
vuser = get_valid_user_struct ( sconn , req - > vuid ) ;
2007-07-30 23:53:57 +04:00
if ( vuser = = NULL ) {
DEBUG ( 3 , ( " ulogoff, vuser id %d does not map to user. \n " ,
req - > vuid ) ) ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
/* in user level security we are supposed to close any files
open by this user */
2007-07-30 23:53:57 +04:00
if ( ( vuser ! = NULL ) & & ( lp_security ( ) ! = SEC_SHARE ) ) {
file_close_user ( req - > vuid ) ;
}
1996-10-05 14:41:13 +04:00
2009-05-26 18:38:45 +04:00
invalidate_vuid ( sconn , req - > vuid ) ;
1996-10-26 00:30:22 +04:00
2007-07-30 23:53:57 +04:00
reply_outbuf ( req , 2 , 0 ) ;
1996-05-04 11:50:46 +04:00
2007-07-30 23:53:57 +04:00
DEBUG ( 3 , ( " ulogoffX vuid=%d \n " , req - > vuid ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBulogoffX ) ;
2009-07-16 00:59:11 +04:00
req - > vuid = UID_FIELD_INVALID ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a mknew or a create .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_mknew ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2007-08-14 00:29:24 +04:00
uint32 fattr = 0 ;
2009-01-24 01:40:19 +03:00
struct smb_file_time ft ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 00:29:24 +04:00
int oplock_request = 0 ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2005-07-08 08:51:27 +04:00
uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE ;
uint32 share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE ;
uint32 create_disposition ;
uint32 create_options = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-07-08 08:51:27 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcreate ) ;
2009-01-24 01:40:19 +03:00
ZERO_STRUCT ( ft ) ;
2007-07-05 20:26:27 +04:00
2007-08-14 00:29:24 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-14 00:29:24 +04:00
}
2002-12-04 02:57:45 +03:00
2008-11-02 14:20:47 +03:00
fattr = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-14 00:29:24 +04:00
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
2007-01-03 09:19:11 +03:00
2009-01-24 01:40:19 +03:00
/* mtime. */
ft . mtime = convert_time_t_to_timespec ( srv_make_unix_date3 ( req - > vwv + 1 ) ) ;
2007-08-14 00:29:24 +04:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 00:29:24 +04:00
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx ,
2009-06-17 04:23:54 +04:00
conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
fname ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2009-06-17 04:23:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
goto out ;
}
2005-07-08 08:51:27 +04:00
if ( fattr & aVOLID ) {
2007-08-14 00:29:24 +04:00
DEBUG ( 0 , ( " Attempt to create file (%s) with volid set - "
2009-07-02 03:15:52 +04:00
" please report this \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2005-07-08 08:51:27 +04:00
}
2008-11-03 00:33:20 +03:00
if ( req - > cmd = = SMBmknew ) {
2002-12-04 02:57:45 +03:00
/* 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
}
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_mode , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
fattr , /* file_attributes */
oplock_request , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-10-21 04:43:45 +04:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2009-06-12 23:54:11 +04:00
NULL ) ; /* pinfo */
2007-08-14 00:29:24 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 00:29:24 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-06-05 05:39:55 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2007-10-11 00:34:30 +04:00
reply_openerror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 00:29:24 +04:00
2009-06-05 05:39:55 +04:00
ft . atime = smb_fname - > st . st_ex_atime ; /* atime. */
2009-07-03 00:39:20 +04:00
status = smb_set_file_time ( conn , fsp , smb_fname , & ft , true ) ;
2008-03-12 17:39:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcreate ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2008-03-12 17:39:38 +03:00
}
2007-01-03 09:19:11 +03:00
2007-08-14 00:29:24 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
1996-10-05 14:41:13 +04:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 00:29:24 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 00:29:24 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 00:29:24 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 00:29:24 +04:00
2009-07-03 00:39:20 +04:00
DEBUG ( 2 , ( " reply_mknew: file %s \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
DEBUG ( 3 , ( " reply_mknew %s fd=%d dmode=0x%x \n " ,
smb_fname_str_dbg ( smb_fname ) , fsp - > fh - > fd ,
( unsigned int ) fattr ) ) ;
1998-08-01 02:39:15 +04:00
2009-06-05 05:39:55 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcreate ) ;
2007-08-14 00:29:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a create temporary file .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_ctemp ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2007-08-14 19:42:39 +04:00
uint32 fattr ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 19:42:39 +04:00
int oplock_request ;
2002-12-04 02:57:45 +03:00
int tmpfd ;
2007-08-14 19:42:39 +04:00
char * s ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-14 19:42:39 +04:00
}
2007-07-05 20:26:27 +04:00
2008-11-02 14:20:47 +03:00
fattr = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-14 19:42:39 +04:00
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:42:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2007-09-12 03:57:59 +04:00
if ( * fname ) {
fname = talloc_asprintf ( ctx ,
" %s/TMXXXXXX " ,
fname ) ;
2004-04-03 02:11:08 +04:00
} else {
2007-09-12 03:57:59 +04:00
fname = talloc_strdup ( ctx , " TMXXXXXX " ) ;
}
if ( ! fname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2004-04-03 02:11:08 +04:00
}
2002-12-04 02:57:45 +03:00
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx , conn ,
2007-09-11 22:31:29 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 19:42:39 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 19:42:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2002-12-04 02:57:45 +03:00
2009-06-12 23:54:11 +04:00
tmpfd = mkstemp ( smb_fname - > base_name ) ;
2002-12-04 02:57:45 +03:00
if ( tmpfd = = - 1 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2009-06-23 02:26:56 +04:00
SMB_VFS_STAT ( conn , smb_fname ) ;
2002-12-04 02:57:45 +03:00
/* We should fail if file does not exist. */
2008-11-21 05:55:24 +03:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-11-21 05:55:24 +03:00
FILE_GENERIC_READ | FILE_GENERIC_WRITE , /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE , /* share_access */
FILE_OPEN , /* create_disposition*/
0 , /* create_options */
fattr , /* file_attributes */
oplock_request , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-11-21 05:55:24 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2009-06-12 23:54:11 +04:00
NULL ) ; /* pinfo */
2002-12-04 02:57:45 +03:00
2009-04-21 01:58:26 +04:00
/* close fd from mkstemp() */
2002-12-04 02:57:45 +03:00
close ( tmpfd ) ;
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:42:39 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-16 04:37:07 +04:00
}
2007-08-16 21:42:34 +04:00
reply_openerror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 19:42:39 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
2002-12-04 02:57:45 +03:00
/* the returned filename is relative to the directory */
2009-07-11 01:50:37 +04:00
s = strrchr_m ( fsp - > fsp_name - > base_name , ' / ' ) ;
2005-07-08 08:51:27 +04:00
if ( ! s ) {
2009-07-11 01:50:37 +04:00
s = fsp - > fsp_name - > base_name ;
2005-07-08 08:51:27 +04:00
} else {
2002-12-04 02:57:45 +03:00
s + + ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2004-04-03 02:11:08 +04:00
#if 0
/* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
thing in the byte section . JRA */
2002-12-04 02:57:45 +03:00
SSVALS ( p , 0 , - 1 ) ; /* what is this? not in spec */
2004-04-03 02:11:08 +04:00
# endif
2007-08-14 19:42:39 +04:00
if ( message_push_string ( & req - > outbuf , s , STR_ASCII | STR_TERMINATE )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-14 19:42:39 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 19:42:39 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2008-10-19 17:30:12 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 19:42:39 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2009-07-11 01:50:37 +04:00
DEBUG ( 2 , ( " reply_ctemp: created temp file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
DEBUG ( 3 , ( " reply_ctemp %s fd=%d umode=0%o \n " , fsp_str_dbg ( fsp ) ,
2009-05-14 17:34:42 +04:00
fsp - > fh - > fd , ( unsigned int ) smb_fname - > st . st_ex_mode ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2002-03-23 05:57:44 +03:00
/*******************************************************************
Check if a user is allowed to rename a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-16 14:02:51 +04:00
static NTSTATUS can_rename ( connection_struct * conn , files_struct * fsp ,
2009-11-18 03:06:08 +03:00
uint16 dirtype )
2002-03-23 05:57:44 +03:00
{
2005-07-08 08:51:27 +04:00
uint32 fmode ;
2002-03-23 05:57:44 +03:00
2005-07-08 08:51:27 +04:00
if ( ! CAN_WRITE ( conn ) ) {
2002-03-23 05:57:44 +03:00
return NT_STATUS_MEDIA_WRITE_PROTECTED ;
2005-07-08 08:51:27 +04:00
}
2004-06-26 01:33:21 +04:00
2009-07-11 01:50:37 +04:00
fmode = dos_mode ( conn , fsp - > fsp_name ) ;
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
2009-11-18 03:06:08 +03:00
if ( S_ISDIR ( fsp - > fsp_name - > st . st_ex_mode ) ) {
2009-02-26 22:42:23 +03:00
if ( fsp - > posix_open ) {
return NT_STATUS_OK ;
}
/* If no pathnames are open below this
directory , allow the rename . */
if ( file_find_subpath ( fsp ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
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
2008-03-11 23:27:33 +03:00
if ( fsp - > access_mask & ( DELETE_ACCESS | FILE_WRITE_ATTRIBUTES ) ) {
2007-06-16 14:02:51 +04:00
return NT_STATUS_OK ;
2002-03-23 05:57:44 +03:00
}
2007-06-16 14:02:51 +04:00
return NT_STATUS_ACCESS_DENIED ;
2002-03-23 05:57:44 +03:00
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2007-06-13 13:55:13 +04:00
* unlink a file with all relevant access checks
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-17 06:19:17 +03:00
2007-09-13 01:48:20 +04:00
static NTSTATUS do_unlink ( connection_struct * conn ,
struct smb_request * req ,
2009-06-11 03:08:34 +04:00
struct smb_filename * smb_fname ,
2007-09-13 01:48:20 +04:00
uint32 dirtype )
1996-05-04 11:50:46 +04:00
{
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 ;
2009-10-09 02:36:36 +04:00
int ret ;
bool posix_paths = lp_posix_pathnames ( ) ;
1996-05-04 11:50:46 +04:00
2009-07-08 23:24:03 +04:00
DEBUG ( 10 , ( " do_unlink: %s, dirtype = %d \n " ,
smb_fname_str_dbg ( smb_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
2009-10-09 02:36:36 +04:00
if ( posix_paths ) {
ret = SMB_VFS_LSTAT ( conn , smb_fname ) ;
} else {
2010-03-11 01:06:18 +03:00
ret = SMB_VFS_STAT ( conn , smb_fname ) ;
2009-10-09 02:36:36 +04:00
}
if ( ret ! = 0 ) {
2009-06-23 02:26:56 +04:00
return map_nt_error_from_unix ( errno ) ;
}
2009-07-08 23:24:03 +04:00
fattr = dos_mode ( conn , smb_fname ) ;
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
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 . */
2008-11-20 05:03:27 +03:00
status = SMB_VFS_CREATE_FILE
2008-01-20 01:25:36 +03:00
( conn , /* conn */
req , /* req */
2008-11-20 05:03:27 +03:00
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-01-20 01:25:36 +03:00
DELETE_ACCESS , /* access_mask */
FILE_SHARE_NONE , /* share_access */
FILE_OPEN , /* create_disposition*/
FILE_NON_DIRECTORY_FILE , /* create_options */
2009-10-09 02:36:36 +04:00
/* file_attributes */
posix_paths ? FILE_FLAG_POSIX_SEMANTICS | 0777 :
FILE_ATTRIBUTE_NORMAL ,
2008-01-20 01:25:36 +03:00
0 , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-01-20 01:25:36 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2009-06-12 23:54:11 +04:00
NULL ) ; /* pinfo */
2007-01-02 18:07:27 +03:00
2007-06-13 13:55:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-11-20 05:03:27 +03:00
DEBUG ( 10 , ( " SMB_VFS_CREATEFILE failed: %s \n " ,
2007-06-13 13:55:13 +04:00
nt_errstr ( status ) ) ) ;
return status ;
2002-03-23 05:57:44 +03:00
}
2007-06-13 13:55:13 +04:00
2009-12-03 05:06:40 +03:00
status = can_set_delete_on_close ( fsp , fattr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " do_unlink can_set_delete_on_close for file %s - "
" (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) ,
nt_errstr ( status ) ) ) ;
close_file ( req , fsp , NORMAL_CLOSE ) ;
return status ;
}
2007-06-13 13:55:13 +04:00
/* The set is across all open files on this dev/inode pair. */
2008-06-19 20:21:41 +04:00
if ( ! set_delete_on_close ( fsp , True , & conn - > server_info - > utok ) ) {
2008-10-09 18:27:49 +04:00
close_file ( req , fsp , NORMAL_CLOSE ) ;
2007-06-13 13:55:13 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2008-10-09 18:27:49 +04:00
return close_file ( req , fsp , NORMAL_CLOSE ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2000-11-15 00:56:32 +03:00
The guts of the unlink command , split out so it may be called by the NT SMB
code .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-07-05 20:26:27 +04:00
NTSTATUS unlink_internals ( connection_struct * conn , struct smb_request * req ,
2009-07-25 05:38:40 +04:00
uint32 dirtype , struct smb_filename * smb_fname ,
bool has_wild )
1996-05-04 11:50:46 +04:00
{
2009-06-11 03:08:34 +04:00
char * fname_dir = NULL ;
char * fname_mask = NULL ;
2001-08-27 12:19:43 +04:00
int count = 0 ;
2007-01-13 02:47:16 +03:00
NTSTATUS status = NT_STATUS_OK ;
2007-09-13 01:48:20 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-09-08 00:57:01 +04:00
2009-06-11 03:08:34 +04:00
/* Split up the directory from the filename/mask. */
status = split_fname_dir_mask ( ctx , smb_fname - > base_name ,
& fname_dir , & fname_mask ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-11 03:08:34 +04:00
goto out ;
2001-08-27 12:19:43 +04:00
}
2007-09-08 00:57:01 +04:00
2001-08-27 12:19:43 +04:00
/*
* We should only check the mangled cache
* here if unix_convert failed . This means
* that the path in ' mask ' doesn ' t exist
* on the file system and so we need to look
* for a possible mangle . This patch from
* Tine Smukavec < valentin . smukavec @ hermes . si > .
*/
2007-09-08 00:57:01 +04:00
2009-06-11 03:08:34 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) & &
mangle_is_mangled ( fname_mask , conn - > params ) ) {
2007-09-08 00:57:01 +04:00
char * new_mask = NULL ;
2009-06-11 03:08:34 +04:00
mangle_lookup_name_from_8_3 ( ctx , fname_mask ,
& new_mask , conn - > params ) ;
2007-09-08 00:57:01 +04:00
if ( new_mask ) {
2009-06-11 03:08:34 +04:00
TALLOC_FREE ( fname_mask ) ;
fname_mask = new_mask ;
2007-09-08 00:57:01 +04:00
}
}
2001-08-27 12:19:43 +04:00
if ( ! has_wild ) {
2009-06-11 03:08:34 +04:00
/*
* Only one file needs to be unlinked . Append the mask back
* onto the directory .
*/
TALLOC_FREE ( smb_fname - > base_name ) ;
smb_fname - > base_name = talloc_asprintf ( smb_fname ,
" %s/%s " ,
fname_dir ,
fname_mask ) ;
if ( ! smb_fname - > base_name ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
2007-09-13 01:48:20 +04:00
}
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
2009-06-11 03:08:34 +04:00
status = check_name ( conn , smb_fname - > base_name ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-11 03:08:34 +04:00
goto out ;
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
}
2009-06-11 03:08:34 +04:00
status = do_unlink ( conn , req , smb_fname , dirtype ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-11 03:08:34 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
2001-09-21 18:27:43 +04:00
2007-06-13 13:55:13 +04:00
count + + ;
2001-08-27 12:19:43 +04:00
} else {
2005-02-01 03:28:20 +03:00
struct smb_Dir * dir_hnd = NULL ;
2007-01-17 05:09:37 +03:00
long offset = 0 ;
2009-11-16 11:49:23 +03:00
const char * dname = NULL ;
char * talloced = NULL ;
2007-09-08 00:57:01 +04:00
2007-01-13 02:47:16 +03:00
if ( ( dirtype & SAMBA_ATTRIBUTES_MASK ) = = aDIR ) {
2009-06-11 03:08:34 +04:00
status = NT_STATUS_OBJECT_NAME_INVALID ;
goto out ;
2007-01-09 21:48:38 +03:00
}
2009-06-11 03:08:34 +04:00
if ( strequal ( fname_mask , " ????????.??? " ) ) {
TALLOC_FREE ( fname_mask ) ;
fname_mask = talloc_strdup ( ctx , " * " ) ;
if ( ! fname_mask ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2007-01-17 05:09:37 +03:00
}
2009-06-11 03:08:34 +04:00
status = check_name ( conn , fname_dir ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-11 03:08:34 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
2005-06-25 07:03:44 +04:00
2009-06-11 03:08:34 +04:00
dir_hnd = OpenDir ( talloc_tos ( ) , conn , fname_dir , fname_mask ,
2008-01-12 19:08:04 +03:00
dirtype ) ;
2007-01-17 05:09:37 +03:00
if ( dir_hnd = = NULL ) {
2009-06-11 03:08:34 +04:00
status = map_nt_error_from_unix ( errno ) ;
goto out ;
2007-01-17 05:09:37 +03:00
}
2007-09-13 01:48:20 +04:00
2001-08-27 12:19:43 +04:00
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
the pattern matches against the long name , otherwise the short name
We don ' t implement this yet XXXX
*/
2007-09-13 01:48:20 +04:00
2007-01-17 05:09:37 +03:00
status = NT_STATUS_NO_SUCH_FILE ;
2007-01-09 18:50:40 +03:00
2009-06-11 03:08:34 +04:00
while ( ( dname = ReadDirName ( dir_hnd , & offset ,
2009-11-16 11:49:23 +03:00
& smb_fname - > st , & talloced ) ) ) {
2009-07-14 20:34:36 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-06-11 03:08:34 +04:00
if ( ! is_visible_file ( conn , fname_dir , dname ,
& smb_fname - > st , true ) ) {
2009-07-14 20:34:36 +04:00
TALLOC_FREE ( frame ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-01-17 05:09:37 +03:00
continue ;
}
2007-01-09 12:03:33 +03:00
2007-01-17 05:09:37 +03:00
/* Quick check for "." and ".." */
2007-09-13 01:48:20 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
2009-07-14 20:34:36 +04:00
TALLOC_FREE ( frame ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-09-13 01:48:20 +04:00
continue ;
2007-01-17 05:09:37 +03:00
}
2004-02-24 04:46:24 +03:00
2009-11-23 18:34:07 +03:00
if ( ! mask_match ( dname , fname_mask ,
2009-06-11 03:08:34 +04:00
conn - > case_sensitive ) ) {
2009-07-14 20:34:36 +04:00
TALLOC_FREE ( frame ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-01-17 05:09:37 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
2009-06-11 03:08:34 +04:00
TALLOC_FREE ( smb_fname - > base_name ) ;
smb_fname - > base_name =
talloc_asprintf ( smb_fname , " %s/%s " ,
fname_dir , dname ) ;
if ( ! smb_fname - > base_name ) {
TALLOC_FREE ( dir_hnd ) ;
status = NT_STATUS_NO_MEMORY ;
2009-07-14 20:34:36 +04:00
TALLOC_FREE ( frame ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2009-06-11 03:08:34 +04:00
goto out ;
2007-09-13 01:48:20 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
2009-06-11 03:08:34 +04:00
status = check_name ( conn , smb_fname - > base_name ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2009-07-14 20:34:36 +04:00
TALLOC_FREE ( frame ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2009-06-11 03:08:34 +04:00
goto out ;
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
}
2009-06-11 03:08:34 +04:00
status = do_unlink ( conn , req , smb_fname , dirtype ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-07-14 20:34:36 +04:00
TALLOC_FREE ( frame ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-01-17 05:09:37 +03:00
continue ;
2001-08-27 12:19:43 +04:00
}
2007-06-13 13:55:13 +04:00
count + + ;
2008-02-08 11:28:57 +03:00
DEBUG ( 3 , ( " unlink_internals: successful unlink [%s] \n " ,
2009-06-11 03:08:34 +04:00
smb_fname - > base_name ) ) ;
2009-07-14 20:34:36 +04:00
TALLOC_FREE ( frame ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2001-08-27 12:19:43 +04:00
}
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2001-08-27 12:19:43 +04:00
}
2007-09-13 01:48:20 +04:00
2008-08-10 04:43:36 +04:00
if ( count = = 0 & & NT_STATUS_IS_OK ( status ) & & errno ! = 0 ) {
2007-01-13 02:47:16 +03:00
status = map_nt_error_from_unix ( errno ) ;
2001-08-27 12:19:43 +04:00
}
2001-09-04 11:13:01 +04:00
2009-06-11 03:08:34 +04:00
out :
TALLOC_FREE ( fname_dir ) ;
TALLOC_FREE ( fname_mask ) ;
2007-01-13 02:47:16 +03:00
return status ;
2000-11-15 00:56:32 +03:00
}
/****************************************************************************
Reply to a unlink
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_unlink ( struct smb_request * req )
2000-11-15 00:56:32 +03:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-09-11 22:31:29 +04:00
char * name = NULL ;
2009-07-25 05:38:40 +04:00
struct smb_filename * smb_fname = NULL ;
2005-06-25 07:03:44 +04:00
uint32 dirtype ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2007-10-19 04:40:25 +04:00
bool path_contains_wcard = False ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-10-31 23:11:58 +03:00
2005-11-02 02:49:40 +03:00
START_PROFILE ( SMBunlink ) ;
2007-07-31 11:57:33 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2007-07-31 11:57:33 +04:00
}
2007-07-05 20:26:27 +04:00
2008-11-02 14:20:47 +03:00
dirtype = SVAL ( req - > vwv + 0 , 0 ) ;
2007-09-11 22:31:29 +04:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req_wcard ( ctx , req , & name , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ,
& path_contains_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2007-03-12 20:55:24 +03:00
2009-07-25 05:38:40 +04:00
status = filename_convert ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
name ,
UCF_COND_ALLOW_WCARD_LCOMP ,
& path_contains_wcard ,
& smb_fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-31 11:57:33 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2009-07-25 05:38:40 +04:00
DEBUG ( 3 , ( " reply_unlink : %s \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
2007-09-11 22:31:29 +04:00
2009-07-25 05:38:40 +04:00
status = unlink_internals ( conn , req , dirtype , smb_fname ,
2007-07-05 20:26:27 +04:00
path_contains_wcard ) ;
2004-06-08 20:14:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 11:57:33 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-07-25 05:38:40 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2001-09-04 11:13:01 +04:00
2007-07-31 11:57:33 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2009-07-25 05:38:40 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlink ) ;
2007-07-31 11:57:33 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2001-09-04 23:10:30 +04:00
/****************************************************************************
Fail for readbraw .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-11-25 01:05:59 +03:00
static void fail_readraw ( void )
2001-09-04 23:10:30 +04:00
{
2007-09-13 01:48:20 +04:00
const char * errstr = talloc_asprintf ( talloc_tos ( ) ,
" FAIL ! reply_readbraw: socket write fail (%s) " ,
strerror ( errno ) ) ;
if ( ! errstr ) {
errstr = " " ;
}
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( errstr ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2004-11-25 01:05:59 +03:00
/****************************************************************************
Fake ( read / write ) sendfile . Returns - 1 on read or write fail .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-12 15:22:26 +04:00
static ssize_t fake_sendfile ( files_struct * fsp , SMB_OFF_T startpos ,
size_t nread )
2004-11-25 01:05:59 +03:00
{
2007-08-12 15:22:26 +04:00
size_t bufsize ;
2007-05-16 04:07:38 +04:00
size_t tosend = nread ;
2007-08-12 15:22:26 +04:00
char * buf ;
if ( nread = = 0 ) {
return 0 ;
}
bufsize = MIN ( nread , 65536 ) ;
if ( ! ( buf = SMB_MALLOC_ARRAY ( char , bufsize ) ) ) {
return - 1 ;
}
2004-11-25 01:05:59 +03:00
2007-05-16 04:07:38 +04:00
while ( tosend > 0 ) {
ssize_t ret ;
size_t cur_read ;
2004-11-25 01:05:59 +03:00
2007-05-16 04:07:38 +04:00
if ( tosend > bufsize ) {
cur_read = bufsize ;
} else {
cur_read = tosend ;
}
ret = read_file ( fsp , buf , startpos , cur_read ) ;
2004-11-25 01:05:59 +03:00
if ( ret = = - 1 ) {
2007-08-12 15:22:26 +04:00
SAFE_FREE ( buf ) ;
2004-11-25 01:05:59 +03:00
return - 1 ;
}
2007-05-16 04:07:38 +04:00
/* If we had a short read, fill with zeros. */
if ( ret < cur_read ) {
2009-05-19 05:20:18 +04:00
memset ( buf + ret , ' \0 ' , cur_read - ret ) ;
2007-05-16 04:07:38 +04:00
}
2004-11-25 01:05:59 +03:00
2007-05-16 04:07:38 +04:00
if ( write_data ( smbd_server_fd ( ) , buf , cur_read ) ! = cur_read ) {
2007-08-12 15:22:26 +04:00
SAFE_FREE ( buf ) ;
2007-05-16 04:07:38 +04:00
return - 1 ;
}
tosend - = cur_read ;
startpos + = cur_read ;
}
2004-11-25 01:05:59 +03:00
2007-08-12 15:22:26 +04:00
SAFE_FREE ( buf ) ;
2004-11-25 01:05:59 +03:00
return ( ssize_t ) nread ;
}
2009-03-27 12:24:18 +03:00
# if defined(WITH_SENDFILE)
2009-01-14 00:02:44 +03:00
/****************************************************************************
Deal with the case of sendfile reading less bytes from the file than
requested . Fill with zeros ( all we can do ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void sendfile_short_send ( files_struct * fsp ,
ssize_t nread ,
size_t headersize ,
size_t smb_maxcnt )
{
2009-05-19 05:20:18 +04:00
# define SHORT_SEND_BUFSIZE 1024
2009-01-14 00:02:44 +03:00
if ( nread < headersize ) {
DEBUG ( 0 , ( " sendfile_short_send: sendfile failed to send "
" header for file %s (%s). Terminating \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , strerror ( errno ) ) ) ;
2009-01-14 00:02:44 +03:00
exit_server_cleanly ( " sendfile_short_send failed " ) ;
}
nread - = headersize ;
if ( nread < smb_maxcnt ) {
2009-05-19 05:20:18 +04:00
char * buf = SMB_CALLOC_ARRAY ( char , SHORT_SEND_BUFSIZE ) ;
2009-01-14 00:02:44 +03:00
if ( ! buf ) {
exit_server_cleanly ( " sendfile_short_send: "
" malloc failed " ) ;
}
DEBUG ( 0 , ( " sendfile_short_send: filling truncated file %s "
2009-07-11 01:50:37 +04:00
" with zeros ! \n " , fsp_str_dbg ( fsp ) ) ) ;
2009-01-14 00:02:44 +03:00
while ( nread < smb_maxcnt ) {
/*
* We asked for the real file size and told sendfile
* to not go beyond the end of the file . But it can
* happen that in between our fstat call and the
* sendfile call the file was truncated . This is very
* bad because we have already announced the larger
* number of bytes to the client .
*
* The best we can do now is to send 0 - bytes , just as
* a read from a hole in a sparse file would do .
*
* This should happen rarely enough that I don ' t care
* about efficiency here : - )
*/
size_t to_write ;
2009-05-19 05:20:18 +04:00
to_write = MIN ( SHORT_SEND_BUFSIZE , smb_maxcnt - nread ) ;
2009-01-14 00:02:44 +03:00
if ( write_data ( smbd_server_fd ( ) , buf , to_write ) ! = to_write ) {
exit_server_cleanly ( " sendfile_short_send: "
" write_data failed " ) ;
}
nread + = to_write ;
}
SAFE_FREE ( buf ) ;
}
}
2009-03-27 12:24:18 +03:00
# endif /* defined WITH_SENDFILE */
2009-01-14 00:02:44 +03:00
2007-08-14 05:45:26 +04:00
/****************************************************************************
Return a readbraw error ( 4 bytes of zero ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void reply_readbraw_error ( void )
{
char header [ 4 ] ;
2010-03-19 14:04:32 +03:00
2007-08-14 05:45:26 +04:00
SIVAL ( header , 0 , 0 ) ;
2010-03-19 14:04:32 +03:00
2010-04-01 04:40:30 +04:00
smbd_lock_socket ( smbd_server_conn ) ;
2007-08-14 05:45:26 +04:00
if ( write_data ( smbd_server_fd ( ) , header , 4 ) ! = 4 ) {
fail_readraw ( ) ;
}
2010-04-01 04:40:30 +04:00
smbd_unlock_socket ( smbd_server_conn ) ;
2007-08-14 05:45:26 +04:00
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Use sendfile in readbraw .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-01-31 01:45:35 +03:00
static void send_file_readbraw ( connection_struct * conn ,
struct smb_request * req ,
files_struct * fsp ,
SMB_OFF_T startpos ,
size_t nread ,
ssize_t mincount )
2002-09-25 19:19:00 +04:00
{
2007-08-14 05:45:26 +04:00
char * outbuf = NULL ;
2002-09-25 19:19:00 +04:00
ssize_t ret = 0 ;
# if defined(WITH_SENDFILE)
/*
2004-07-01 03:00:40 +04:00
* We can only use sendfile on a non - chained packet
* but we can use on a non - oplocked file . tridge proved this
* on a train in Germany : - ) . JRA .
* reply_readbraw has already checked the length .
2002-09-25 19:19:00 +04:00
*/
2009-01-31 01:44:21 +03:00
if ( ! req_is_in_chain ( req ) & & ( nread > 0 ) & & ( fsp - > base_fsp = = NULL ) & &
2009-03-09 11:47:59 +03:00
( fsp - > wcp = = NULL ) & &
2010-06-12 13:42:40 +04:00
lp_use_sendfile ( SNUM ( conn ) , req - > sconn - > smb1 . signing_state ) ) {
2009-01-14 00:02:44 +03:00
ssize_t sendfile_read = - 1 ;
2007-08-14 05:45:26 +04:00
char header [ 4 ] ;
DATA_BLOB header_blob ;
_smb_setlen ( header , nread ) ;
2007-08-14 10:18:55 +04:00
header_blob = data_blob_const ( header , 4 ) ;
2007-08-14 05:45:26 +04:00
2009-01-14 00:02:44 +03:00
if ( ( sendfile_read = SMB_VFS_SENDFILE ( smbd_server_fd ( ) , fsp ,
& header_blob , startpos , nread ) ) = = - 1 ) {
2007-08-14 05:45:26 +04:00
/* Returning ENOSYS means no data at all was sent.
* Do this as a normal read . */
2004-12-21 01:01:42 +03:00
if ( errno = = ENOSYS ) {
goto normal_readbraw ;
}
2002-09-25 19:19:00 +04:00
/*
2004-11-25 01:05:59 +03:00
* Special hack for broken Linux with no working sendfile . If we
* return EINTR we sent the header but not the rest of the data .
* Fake this up by doing read / write calls .
2002-09-25 19:19:00 +04:00
*/
2004-11-25 01:05:59 +03:00
if ( errno = = EINTR ) {
/* Ensure we don't do this again. */
2004-08-06 21:49:00 +04:00
set_use_sendfile ( SNUM ( conn ) , False ) ;
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readbraw: sendfile not available. Faking.. \n " ) ) ;
2007-08-12 15:22:26 +04:00
if ( fake_sendfile ( fsp , startpos , nread ) = = - 1 ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readbraw: "
" fake_sendfile failed for "
" file %s (%s). \n " ,
fsp_str_dbg ( fsp ) ,
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
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readbraw: sendfile failed for "
" file %s (%s). Terminating \n " ,
fsp_str_dbg ( fsp ) , strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readbraw sendfile failed " ) ;
2009-02-21 00:28:36 +03:00
} else if ( sendfile_read = = 0 ) {
/*
* Some sendfile implementations return 0 to indicate
* that there was a short read , but nothing was
* actually written to the socket . In this case ,
* fallback to the normal read path so the header gets
* the correct byte count .
*/
DEBUG ( 3 , ( " send_file_readbraw: sendfile sent zero "
" bytes falling back to the normal read: "
2009-07-11 01:50:37 +04:00
" %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2009-02-21 00:28:36 +03:00
goto normal_readbraw ;
2002-09-25 19:19:00 +04:00
}
2009-01-14 00:02:44 +03:00
/* Deal with possible short send. */
2009-01-14 02:36:09 +03:00
if ( sendfile_read ! = 4 + nread ) {
sendfile_short_send ( fsp , sendfile_read , 4 , nread ) ;
}
2007-05-09 04:52:46 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2007-06-01 23:34:08 +04:00
normal_readbraw :
2009-02-25 20:59:53 +03:00
# endif
2007-06-01 23:34:08 +04:00
2007-08-14 05:45:26 +04:00
outbuf = TALLOC_ARRAY ( NULL , char , nread + 4 ) ;
if ( ! outbuf ) {
DEBUG ( 0 , ( " send_file_readbraw: TALLOC_ARRAY failed for size %u. \n " ,
2007-08-14 12:29:36 +04:00
( unsigned ) ( nread + 4 ) ) ) ;
2007-08-14 05:45:26 +04:00
reply_readbraw_error ( ) ;
return ;
}
2002-09-25 19:19:00 +04:00
if ( nread > 0 ) {
ret = read_file ( fsp , outbuf + 4 , startpos , nread ) ;
2003-10-09 05:46:01 +04:00
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2002-09-25 19:19:00 +04:00
if ( ret < mincount )
ret = 0 ;
2003-10-09 05:46:01 +04:00
# else
if ( ret < nread )
ret = 0 ;
# endif
2002-09-25 19:19:00 +04:00
}
_smb_setlen ( outbuf , ret ) ;
if ( write_data ( smbd_server_fd ( ) , outbuf , 4 + ret ) ! = 4 + ret )
fail_readraw ( ) ;
2007-08-14 05:45:26 +04:00
TALLOC_FREE ( outbuf ) ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-09-04 23:10:30 +04:00
Reply to a readbraw ( core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_readbraw ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2010-06-12 13:43:53 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2001-11-14 05:35:56 +03:00
ssize_t maxcount , mincount ;
2001-09-04 23:10:30 +04:00
size_t nread = 0 ;
SMB_OFF_T startpos ;
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-08-14 05:45:26 +04:00
SMB_OFF_T size = 0 ;
2001-09-04 23:10:30 +04:00
START_PROFILE ( SMBreadbraw ) ;
1996-05-04 11:50:46 +04:00
2010-06-12 13:43:53 +04:00
if ( srv_is_signing_active ( sconn ) | |
2009-03-09 11:47:59 +03:00
is_encrypted_packet ( req - > inbuf ) ) {
2007-12-27 04:12:36 +03:00
exit_server_cleanly ( " reply_readbraw: SMB signing/sealing is active - "
2007-08-14 05:45:26 +04:00
" raw reads/writes are disallowed. " ) ;
}
if ( req - > wct < 8 ) {
reply_readbraw_error ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ;
2003-07-17 04:53:37 +04:00
}
2010-06-12 13:43:53 +04:00
if ( sconn - > smb1 . echo_handler . trusted_fde ) {
2010-05-26 19:52:10 +04:00
DEBUG ( 2 , ( " SMBreadbraw rejected with NOT_SUPPORTED because of "
" 'async smb echo handler = yes' \n " ) ) ;
2010-03-22 11:11:05 +03:00
reply_readbraw_error ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ;
}
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
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
1996-05-04 11:50:46 +04:00
2007-08-25 23:47:57 +04:00
/*
2007-08-14 05:45:26 +04:00
* We have to do a check_fsp by hand here , as
* we must always return 4 zero bytes on error ,
* not a NTSTATUS .
*/
if ( ! fsp | | ! conn | | conn ! = fsp - > conn | |
2008-06-19 20:21:41 +04:00
req - > vuid ! = fsp - > vuid | |
2007-08-14 05:45:26 +04:00
fsp - > is_directory | | fsp - > fh - > fd = = - 1 ) {
2001-09-04 23:10:30 +04:00
/*
* fsp could be NULL here so use the value from the packet . JRA .
*/
2007-08-14 05:45:26 +04:00
DEBUG ( 3 , ( " reply_readbraw: fnum %d not valid "
" - cache prime? \n " ,
2008-11-02 14:20:47 +03:00
( int ) SVAL ( req - > vwv + 0 , 0 ) ) ) ;
2007-08-14 05:45:26 +04:00
reply_readbraw_error ( ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
1999-12-13 16:27:58 +03:00
2007-08-14 05:45:26 +04:00
/* Do a "by hand" version of CHECK_READ. */
if ( ! ( fsp - > can_read | |
( ( req - > flags2 & FLAGS2_READ_PERMIT_EXECUTE ) & &
( fsp - > access_mask & FILE_EXECUTE ) ) ) ) {
DEBUG ( 3 , ( " reply_readbraw: fnum %d not readable. \n " ,
2008-11-02 14:20:47 +03:00
( int ) SVAL ( req - > vwv + 0 , 0 ) ) ) ;
2007-08-14 05:45:26 +04:00
reply_readbraw_error ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ;
}
1999-12-13 16:27:58 +03:00
2001-09-04 23:10:30 +04:00
flush_write_cache ( fsp , READRAW_FLUSH ) ;
1999-12-13 16:27:58 +03:00
2008-11-02 14:20:47 +03:00
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 1 , 0 ) ;
2007-08-14 10:18:55 +04:00
if ( req - > wct = = 10 ) {
2001-09-04 23:10:30 +04:00
/*
* This is a large offset ( 64 bit ) read .
*/
1999-12-13 16:27:58 +03:00
# ifdef LARGE_SMB_OFF_T
2008-11-02 14:20:47 +03:00
startpos | = ( ( ( SMB_OFF_T ) IVAL ( req - > vwv + 8 , 0 ) ) < < 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
2008-11-02 14:20:47 +03:00
if ( IVAL ( req - > vwv + 8 , 0 ) ! = 0 ) {
2007-08-14 05:45:26 +04:00
DEBUG ( 0 , ( " reply_readbraw: large offset "
" (%x << 32) used and we don't support "
" 64 bit offsets. \n " ,
2008-11-02 14:20:47 +03:00
( unsigned int ) IVAL ( req - > vwv + 8 , 0 ) ) ) ;
2007-08-14 05:45:26 +04:00
reply_readbraw_error ( ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
1999-12-13 16:27:58 +03:00
# endif /* LARGE_SMB_OFF_T */
2001-09-04 23:10:30 +04:00
if ( startpos < 0 ) {
2007-08-14 05:45:26 +04:00
DEBUG ( 0 , ( " reply_readbraw: negative 64 bit "
" readraw offset (%.0f) ! \n " ,
( double ) startpos ) ) ;
reply_readbraw_error ( ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2009-11-18 03:06:08 +03:00
}
2001-09-04 23:10:30 +04:00
}
2007-08-14 05:45:26 +04:00
2008-11-02 14:20:47 +03:00
maxcount = ( SVAL ( req - > vwv + 3 , 0 ) & 0xFFFF ) ;
mincount = ( SVAL ( req - > vwv + 4 , 0 ) & 0xFFFF ) ;
2001-09-04 23:10:30 +04:00
/* ensure we don't overrun the packet size */
maxcount = MIN ( 65535 , maxcount ) ;
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2009-03-14 00:15:28 +03:00
( uint64_t ) startpos , ( uint64_t ) maxcount , READ_LOCK ,
& lock ) ;
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
2007-08-14 05:45:26 +04:00
reply_readbraw_error ( ) ;
END_PROFILE ( SMBreadbraw ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2009-11-18 03:06:08 +03:00
if ( fsp_stat ( fsp ) = = 0 ) {
size = fsp - > fsp_name - > st . st_ex_size ;
2007-08-14 05:45:26 +04:00
}
if ( startpos > = size ) {
nread = 0 ;
} else {
2007-08-25 23:47:57 +04:00
nread = MIN ( maxcount , ( size - startpos ) ) ;
2001-09-04 23:10:30 +04:00
}
1998-07-31 01:18:57 +04:00
2003-10-09 05:46:01 +04:00
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2001-09-04 23:10:30 +04:00
if ( nread < mincount )
nread = 0 ;
2003-10-09 05:46:01 +04:00
# endif
2008-10-19 17:30:12 +04:00
2007-08-14 05:45:26 +04:00
DEBUG ( 3 , ( " reply_readbraw: fnum=%d start=%.0f max=%lu "
" min=%lu nread=%lu \n " ,
fsp - > fnum , ( double ) startpos ,
( unsigned long ) maxcount ,
( unsigned long ) mincount ,
( unsigned long ) nread ) ) ;
2008-10-19 17:30:12 +04:00
2009-01-31 01:44:21 +03:00
send_file_readbraw ( conn , req , fsp , startpos , nread , mincount ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 05:45:26 +04:00
DEBUG ( 5 , ( " reply_readbraw finished \n " ) ) ;
2009-03-14 00:15:28 +03:00
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2009-03-14 00:15:28 +03:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lockread ( core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_lockread ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2001-08-27 12:19:43 +04:00
ssize_t nread = - 1 ;
char * data ;
SMB_OFF_T startpos ;
size_t numtoread ;
NTSTATUS status ;
2007-08-15 00:20:51 +04:00
files_struct * fsp ;
2006-07-18 05:05:51 +04:00
struct byte_range_lock * br_lck = NULL ;
2007-09-08 00:57:01 +04:00
char * p = NULL ;
2010-06-12 13:44:14 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2007-08-15 00:20:51 +04:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBlockread ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:20:51 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockread ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-15 00:20:51 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBlockread ) ;
return ;
}
2008-11-06 22:16:04 +03:00
if ( ! CHECK_READ ( fsp , req ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBlockread ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
numtoread = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2007-08-15 00:20:51 +04:00
numtoread = MIN ( BUFFER_SIZE - ( smb_size + 3 * 2 + 3 ) , numtoread ) ;
reply_outbuf ( req , 5 , numtoread + 3 ) ;
data = smb_buf ( req - > outbuf ) + 3 ;
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/*
* NB . Discovered by Menny Hamburger at Mainsoft . This is a core +
* protocol request that predates the read / write lock concept .
* Thus instead of asking for a read lock here we need to ask
* for a write lock . JRA .
2003-10-09 05:46:01 +04:00
* Note that the requested lock size is unaffected by max_recv .
2001-08-27 12:19:43 +04:00
*/
2008-10-19 17:30:12 +04:00
2007-05-14 17:01:28 +04:00
br_lck = do_lock ( smbd_messaging_context ( ) ,
fsp ,
2010-05-07 17:20:50 +04:00
( uint64_t ) req - > smbpid ,
2008-10-14 03:59:36 +04:00
( uint64_t ) numtoread ,
( uint64_t ) startpos ,
2006-07-18 01:09:02 +04:00
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 ,
2009-02-10 08:51:29 +03:00
NULL ,
2007-05-20 00:57:12 +04:00
NULL ) ;
2006-07-18 05:05:51 +04:00
TALLOC_FREE ( br_lck ) ;
1999-12-13 16:27:58 +03:00
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
1998-08-01 02:39:15 +04:00
2003-10-09 05:46:01 +04:00
/*
* However the requested READ size IS affected by max_recv . Insanity . . . . JRA .
*/
2009-05-26 16:56:08 +04:00
if ( numtoread > sconn - > smb1 . negprot . max_recv ) {
2003-10-09 23:01:31 +04:00
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 " ,
2009-05-26 16:56:08 +04:00
( unsigned int ) numtoread ,
( unsigned int ) sconn - > smb1 . negprot . max_recv ) ) ;
numtoread = MIN ( numtoread , sconn - > smb1 . negprot . max_recv ) ;
2003-10-09 23:01:31 +04:00
}
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 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
2008-10-19 17:30:12 +04:00
2008-01-04 23:56:23 +03:00
srv_set_message ( ( char * ) req - > outbuf , 5 , nread + 3 , False ) ;
2007-08-15 00:20:51 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nread ) ;
SSVAL ( req - > outbuf , smb_vwv5 , nread + 3 ) ;
2007-09-08 00:57:01 +04:00
p = smb_buf ( req - > outbuf ) ;
SCVAL ( p , 0 , 0 ) ; /* pad byte. */
SSVAL ( p , 1 , nread ) ;
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " lockread fnum=%d num=%d nread=%d \n " ,
fsp - > fnum , ( int ) numtoread , ( int ) nread ) ) ;
1998-08-01 02:39:15 +04:00
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a read .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_read ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-09-25 19:19:00 +04:00
size_t numtoread ;
ssize_t nread = 0 ;
char * data ;
SMB_OFF_T startpos ;
int outsize = 0 ;
2007-08-14 22:33:29 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2010-06-12 13:44:41 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2007-08-14 22:33:29 +04:00
2002-09-25 19:19:00 +04:00
START_PROFILE ( SMBread ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:33:29 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBread ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2001-08-27 12:19:43 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 22:33:29 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 22:33:29 +04:00
END_PROFILE ( SMBread ) ;
return ;
}
2008-11-06 22:16:04 +03:00
if ( ! CHECK_READ ( fsp , req ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-14 22:33:29 +04:00
END_PROFILE ( SMBread ) ;
return ;
}
2008-11-02 14:20:47 +03:00
numtoread = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2001-08-27 12:19:43 +04:00
2002-09-25 19:19:00 +04:00
numtoread = MIN ( BUFFER_SIZE - outsize , numtoread ) ;
2007-08-14 22:33:29 +04:00
2003-10-09 05:46:01 +04:00
/*
* The requested read size cannot be greater than max_recv . JRA .
*/
2009-05-26 16:56:08 +04:00
if ( numtoread > sconn - > smb1 . negprot . max_recv ) {
2003-10-09 23:01:31 +04:00
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 " ,
2009-05-26 16:56:08 +04:00
( unsigned int ) numtoread ,
( unsigned int ) sconn - > smb1 . negprot . max_recv ) ) ;
numtoread = MIN ( numtoread , sconn - > smb1 . negprot . max_recv ) ;
2003-10-09 23:01:31 +04:00
}
2003-10-09 05:46:01 +04:00
2007-08-14 22:33:29 +04:00
reply_outbuf ( req , 5 , numtoread + 3 ) ;
data = smb_buf ( req - > outbuf ) + 3 ;
2008-10-19 17:30:12 +04:00
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2009-03-14 00:15:28 +03:00
( uint64_t ) startpos , ( uint64_t ) numtoread , READ_LOCK ,
& lock ) ;
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
2007-08-14 22:33:29 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
if ( numtoread > 0 )
nread = read_file ( fsp , data , startpos , numtoread ) ;
2001-08-27 12:19:43 +04:00
2002-09-25 19:19:00 +04:00
if ( nread < 0 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2002-09-25 19:19:00 +04:00
}
2007-08-14 22:33:29 +04:00
2008-01-04 23:56:23 +03:00
srv_set_message ( ( char * ) req - > outbuf , 5 , nread + 3 , False ) ;
2007-08-14 22:33:29 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nread ) ;
SSVAL ( req - > outbuf , smb_vwv5 , nread + 3 ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , nread ) ;
2008-10-19 17:30:12 +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
2009-03-14 00:15:28 +03:00
strict_unlock :
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
2007-08-14 22:33:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2007-05-16 04:07:38 +04:00
/****************************************************************************
Setup readX header .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-11-22 01:17:31 +03:00
static int setup_readX_header ( struct smb_request * req , char * outbuf ,
size_t smb_maxcnt )
2007-05-16 04:07:38 +04:00
{
int outsize ;
2007-08-12 15:40:27 +04:00
char * data ;
2008-01-04 23:56:23 +03:00
outsize = srv_set_message ( outbuf , 12 , smb_maxcnt , False ) ;
2007-08-12 15:40:27 +04:00
data = smb_buf ( outbuf ) ;
2007-05-16 04:07:38 +04:00
2007-09-13 01:48:20 +04:00
memset ( outbuf + smb_vwv0 , ' \0 ' , 24 ) ; /* valgrind init. */
SCVAL ( outbuf , smb_vwv0 , 0xFF ) ;
2007-05-16 04:07:38 +04:00
SSVAL ( outbuf , smb_vwv2 , 0xFFFF ) ; /* Remaining - must be -1. */
SSVAL ( outbuf , smb_vwv5 , smb_maxcnt ) ;
2008-11-22 01:17:31 +03:00
SSVAL ( outbuf , smb_vwv6 ,
req_wct_ofs ( req )
+ 1 /* the wct field */
+ 12 * sizeof ( uint16_t ) /* vwv */
+ 2 ) ; /* the buflen field */
2007-05-16 04:07:38 +04:00
SSVAL ( outbuf , smb_vwv7 , ( smb_maxcnt > > 16 ) ) ;
2008-11-22 01:17:31 +03:00
SSVAL ( outbuf , smb_vwv11 , smb_maxcnt ) ;
2007-05-16 04:07:38 +04:00
/* Reset the outgoing length, set_message truncates at 0x1FFFF. */
_smb_setlen_large ( outbuf , ( smb_size + 12 * 2 + smb_maxcnt - 4 ) ) ;
return outsize ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Reply to a read and X - possibly using sendfile .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-12 13:16:54 +04:00
static void send_file_readX ( connection_struct * conn , struct smb_request * req ,
files_struct * fsp , SMB_OFF_T startpos ,
size_t smb_maxcnt )
2002-09-25 19:19:00 +04:00
{
ssize_t nread = - 1 ;
2009-05-13 03:32:32 +04:00
struct lock_struct lock ;
2009-07-11 05:23:00 +04:00
int saved_errno = 0 ;
2007-08-12 13:16:54 +04:00
2009-11-18 03:06:08 +03:00
if ( fsp_stat ( fsp ) = = - 1 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2007-08-12 13:16:54 +04:00
return ;
2007-05-16 04:07:38 +04:00
}
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2009-05-13 03:32:32 +04:00
( uint64_t ) startpos , ( uint64_t ) smb_maxcnt , READ_LOCK ,
& lock ) ;
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2009-05-13 03:32:32 +04:00
return ;
}
2009-11-18 03:06:08 +03:00
if ( ! S_ISREG ( fsp - > fsp_name - > st . st_ex_mode ) | |
( startpos > fsp - > fsp_name - > st . st_ex_size )
| | ( smb_maxcnt > ( fsp - > fsp_name - > st . st_ex_size - startpos ) ) ) {
2009-05-02 13:31:37 +04:00
/*
* We already know that we would do a short read , so don ' t
* try the sendfile ( ) path .
*/
goto nosendfile_read ;
2007-05-16 04:07:38 +04:00
}
2002-09-25 19:19:00 +04:00
# if defined(WITH_SENDFILE)
/*
2007-09-13 01:48:20 +04:00
* We can only use sendfile on a non - chained packet
2004-07-01 03:00:40 +04:00
* but we can use on a non - oplocked file . tridge proved this
* on a train in Germany : - ) . JRA .
2002-09-25 19:19:00 +04:00
*/
2009-01-31 01:44:21 +03:00
if ( ! req_is_in_chain ( req ) & &
2008-03-29 03:31:06 +03:00
! is_encrypted_packet ( req - > inbuf ) & & ( fsp - > base_fsp = = NULL ) & &
2009-03-09 11:47:59 +03:00
( fsp - > wcp = = NULL ) & &
2010-06-12 13:45:24 +04:00
lp_use_sendfile ( SNUM ( conn ) , req - > sconn - > smb1 . signing_state ) ) {
2007-08-12 16:57:56 +04:00
uint8 headerbuf [ smb_size + 12 * 2 ] ;
2002-09-25 19:19:00 +04:00
DATA_BLOB header ;
2007-09-13 01:48:20 +04:00
/*
2002-09-25 19:19:00 +04:00
* Set up the packet header before send . We
* assume here the sendfile will work ( get the
* correct amount of data ) .
*/
2007-08-12 15:40:27 +04:00
header = data_blob_const ( headerbuf , sizeof ( headerbuf ) ) ;
2008-11-03 22:16:09 +03:00
construct_reply_common_req ( req , ( char * ) headerbuf ) ;
2008-11-22 01:17:31 +03:00
setup_readX_header ( req , ( char * ) headerbuf , smb_maxcnt ) ;
2002-09-25 19:19:00 +04:00
2008-01-11 02:51:19 +03:00
if ( ( nread = SMB_VFS_SENDFILE ( smbd_server_fd ( ) , fsp , & header , startpos , smb_maxcnt ) ) = = - 1 ) {
2009-01-13 22:19:11 +03:00
/* Returning ENOSYS means no data at all was sent.
2008-08-26 08:06:42 +04:00
Do this as a normal read . */
2009-01-13 22:19:11 +03:00
if ( errno = = ENOSYS ) {
2004-12-21 01:01:42 +03:00
goto normal_read ;
}
2002-09-25 19:19:00 +04:00
/*
2004-11-25 01:05:59 +03:00
* Special hack for broken Linux with no working sendfile . If we
* return EINTR we sent the header but not the rest of the data .
* Fake this up by doing read / write calls .
2002-09-25 19:19:00 +04:00
*/
2004-12-21 01:01:42 +03:00
2004-11-25 01:05:59 +03:00
if ( errno = = EINTR ) {
/* Ensure we don't do this again. */
2004-08-06 21:49:00 +04:00
set_use_sendfile ( SNUM ( conn ) , False ) ;
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readX: sendfile not available. Faking.. \n " ) ) ;
2007-08-12 15:22:26 +04:00
nread = fake_sendfile ( fsp , startpos ,
smb_maxcnt ) ;
if ( nread = = - 1 ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readX: "
" fake_sendfile failed for "
" file %s (%s). \n " ,
fsp_str_dbg ( fsp ) ,
strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readX: fake_sendfile failed " ) ;
2004-11-25 01:05:59 +03:00
}
2004-12-21 01:01:42 +03:00
DEBUG ( 3 , ( " send_file_readX: fake_sendfile fnum=%d max=%d nread=%d \n " ,
2004-12-21 01:04:53 +03:00
fsp - > fnum , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2007-08-12 13:16:54 +04:00
/* No outbuf here means successful sendfile. */
2009-05-13 03:32:32 +04:00
goto strict_unlock ;
2004-08-06 21:49:00 +04:00
}
2002-09-25 19:19:00 +04:00
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readX: sendfile failed for file "
" %s (%s). Terminating \n " , fsp_str_dbg ( fsp ) ,
strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readX sendfile failed " ) ;
2009-02-21 00:28:36 +03:00
} else if ( nread = = 0 ) {
/*
* Some sendfile implementations return 0 to indicate
* that there was a short read , but nothing was
* actually written to the socket . In this case ,
* fallback to the normal read path so the header gets
* the correct byte count .
*/
DEBUG ( 3 , ( " send_file_readX: sendfile sent zero bytes "
" falling back to the normal read: %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2009-02-21 00:28:36 +03:00
goto normal_read ;
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 ) ) ;
2009-01-14 00:02:44 +03:00
/* Deal with possible short send. */
2009-01-14 02:36:09 +03:00
if ( nread ! = smb_maxcnt + sizeof ( headerbuf ) ) {
sendfile_short_send ( fsp , nread , sizeof ( headerbuf ) , smb_maxcnt ) ;
}
2007-08-12 13:16:54 +04:00
/* No outbuf here means successful sendfile. */
2009-02-09 10:10:34 +03:00
SMB_PERFCOUNT_SET_MSGLEN_OUT ( & req - > pcd , nread ) ;
SMB_PERFCOUNT_END ( & req - > pcd ) ;
2009-05-13 03:32:32 +04:00
goto strict_unlock ;
2002-09-25 19:19:00 +04:00
}
2007-06-01 23:34:08 +04:00
normal_read :
2007-05-16 04:21:12 +04:00
2009-05-12 10:23:17 +04:00
# endif
2007-08-12 16:57:56 +04:00
if ( ( smb_maxcnt & 0xFF0000 ) > 0x10000 ) {
uint8 headerbuf [ smb_size + 2 * 12 ] ;
2007-08-12 15:40:27 +04:00
2008-11-03 22:16:09 +03:00
construct_reply_common_req ( req , ( char * ) headerbuf ) ;
2008-11-22 01:17:31 +03:00
setup_readX_header ( req , ( char * ) headerbuf , smb_maxcnt ) ;
2007-08-12 15:40:27 +04:00
2007-05-16 04:07:38 +04:00
/* Send out the header. */
2007-08-12 16:57:56 +04:00
if ( write_data ( smbd_server_fd ( ) , ( char * ) headerbuf ,
sizeof ( headerbuf ) ) ! = sizeof ( headerbuf ) ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readX: write_data failed for file "
" %s (%s). Terminating \n " , fsp_str_dbg ( fsp ) ,
strerror ( errno ) ) ) ;
2007-05-16 04:07:38 +04:00
exit_server_cleanly ( " send_file_readX sendfile failed " ) ;
}
2007-08-12 15:22:26 +04:00
nread = fake_sendfile ( fsp , startpos , smb_maxcnt ) ;
if ( nread = = - 1 ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readX: fake_sendfile failed for "
" file %s (%s). \n " , fsp_str_dbg ( fsp ) ,
strerror ( errno ) ) ) ;
2007-05-16 04:07:38 +04:00
exit_server_cleanly ( " send_file_readX: fake_sendfile failed " ) ;
}
2009-05-13 03:32:32 +04:00
goto strict_unlock ;
2008-09-01 20:42:44 +04:00
}
2002-09-25 19:19:00 +04:00
2009-05-02 13:31:37 +04:00
nosendfile_read :
2008-09-01 20:42:44 +04:00
reply_outbuf ( req , 12 , smb_maxcnt ) ;
2002-09-25 19:19:00 +04:00
2008-09-01 20:42:44 +04:00
nread = read_file ( fsp , smb_buf ( req - > outbuf ) , startpos , smb_maxcnt ) ;
2009-07-11 05:23:00 +04:00
saved_errno = errno ;
2009-05-13 03:32:32 +04:00
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
2008-09-01 20:42:44 +04:00
if ( nread < 0 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
2008-09-01 20:42:44 +04:00
return ;
}
2007-05-16 04:07:38 +04:00
2008-11-22 01:17:31 +03:00
setup_readX_header ( req , ( char * ) req - > outbuf , nread ) ;
2007-05-16 04:07:38 +04:00
2008-09-01 20:42:44 +04:00
DEBUG ( 3 , ( " send_file_readX fnum=%d max=%d nread=%d \n " ,
fsp - > fnum , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2007-08-12 13:16:54 +04:00
2008-09-01 20:42:44 +04:00
chain_reply ( req ) ;
2009-05-13 03:32:32 +04:00
return ;
strict_unlock :
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
TALLOC_FREE ( req - > outbuf ) ;
return ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a read and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_read_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-11 01:33:58 +04:00
files_struct * fsp ;
SMB_OFF_T startpos ;
size_t smb_maxcnt ;
2007-10-19 04:40:25 +04:00
bool big_readX = False ;
2002-09-25 19:19:00 +04:00
#if 0
2008-11-02 14:20:47 +03:00
size_t smb_mincnt = SVAL ( req - > vwv + 6 , 0 ) ;
2002-09-25 19:19:00 +04:00
# endif
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
START_PROFILE ( SMBreadX ) ;
1998-03-12 02:20:26 +03:00
2007-08-11 14:40:35 +04:00
if ( ( req - > wct ! = 10 ) & & ( req - > wct ! = 12 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2007-08-11 01:33:58 +04:00
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 2 , 0 ) ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 3 , 0 ) ;
smb_maxcnt = SVAL ( req - > vwv + 5 , 0 ) ;
2007-08-11 14:40:35 +04:00
2002-09-25 19:19:00 +04:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-08-11 14:53:36 +04:00
reply_pipe_read_and_X ( req ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
2007-08-11 14:40:35 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-11 14:40:35 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
}
2008-11-06 22:16:04 +03:00
if ( ! CHECK_READ ( fsp , req ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-11 14:40:35 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2004-11-24 06:42:01 +03:00
if ( global_client_caps & CAP_LARGE_READX ) {
2008-11-02 14:20:47 +03:00
size_t upper_size = SVAL ( req - > vwv + 7 , 0 ) ;
2007-05-16 04:07:38 +04:00
smb_maxcnt | = ( upper_size < < 16 ) ;
if ( upper_size > 1 ) {
/* Can't do this on a chained packet. */
2008-11-02 14:20:47 +03:00
if ( ( CVAL ( req - > vwv + 0 , 0 ) ! = 0xFF ) ) {
2007-08-11 14:40:35 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
END_PROFILE ( SMBreadX ) ;
return ;
2007-05-16 04:07:38 +04:00
}
2007-12-27 04:12:36 +03:00
/* We currently don't do this on signed or sealed data. */
2010-06-12 13:46:29 +04:00
if ( srv_is_signing_active ( req - > sconn ) | |
2009-03-09 11:47:59 +03:00
is_encrypted_packet ( req - > inbuf ) ) {
2007-08-11 14:40:35 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
END_PROFILE ( SMBreadX ) ;
return ;
2007-05-16 04:07:38 +04:00
}
2007-05-19 05:27:34 +04:00
/* Is there room in the reply for this data ? */
if ( smb_maxcnt > ( 0xFFFFFF - ( smb_size - 4 + 12 * 2 ) ) ) {
2007-08-11 14:40:35 +04:00
reply_nterror ( req ,
NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBreadX ) ;
return ;
2007-05-19 05:27:34 +04:00
}
2007-05-16 04:07:38 +04:00
big_readX = True ;
2004-11-24 08:24:38 +03:00
}
2004-11-24 06:42:01 +03:00
}
2007-08-11 15:20:21 +04:00
if ( req - > wct = = 12 ) {
1999-12-13 16:27:58 +03:00
# ifdef LARGE_SMB_OFF_T
2002-09-25 19:19:00 +04:00
/*
* This is a large offset ( 64 bit ) read .
*/
2008-11-02 14:20:47 +03:00
startpos | = ( ( ( SMB_OFF_T ) IVAL ( req - > vwv + 10 , 0 ) ) < < 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
2008-11-02 14:20:47 +03:00
if ( IVAL ( req - > vwv + 10 , 0 ) ! = 0 ) {
2007-08-11 14:40:35 +04:00
DEBUG ( 0 , ( " reply_read_and_X - large offset (%x << 32) "
" used and we don't support 64 bit offsets. \n " ,
2008-11-02 14:20:47 +03:00
( unsigned int ) IVAL ( req - > vwv + 10 , 0 ) ) ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-11 14:40:35 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
1999-12-13 16:27:58 +03:00
1998-09-11 23:14:27 +04:00
# endif /* LARGE_SMB_OFF_T */
1998-09-11 05:24:30 +04:00
2002-09-25 19:19:00 +04:00
}
1999-12-13 16:27:58 +03:00
2010-04-06 01:16:21 +04:00
if ( ! big_readX ) {
NTSTATUS status = schedule_aio_read_and_X ( conn ,
req ,
fsp ,
startpos ,
smb_maxcnt ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
/* Read scheduled - we're done. */
goto out ;
}
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_RETRY ) ) {
/* Real error - report to client. */
END_PROFILE ( SMBreadX ) ;
reply_nterror ( req , status ) ;
return ;
}
/* NT_STATUS_RETRY - fall back to sync read. */
2007-08-11 15:20:21 +04:00
}
2010-06-12 13:46:29 +04:00
smbd_lock_socket ( req - > sconn ) ;
2007-08-12 13:16:54 +04:00
send_file_readX ( conn , req , fsp , startpos , smb_maxcnt ) ;
2010-06-12 13:46:29 +04:00
smbd_unlock_socket ( req - > sconn ) ;
2007-08-11 14:40:35 +04:00
2009-05-13 03:32:32 +04:00
out :
2007-08-11 14:40:35 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
2007-08-11 14:26:40 +04:00
}
2007-08-15 05:54:37 +04:00
/****************************************************************************
Error replies to writebraw must have smb_wct = = 1. Fix this up .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void error_to_writebrawerr ( struct smb_request * req )
{
uint8 * old_outbuf = req - > outbuf ;
reply_outbuf ( req , 1 , 0 ) ;
memcpy ( req - > outbuf , old_outbuf , smb_size ) ;
TALLOC_FREE ( old_outbuf ) ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writebraw ( core + or LANMAN1 .0 protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_writebraw ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-15 05:54:37 +04:00
char * buf = NULL ;
2001-09-04 23:10:30 +04:00
ssize_t nwritten = 0 ;
ssize_t total_written = 0 ;
size_t numtowrite = 0 ;
size_t tcount ;
SMB_OFF_T startpos ;
char * data = NULL ;
2007-10-19 04:40:25 +04:00
bool write_through ;
2007-08-15 05:54:37 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2007-08-15 05:54:37 +04:00
2001-09-04 23:10:30 +04:00
START_PROFILE ( SMBwritebraw ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/*
* If we ever reply with an error , it must have the SMB command
* type of SMBwritec , not SMBwriteBraw , as this tells the client
* we ' re finished .
*/
SCVAL ( req - > inbuf , smb_com , SMBwritec ) ;
2010-06-12 13:47:33 +04:00
if ( srv_is_signing_active ( req - > sconn ) ) {
2007-08-15 05:54:37 +04:00
END_PROFILE ( SMBwritebraw ) ;
exit_server_cleanly ( " reply_writebraw: SMB signing is active - "
" raw reads/writes are disallowed. " ) ;
}
if ( req - > wct < 12 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
2010-06-12 13:47:33 +04:00
if ( req - > sconn - > smb1 . echo_handler . trusted_fde ) {
2010-05-26 19:52:10 +04:00
DEBUG ( 2 , ( " SMBwritebraw rejected with NOT_SUPPORTED because of "
" 'async smb echo handler = yes' \n " ) ) ;
2010-03-22 11:11:05 +03:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
2003-07-17 04:53:37 +04:00
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2007-08-15 05:54:37 +04:00
2008-11-02 14:20:47 +03:00
tcount = IVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 3 , 0 ) ;
write_through = BITSETW ( req - > vwv + 7 , 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
2009-11-23 18:33:26 +03:00
if ( get_Protocol ( ) < = PROTOCOL_COREPLUS ) {
2007-08-15 05:54:37 +04:00
numtowrite = SVAL ( smb_buf ( req - > inbuf ) , - 2 ) ;
data = smb_buf ( req - > inbuf ) ;
2001-09-04 23:10:30 +04:00
} else {
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 10 , 0 ) ;
data = smb_base ( req - > inbuf ) + SVAL ( req - > vwv + 11 , 0 ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Ensure we don't write bytes past the end of this packet. */
if ( data + numtowrite > smb_base ( req - > inbuf ) + smb_len ( req - > inbuf ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2010-04-29 03:42:04 +04:00
if ( ! fsp - > print_file ) {
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2010-03-24 22:47:01 +03:00
( uint64_t ) startpos , ( uint64_t ) tcount , WRITE_LOCK ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2010-03-24 22:47:01 +03:00
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
if ( numtowrite > 0 ) {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2007-08-15 05:54:37 +04:00
}
DEBUG ( 3 , ( " reply_writebraw: initial write fnum=%d start=%.0f num=%d "
" wrote=%d sync=%d \n " ,
fsp - > fnum , ( double ) startpos , ( int ) numtowrite ,
( int ) nwritten , ( int ) write_through ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-31 13:25:11 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
total_written = nwritten ;
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Allocate a buffer of 64k + length. */
buf = TALLOC_ARRAY ( NULL , char , 65540 ) ;
if ( ! buf ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2007-08-15 05:54:37 +04:00
}
/* Return a SMBwritebraw message to the redirector to tell
* it to send more bytes */
memcpy ( buf , req - > inbuf , smb_size ) ;
2009-11-23 18:33:26 +03:00
srv_set_message ( buf , get_Protocol ( ) > PROTOCOL_COREPLUS ? 1 : 0 , 0 , True ) ;
2007-08-15 05:54:37 +04:00
SCVAL ( buf , smb_com , SMBwritebraw ) ;
SSVALS ( buf , smb_vwv0 , 0xFFFF ) ;
show_msg ( buf ) ;
2008-01-04 23:56:23 +03:00
if ( ! srv_send_smb ( smbd_server_fd ( ) ,
2009-03-09 11:47:59 +03:00
buf ,
false , 0 , /* no signing */
IS_CONN_ENCRYPTED ( conn ) ,
& req - > pcd ) ) {
2008-01-04 23:56:23 +03:00
exit_server_cleanly ( " reply_writebraw: srv_send_smb "
2007-08-15 05:54:37 +04:00
" failed. " ) ;
}
2001-09-04 23:10:30 +04:00
/* Now read the raw data into the buffer and write it */
2008-01-25 23:31:40 +03:00
status = read_smb_length ( smbd_server_fd ( ) , buf , SMB_SECONDARY_WAIT ,
& numtowrite ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Set up outbuf to return the correct size */
reply_outbuf ( req , 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( numtowrite ! = 0 ) {
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
if ( numtowrite > 0xFFFF ) {
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write "
" raw requested (%u). Terminating \n " ,
2001-09-04 23:10:30 +04:00
( unsigned int ) numtowrite ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( tcount > nwritten + numtowrite ) {
2007-08-15 05:54:37 +04:00
DEBUG ( 3 , ( " reply_writebraw: Client overestimated the "
" write %d %d %d \n " ,
2001-09-04 23:10:30 +04:00
( int ) tcount , ( int ) nwritten , ( int ) numtowrite ) ) ;
}
1996-05-04 11:50:46 +04:00
2008-01-26 12:39:21 +03:00
status = read_data ( smbd_server_fd ( ) , buf + 4 , numtowrite ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 05:54:37 +04:00
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write "
2008-01-26 12:39:21 +03:00
" raw read failed (%s). Terminating \n " ,
nt_errstr ( status ) ) ) ;
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
2010-03-26 19:32:40 +03:00
nwritten = write_file ( req , fsp , buf + 4 , startpos + nwritten , numtowrite ) ;
2006-07-25 04:16:45 +04:00
if ( nwritten = = - 1 ) {
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( buf ) ;
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2006-07-25 04:16:45 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-15 05:54:37 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
if ( nwritten > 0 ) {
2001-09-04 23:10:30 +04:00
total_written + = nwritten ;
2007-08-15 05:54:37 +04:00
}
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( buf ) ;
SSVAL ( req - > outbuf , smb_vwv0 , total_written ) ;
2005-07-10 20:37:32 +04:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , write_through ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_writebraw: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-15 05:54:37 +04:00
reply_nterror ( req , status ) ;
error_to_writebrawerr ( req ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2007-06-15 23:24:04 +04:00
}
2001-09-04 23:10:30 +04:00
2007-08-15 05:54:37 +04:00
DEBUG ( 3 , ( " reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
" wrote=%d \n " ,
fsp - > fnum , ( double ) startpos , ( int ) numtowrite ,
( int ) total_written ) ) ;
2001-09-04 23:10:30 +04:00
2010-03-24 22:47:01 +03:00
if ( ! fsp - > print_file ) {
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
}
2009-03-14 00:15:28 +03:00
2007-08-15 05:54:37 +04:00
/* We won't return a status if write through is not selected - this
* follows what WfWg does */
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBwritebraw ) ;
2007-08-15 05:54:37 +04:00
2001-09-04 23:10:30 +04:00
if ( ! write_through & & total_written = = tcount ) {
2002-04-11 06:20:56 +04:00
# if RABBIT_PELLET_FIX
2001-09-04 23:10:30 +04:00
/*
* Fix for " rabbit pellet " mode , trigger an early TCP ack by
2007-08-15 05:54:37 +04:00
* sending a SMBkeepalive . Thanks to DaveCB at Sun for this .
* JRA .
2001-09-04 23:10:30 +04:00
*/
2007-08-15 05:54:37 +04:00
if ( ! send_keepalive ( smbd_server_fd ( ) ) ) {
exit_server_cleanly ( " reply_writebraw: send of "
" keepalive failed " ) ;
}
2002-04-11 06:20:56 +04:00
# endif
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( req - > outbuf ) ;
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
return ;
2009-03-14 00:15:28 +03:00
strict_unlock :
2010-03-24 22:47:01 +03:00
if ( ! fsp - > print_file ) {
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
}
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwritebraw ) ;
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writeunlock ( core + ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_writeunlock ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2001-08-27 12:19:43 +04:00
ssize_t nwritten = - 1 ;
size_t numtowrite ;
SMB_OFF_T startpos ;
2008-11-01 19:35:48 +03:00
const char * data ;
2003-10-10 01:04:48 +04:00
NTSTATUS status = NT_STATUS_OK ;
2007-08-15 00:20:51 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2009-07-11 05:23:00 +04:00
int saved_errno = 0 ;
2007-08-15 00:20:51 +04:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-15 00:20:51 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBwriteunlock ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 3 ;
2008-10-19 17:30:12 +04:00
2010-04-29 03:42:04 +04:00
if ( ! fsp - > print_file & & numtowrite > 0 ) {
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2009-03-14 00:15:28 +03:00
( uint64_t ) startpos , ( uint64_t ) numtowrite , WRITE_LOCK ,
& lock ) ;
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2001-08-27 12:19:43 +04:00
}
2001-08-07 05:19:32 +04:00
2001-08-27 12:19:43 +04:00
/* The special X/Open SMB protocol handling of
zero length writes is * NOT * done for
this call */
2005-07-08 08:51:27 +04:00
if ( numtowrite = = 0 ) {
2001-08-27 12:19:43 +04:00
nwritten = 0 ;
2005-07-08 08:51:27 +04:00
} else {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2009-07-11 05:23:00 +04:00
saved_errno = errno ;
2005-07-08 08:51:27 +04:00
}
2008-10-19 17:30:12 +04:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , False /* write through */ ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_writeunlock: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2007-06-15 23:24:04 +04:00
}
2001-08-27 12:19:43 +04:00
2009-07-11 05:23:00 +04:00
if ( nwritten < 0 ) {
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
goto strict_unlock ;
}
if ( ( nwritten < numtowrite ) & & ( numtowrite ! = 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2001-08-07 05:19:32 +04:00
}
2010-03-24 22:47:01 +03:00
if ( numtowrite & & ! fsp - > print_file ) {
2007-05-14 17:01:28 +04:00
status = do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2010-05-07 17:20:50 +04:00
( uint64_t ) req - > smbpid ,
2008-10-14 03:59:36 +04:00
( uint64_t ) numtowrite ,
( uint64_t ) startpos ,
2006-04-10 19:33:04 +04:00
WINDOWS_LOCK ) ;
2003-10-10 01:04:48 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2003-10-10 01:04:48 +04:00
}
2001-08-27 12:19:43 +04:00
}
2007-08-15 00:20:51 +04:00
reply_outbuf ( req , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
2007-08-15 00:20:51 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " writeunlock fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
2008-10-19 17:30:12 +04:00
2009-03-14 00:15:28 +03:00
strict_unlock :
2010-03-24 22:47:01 +03:00
if ( numtowrite & & ! fsp - > print_file ) {
2009-03-14 00:15:28 +03:00
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
}
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-07 05:19:32 +04:00
}
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_write ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2001-11-25 05:23:22 +03:00
size_t numtowrite ;
ssize_t nwritten = - 1 ;
SMB_OFF_T startpos ;
2008-11-01 19:35:48 +03:00
const char * data ;
2007-08-14 22:16:04 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2009-07-11 05:23:00 +04:00
int saved_errno = 0 ;
2007-08-14 22:16:04 +04:00
2001-11-25 05:23:22 +03:00
START_PROFILE ( SMBwrite ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
if ( req - > wct < 5 ) {
END_PROFILE ( SMBwrite ) ;
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2001-11-25 05:23:22 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-08-14 22:16:04 +04:00
reply_pipe_write ( req ) ;
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 22:16:04 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 05:54:37 +04:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2001-11-25 05:23:22 +03:00
}
1999-11-16 01:11:10 +03:00
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-06-15 23:24:04 +04:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 3 ;
2008-10-19 17:30:12 +04:00
2010-04-29 03:42:04 +04:00
if ( ! fsp - > print_file ) {
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2010-03-24 22:47:01 +03:00
( uint64_t ) startpos , ( uint64_t ) numtowrite , WRITE_LOCK ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2010-03-24 22:47:01 +03:00
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
END_PROFILE ( SMBwrite ) ;
return ;
}
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
/*
* X / Open SMB protocol says that if smb_vwv1 is
* zero then the file size should be extended or
* truncated to the size given in smb_vwv [ 2 - 3 ] .
*/
if ( numtowrite = = 0 ) {
/*
* This is actually an allocate call , and set EOF . JRA .
*/
nwritten = vfs_allocate_file_space ( fsp , ( SMB_OFF_T ) startpos ) ;
if ( nwritten < 0 ) {
2007-08-14 22:16:04 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2001-11-25 05:23:22 +03:00
}
nwritten = vfs_set_filelen ( fsp , ( SMB_OFF_T ) startpos ) ;
if ( nwritten < 0 ) {
2007-08-14 22:16:04 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2001-11-25 05:23:22 +03:00
}
2008-09-06 06:00:48 +04:00
trigger_write_time_update_immediate ( fsp ) ;
} else {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2008-09-06 06:00:48 +04:00
}
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , False ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_write: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-14 22:16:04 +04:00
reply_nterror ( req , status ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2007-06-15 23:24:04 +04:00
}
1996-05-04 11:50:46 +04:00
2009-07-11 05:23:00 +04:00
if ( nwritten < 0 ) {
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
goto strict_unlock ;
}
if ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
reply_outbuf ( req , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
2007-08-14 22:16:04 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-14 22:16:04 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2001-11-25 05:23:22 +03:00
}
2008-10-19 17:30:12 +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
2009-03-14 00:15:28 +03:00
strict_unlock :
2010-03-24 22:47:01 +03:00
if ( ! fsp - > print_file ) {
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
}
2009-03-14 00:15:28 +03:00
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2007-10-31 02:22:24 +03:00
/****************************************************************************
Ensure a buffer is a valid writeX for recvfile purposes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
( 2 * 14 ) + /* word count (including bcc) */ \
1 /* pad byte */ )
2008-01-04 23:56:23 +03:00
bool is_valid_writeX_buffer ( const uint8_t * inbuf )
2007-10-31 02:22:24 +03:00
{
size_t numtowrite ;
connection_struct * conn = NULL ;
unsigned int doff = 0 ;
2007-11-02 22:21:34 +03:00
size_t len = smb_len_large ( inbuf ) ;
2009-05-27 13:15:44 +04:00
struct smbd_server_connection * sconn = smbd_server_conn ;
2007-10-31 02:22:24 +03:00
2008-01-04 23:56:23 +03:00
if ( is_encrypted_packet ( inbuf ) ) {
2007-12-27 04:12:36 +03:00
/* Can't do this on encrypted
* connections . */
return false ;
}
2007-11-08 08:47:00 +03:00
if ( CVAL ( inbuf , smb_com ) ! = SMBwriteX ) {
return false ;
}
if ( CVAL ( inbuf , smb_vwv0 ) ! = 0xFF | |
2007-10-31 02:22:24 +03:00
CVAL ( inbuf , smb_wct ) ! = 14 ) {
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: chained or "
" invalid word length. \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
2007-11-08 08:47:00 +03:00
2009-05-27 13:15:44 +04:00
conn = conn_find ( sconn , SVAL ( inbuf , smb_tid ) ) ;
2007-10-31 02:22:24 +03:00
if ( conn = = NULL ) {
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: bad tid \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
if ( IS_IPC ( conn ) ) {
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: IPC$ tid \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
2008-12-31 20:37:39 +03:00
if ( IS_PRINT ( conn ) ) {
DEBUG ( 10 , ( " is_valid_writeX_buffer: printing tid \n " ) ) ;
return false ;
}
2007-11-02 22:21:34 +03:00
doff = SVAL ( inbuf , smb_vwv11 ) ;
2007-10-31 02:22:24 +03:00
numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
2007-11-02 22:21:34 +03:00
if ( len > doff & & len - doff > 0xFFFF ) {
numtowrite | = ( ( ( size_t ) SVAL ( inbuf , smb_vwv9 ) ) < < 16 ) ;
}
2007-10-31 02:22:24 +03:00
if ( numtowrite = = 0 ) {
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: zero write \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
2007-11-02 22:21:34 +03:00
/* Ensure the sizes match up. */
2007-10-31 02:22:24 +03:00
if ( doff < STANDARD_WRITE_AND_X_HEADER_SIZE ) {
/* no pad byte...old smbclient :-( */
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: small doff %u (min %u) \n " ,
( unsigned int ) doff ,
( unsigned int ) STANDARD_WRITE_AND_X_HEADER_SIZE ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
if ( len - doff ! = numtowrite ) {
DEBUG ( 10 , ( " is_valid_writeX_buffer: doff mismatch "
" len = %u, doff = %u, numtowrite = %u \n " ,
( unsigned int ) len ,
( unsigned int ) doff ,
( unsigned int ) numtowrite ) ) ;
return false ;
}
DEBUG ( 10 , ( " is_valid_writeX_buffer: true "
" len = %u, doff = %u, numtowrite = %u \n " ,
( unsigned int ) len ,
( unsigned int ) doff ,
( unsigned int ) numtowrite ) ) ;
return true ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a write and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_write_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-07 17:12:46 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-08-07 17:12:46 +04:00
SMB_OFF_T startpos ;
size_t numtowrite ;
2007-10-19 04:40:25 +04:00
bool write_through ;
2007-08-07 17:12:46 +04:00
ssize_t nwritten ;
unsigned int smb_doff ;
unsigned int smblen ;
2002-12-04 02:57:45 +03:00
char * data ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2010-04-06 01:16:21 +04:00
int saved_errno = 0 ;
2007-08-07 17:12:46 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBwriteX ) ;
2007-08-08 22:40:26 +04:00
if ( ( req - > wct ! = 12 ) & & ( req - > wct ! = 14 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-07 17:43:02 +04:00
END_PROFILE ( SMBwriteX ) ;
return ;
}
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 10 , 0 ) ;
smb_doff = SVAL ( req - > vwv + 11 , 0 ) ;
2007-08-08 22:40:26 +04:00
smblen = smb_len ( req - > inbuf ) ;
2007-11-02 08:24:39 +03:00
if ( req - > unread_bytes > 0xFFFF | |
2007-11-02 20:35:10 +03:00
( smblen > smb_doff & &
smblen - smb_doff > 0xFFFF ) ) {
2008-11-02 14:20:47 +03:00
numtowrite | = ( ( ( size_t ) SVAL ( req - > vwv + 9 , 0 ) ) < < 16 ) ;
2007-08-08 22:40:26 +04:00
}
2007-10-31 02:22:24 +03:00
if ( req - > unread_bytes ) {
2007-11-08 08:47:00 +03:00
/* Can't do a recvfile write on IPC$ */
if ( IS_IPC ( conn ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteX ) ;
return ;
}
2007-10-31 02:22:24 +03:00
if ( numtowrite ! = req - > unread_bytes ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-10-31 02:22:24 +03:00
END_PROFILE ( SMBwriteX ) ;
return ;
}
} else {
2007-11-02 20:35:10 +03:00
if ( smb_doff > smblen | | smb_doff + numtowrite < numtowrite | |
smb_doff + numtowrite > smblen ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-10-31 02:22:24 +03:00
END_PROFILE ( SMBwriteX ) ;
return ;
}
2007-08-07 17:12:46 +04:00
}
2002-12-04 02:57:45 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-11-02 08:42:21 +03:00
if ( req - > unread_bytes ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-11-02 08:42:21 +03:00
END_PROFILE ( SMBwriteX ) ;
return ;
}
2007-08-08 22:40:26 +04:00
reply_pipe_write_and_X ( req ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 2 , 0 ) ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 3 , 0 ) ;
write_through = BITSETW ( req - > vwv + 7 , 0 ) ;
2007-08-08 22:40:26 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-07 17:43:02 +04:00
END_PROFILE ( SMBwriteX ) ;
return ;
2002-12-04 02:57:45 +03:00
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-07 17:14:49 +04:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2007-08-08 23:05:30 +04:00
data = smb_base ( req - > inbuf ) + smb_doff ;
2002-12-04 02:57:45 +03:00
2007-08-08 23:05:30 +04:00
if ( req - > wct = = 14 ) {
1999-12-13 16:27:58 +03:00
# ifdef LARGE_SMB_OFF_T
2002-12-04 02:57:45 +03:00
/*
* This is a large offset ( 64 bit ) write .
*/
2008-11-02 14:20:47 +03:00
startpos | = ( ( ( SMB_OFF_T ) IVAL ( req - > vwv + 12 , 0 ) ) < < 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
2008-11-02 14:20:47 +03:00
if ( IVAL ( req - > vwv + 12 , 0 ) ! = 0 ) {
2007-08-07 17:43:02 +04:00
DEBUG ( 0 , ( " reply_write_and_X - large offset (%x << 32) "
" used and we don't support 64 bit offsets. \n " ,
2008-11-02 14:20:47 +03:00
( unsigned int ) IVAL ( req - > vwv + 12 , 0 ) ) ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1999-12-13 16:27:58 +03:00
1998-09-11 23:14:27 +04:00
# endif /* LARGE_SMB_OFF_T */
2002-12-04 02:57:45 +03:00
}
/* 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 {
2010-04-06 01:16:21 +04:00
if ( req - > unread_bytes = = 0 ) {
status = schedule_aio_write_and_X ( conn ,
req ,
fsp ,
data ,
startpos ,
numtowrite ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
/* write scheduled - we're done. */
goto out ;
}
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_RETRY ) ) {
/* Real error - report to client. */
reply_nterror ( req , status ) ;
goto out ;
}
/* NT_STATUS_RETRY - fall through to sync write. */
}
2005-06-09 22:15:23 +04:00
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2010-04-06 01:16:21 +04:00
( uint64_t ) startpos , ( uint64_t ) numtowrite , WRITE_LOCK ,
& lock ) ;
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
goto out ;
2005-06-09 22:15:23 +04:00
}
2008-10-19 17:30:12 +04:00
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2010-04-06 01:16:21 +04:00
saved_errno = errno ;
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
2005-06-09 22:15:23 +04:00
}
2007-10-31 02:22:24 +03:00
2009-07-11 05:23:00 +04:00
if ( nwritten < 0 ) {
2010-04-06 01:16:21 +04:00
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
goto out ;
2009-07-11 05:23:00 +04:00
}
if ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2010-04-06 01:16:21 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-08-13 11:20:19 +04:00
reply_outbuf ( req , 6 , 0 ) ;
2007-08-08 23:05:30 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , nwritten ) ;
2007-11-02 08:24:39 +03:00
SSVAL ( req - > outbuf , smb_vwv4 , nwritten > > 16 ) ;
2002-12-04 02:57:45 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-08 23:05:30 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2002-12-04 02:57:45 +03:00
}
DEBUG ( 3 , ( " writeX fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , write_through ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_write_and_X: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-07 17:43:02 +04:00
reply_nterror ( req , status ) ;
2010-04-06 01:16:21 +04:00
goto out ;
2007-06-15 23:24:04 +04:00
}
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2007-08-07 17:43:02 +04:00
return ;
2009-03-14 00:15:28 +03:00
2010-04-06 01:16:21 +04:00
out :
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwriteX ) ;
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lseek .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_lseek ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-12-04 02:57:45 +03:00
SMB_OFF_T startpos ;
SMB_OFF_T res = - 1 ;
int mode , umode ;
2007-08-14 20:04:31 +04:00
files_struct * fsp ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBlseek ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 20:04:31 +04:00
if ( req - > wct < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlseek ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 20:04:31 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 20:04:31 +04:00
return ;
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
flush_write_cache ( fsp , SEEK_FLUSH ) ;
1999-12-13 16:27:58 +03:00
2008-11-02 14:20:47 +03:00
mode = SVAL ( req - > vwv + 1 , 0 ) & 3 ;
2002-12-04 02:57:45 +03:00
/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2008-11-02 14:20:47 +03:00
startpos = ( SMB_OFF_T ) IVALS ( req - > vwv + 2 , 0 ) ;
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 ) {
2008-01-07 12:15:08 +03:00
if ( ( res = SMB_VFS_LSEEK ( fsp , startpos , umode ) ) = = - 1 ) {
2003-08-15 01:16:06 +04:00
if ( errno = = EINVAL ) {
SMB_OFF_T current_pos = startpos ;
1999-12-13 16:27:58 +03:00
2009-11-18 03:06:08 +03:00
if ( fsp_stat ( fsp ) = = - 1 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req ,
map_nt_error_from_unix ( errno ) ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1999-12-13 16:27:58 +03:00
2009-11-18 03:06:08 +03:00
current_pos + = fsp - > fsp_name - > st . st_ex_size ;
2003-08-15 01:16:06 +04:00
if ( current_pos < 0 )
2008-01-07 12:15:08 +03:00
res = SMB_VFS_LSEEK ( fsp , 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 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
}
1998-10-19 02:06:35 +04:00
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos = res ;
2007-08-14 20:04:31 +04:00
reply_outbuf ( req , 2 , 0 ) ;
SIVAL ( req - > outbuf , smb_vwv0 , res ) ;
2008-10-19 17:30:12 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d \n " ,
fsp - > fnum , ( double ) startpos , ( double ) res , mode ) ) ;
1998-08-01 02:39:15 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a flush .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_flush ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-05 00:44:33 +04:00
uint16 fnum ;
files_struct * fsp ;
2001-08-24 08:56:33 +04:00
START_PROFILE ( SMBflush ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:44:33 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fnum = SVAL ( req - > vwv + 0 , 0 ) ;
2008-10-09 17:25:17 +04:00
fsp = file_fsp ( req , fnum ) ;
2007-08-05 00:44:33 +04:00
2008-06-19 18:31:59 +04:00
if ( ( fnum ! = 0xFFFF ) & & ! check_fsp ( conn , req , fsp ) ) {
2007-08-05 00:44:33 +04:00
return ;
}
2008-10-19 17:30:12 +04:00
2001-08-24 08:56:33 +04:00
if ( ! fsp ) {
file_sync_all ( conn ) ;
} else {
2007-06-15 23:24:04 +04:00
NTSTATUS status = sync_file ( conn , fsp , True ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_flush: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-05 00:44:33 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBflush ) ;
return ;
2007-06-15 23:24:04 +04:00
}
2001-08-24 08:56:33 +04:00
}
2008-10-19 17:30:12 +04:00
2007-08-05 00:44:33 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2001-08-24 08:56:33 +04:00
DEBUG ( 3 , ( " flush \n " ) ) ;
END_PROFILE ( SMBflush ) ;
2007-08-05 00:44:33 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a exit .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_exit ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBexit ) ;
2003-08-19 05:53:45 +04:00
2007-08-02 09:50:40 +04:00
file_close_pid ( req - > smbpid , req - > vuid ) ;
2003-08-19 05:53:45 +04:00
2007-08-02 09:50:40 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " exit \n " ) ) ;
1998-08-01 02:39:15 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBexit ) ;
2007-08-02 09:50:40 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1998-07-18 02:21:24 +04:00
Reply to a close - has to deal with closing a directory opened by NT SMB ' s .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_close ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-02-07 00:05:34 +03:00
NTSTATUS status = NT_STATUS_OK ;
1998-08-14 21:38:29 +04:00
files_struct * fsp = NULL ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBclose ) ;
1996-05-04 11:50:46 +04:00
2007-07-23 13:53:06 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBclose ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
1997-10-30 04:05:13 +03:00
1998-08-14 21:38:29 +04:00
/*
2008-10-08 14:56:04 +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
2008-06-19 20:21:41 +04:00
if ( ! fsp | | ( fsp - > conn ! = conn ) | | ( fsp - > vuid ! = req - > vuid ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( fsp - > is_directory ) {
1998-08-14 21:38:29 +04:00
/*
2002-03-20 03:46:53 +03:00
* Special case - close NT SMB directory handle .
1998-08-14 21:38:29 +04:00
*/
2006-12-20 01:13:10 +03:00
DEBUG ( 3 , ( " close directory fnum=%d \n " , fsp - > fnum ) ) ;
2008-10-09 18:27:49 +04:00
status = close_file ( req , fsp , NORMAL_CLOSE ) ;
1998-08-14 21:38:29 +04:00
} else {
2008-03-12 17:39:38 +03:00
time_t t ;
1998-08-14 21:38:29 +04:00
/*
* 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 ) ) ;
2008-10-19 17:30:12 +04:00
2005-03-10 04:30:14 +03:00
/*
* Take care of any time sent in the close .
*/
2008-11-02 14:20:47 +03:00
t = srv_make_unix_date3 ( req - > vwv + 1 ) ;
2009-11-06 09:58:12 +03:00
set_close_write_time ( fsp , convert_time_t_to_timespec ( t ) ) ;
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 .
*/
2008-10-19 17:30:12 +04:00
2008-10-09 18:27:49 +04:00
status = close_file ( req , fsp , NORMAL_CLOSE ) ;
1998-08-14 21:38:29 +04:00
}
1996-06-04 10:42:03 +04:00
2007-07-23 13:53:06 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
2007-07-23 13:53:06 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writeclose ( Core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_writeclose ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
1998-09-11 05:24:30 +04:00
size_t numtowrite ;
ssize_t nwritten = - 1 ;
2007-02-07 00:05:34 +03:00
NTSTATUS close_status = NT_STATUS_OK ;
1998-09-11 05:24:30 +04:00
SMB_OFF_T startpos ;
2008-11-01 19:35:48 +03:00
const char * data ;
2007-03-06 02:40:03 +03:00
struct timespec mtime ;
2007-08-14 23:29:02 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-08-14 23:29:02 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBwriteclose ) ;
1998-08-14 21:38:29 +04:00
2007-08-14 23:29:02 +04:00
if ( req - > wct < 6 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:29:02 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:29:02 +04:00
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-14 23:29:02 +04:00
END_PROFILE ( SMBwriteclose ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-08-14 21:38:29 +04:00
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
mtime = convert_time_t_to_timespec ( srv_make_unix_date3 ( req - > vwv + 4 ) ) ;
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 1 ;
2008-10-19 17:30:12 +04:00
2010-04-29 03:42:04 +04:00
if ( ! fsp - > print_file ) {
2010-05-07 17:20:50 +04:00
init_strict_lock_struct ( fsp , ( uint64_t ) req - > smbpid ,
2009-03-14 00:15:28 +03:00
( uint64_t ) startpos , ( uint64_t ) numtowrite , WRITE_LOCK ,
& lock ) ;
if ( ! SMB_VFS_STRICT_LOCK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2000-10-06 07:21:49 +04:00
}
2008-10-19 17:30:12 +04:00
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
1996-05-04 11:50:46 +04:00
2009-11-06 09:58:12 +03:00
set_close_write_time ( fsp , mtime ) ;
2008-03-12 17:39:38 +03:00
2003-10-10 01:04:48 +04:00
/*
* More insanity . W2K only closes the file if writelen > 0.
* JRA .
*/
if ( numtowrite ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 3 , ( " reply_writeclose: zero length write doesn't close "
" file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2008-10-09 18:27:49 +04:00
close_status = close_file ( req , 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 ) ) ;
2008-10-19 17:30:12 +04:00
2003-01-09 02:49:21 +03:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
2000-10-06 07:21:49 +04:00
}
2008-10-19 17:30:12 +04:00
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( close_status ) ) {
2007-08-14 23:29:02 +04:00
reply_nterror ( req , close_status ) ;
2009-03-14 00:15:28 +03:00
goto strict_unlock ;
1999-12-13 16:27:58 +03:00
}
2007-08-14 23:29:02 +04:00
reply_outbuf ( req , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
2007-08-14 23:29:02 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
2009-03-14 00:15:28 +03:00
strict_unlock :
2010-03-24 22:47:01 +03:00
if ( numtowrite & & ! fsp - > print_file ) {
2009-03-14 00:15:28 +03:00
SMB_VFS_STRICT_UNLOCK ( conn , fsp , & lock ) ;
}
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2007-08-14 23:29:02 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lock .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_lock ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2008-10-14 03:59:36 +04:00
uint64_t count , offset ;
2001-08-27 12:19:43 +04:00
NTSTATUS status ;
2007-08-14 22:52:58 +04:00
files_struct * fsp ;
2006-07-18 05:05:51 +04:00
struct byte_range_lock * br_lck = NULL ;
2003-10-09 05:46:01 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBlock ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:52:58 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlock ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 22:52:58 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 22:52:58 +04:00
END_PROFILE ( SMBlock ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
count = ( uint64_t ) IVAL ( req - > vwv + 1 , 0 ) ;
offset = ( uint64_t ) IVAL ( req - > vwv + 3 , 0 ) ;
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 ,
2010-05-07 17:20:50 +04:00
( uint64_t ) req - > smbpid ,
2006-07-18 01:09:02 +04:00
count ,
offset ,
WRITE_LOCK ,
WINDOWS_LOCK ,
2006-07-18 05:05:51 +04:00
False , /* Non-blocking lock. */
2007-05-20 00:57:12 +04:00
& status ,
2009-02-10 08:51:29 +03:00
NULL ,
2007-05-20 00:57:12 +04:00
NULL ) ;
2006-07-18 05:05:51 +04:00
TALLOC_FREE ( br_lck ) ;
2006-07-18 01:09:02 +04:00
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-14 22:52:58 +04:00
reply_nterror ( req , status ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlock ) ;
2007-08-14 22:52:58 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1998-08-01 02:39:15 +04:00
2007-08-14 22:52:58 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlock ) ;
2007-08-14 22:52:58 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a unlock .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_unlock ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2008-10-14 03:59:36 +04:00
uint64_t count , offset ;
2001-08-27 12:19:43 +04:00
NTSTATUS status ;
2007-08-14 23:09:37 +04:00
files_struct * fsp ;
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBunlock ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 23:09:37 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBunlock ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:09:37 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:09:37 +04:00
END_PROFILE ( SMBunlock ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2008-11-02 14:20:47 +03:00
count = ( uint64_t ) IVAL ( req - > vwv + 1 , 0 ) ;
offset = ( uint64_t ) IVAL ( req - > vwv + 3 , 0 ) ;
2008-10-19 17:30:12 +04:00
2007-05-14 17:01:28 +04:00
status = do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2010-05-07 17:20:50 +04:00
( uint64_t ) req - > smbpid ,
2006-04-10 19:33:04 +04:00
count ,
offset ,
WINDOWS_LOCK ) ;
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-14 23:09:37 +04:00
reply_nterror ( req , status ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
2007-08-14 23:09:37 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
DEBUG ( 3 , ( " unlock fd=%d fnum=%d offset=%.0f count=%.0f \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , fsp - > fnum , ( double ) offset , ( double ) count ) ) ;
2007-08-14 23:09:37 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
2007-08-14 23:09:37 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a tdis .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_tdis ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBtdis ) ;
1996-10-26 00:30:22 +04:00
1998-08-14 21:38:29 +04:00
if ( ! conn ) {
DEBUG ( 4 , ( " Invalid connection in tdis \n " ) ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NETWORK_NAME_DELETED ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtdis ) ;
2007-07-30 14:20:52 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-07-03 05:58:27 +04:00
1998-08-14 21:38:29 +04:00
conn - > used = False ;
1996-05-04 11:50:46 +04:00
2009-08-06 15:22:33 +04:00
close_cnum ( conn , req - > vuid ) ;
2008-01-04 23:56:23 +03:00
req - > conn = NULL ;
2007-07-30 14:20:52 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtdis ) ;
2007-07-30 14:20:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a echo .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_echo ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-02-17 07:45:45 +03:00
struct smb_perfcount_data local_pcd ;
struct smb_perfcount_data * cur_pcd ;
2007-08-05 00:08:35 +04:00
int smb_reverb ;
1998-08-14 21:38:29 +04:00
int seq_num ;
2007-08-05 00:08:35 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBecho ) ;
2000-04-27 20:53:31 +04:00
2009-02-17 07:45:45 +03:00
smb_init_perfcount_data ( & local_pcd ) ;
2007-08-05 00:08:35 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBecho ) ;
return ;
}
2008-11-02 14:20:47 +03:00
smb_reverb = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-05 00:08:35 +04:00
2008-11-01 18:24:42 +03:00
reply_outbuf ( req , 1 , req - > buflen ) ;
2007-08-05 00:08:35 +04:00
1998-08-14 21:38:29 +04:00
/* copy any incoming data back out */
2008-11-01 18:24:42 +03:00
if ( req - > buflen > 0 ) {
2008-11-01 19:35:48 +03:00
memcpy ( smb_buf ( req - > outbuf ) , req - > buf , req - > buflen ) ;
2007-08-05 00:08:35 +04:00
}
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
2009-02-17 07:45:45 +03:00
for ( seq_num = 1 ; seq_num < = smb_reverb ; seq_num + + ) {
/* this makes sure we catch the request pcd */
if ( seq_num = = smb_reverb ) {
cur_pcd = & req - > pcd ;
} else {
SMB_PERFCOUNT_COPY_CONTEXT ( & req - > pcd , & local_pcd ) ;
cur_pcd = & local_pcd ;
}
2007-08-05 00:08:35 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , seq_num ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:08:35 +04:00
show_msg ( ( char * ) req - > outbuf ) ;
2008-01-04 23:56:23 +03:00
if ( ! srv_send_smb ( smbd_server_fd ( ) ,
( char * ) req - > outbuf ,
2009-03-09 11:47:59 +03:00
true , req - > seqnum + 1 ,
2009-02-09 10:10:34 +03:00
IS_CONN_ENCRYPTED ( conn ) | | req - > encrypted ,
2009-02-17 07:45:45 +03:00
cur_pcd ) )
2008-01-04 23:56:23 +03:00
exit_server_cleanly ( " reply_echo: srv_send_smb failed. " ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " echo %d times \n " , smb_reverb ) ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:08:35 +04:00
TALLOC_FREE ( req - > outbuf ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBecho ) ;
2007-08-05 00:08:35 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printopen .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_printopen ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
1998-08-14 21:38:29 +04:00
files_struct * fsp ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
2008-10-19 17:30:12 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplopen ) ;
return ;
}
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-21 23:14:53 +03:00
status = file_new ( req , conn , & fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
END_PROFILE ( SMBsplopen ) ;
return ;
}
1998-08-14 21:38:29 +04:00
/* Open for exclusive use, write only. */
2009-11-18 01:55:02 +03:00
status = print_fsp_open ( req , conn , NULL , req - > vuid , fsp ) ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-04 14:46:30 +04:00
file_free ( req , fsp ) ;
2007-08-14 23:45:24 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 23:45:24 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
2008-10-19 17:30:12 +04:00
2000-04-10 17:05:23 +04:00
DEBUG ( 3 , ( " openprint fd=%d fnum=%d \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , fsp - > fnum ) ) ;
1998-08-01 02:39:15 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printclose .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-12-04 02:57:45 +03:00
2008-01-05 02:37:24 +03:00
void reply_printclose ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-14 23:45:24 +04:00
files_struct * fsp ;
2007-02-07 00:05:34 +03:00
NTSTATUS status ;
2007-08-14 23:45:24 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplclose ) ;
1996-05-04 11:50:46 +04:00
2008-03-26 20:33:38 +03:00
if ( req - > wct < 1 ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplclose ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:45:24 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:45:24 +04:00
END_PROFILE ( SMBsplclose ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRerror ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
2008-10-19 17:30:12 +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 ) ) ;
2008-10-19 17:30:12 +04:00
2008-10-09 18:27:49 +04:00
status = close_file ( req , fsp , NORMAL_CLOSE ) ;
1999-12-13 16:27:58 +03:00
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
1998-04-16 23:23:10 +04:00
2008-08-14 02:46:35 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printqueue .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_printqueue ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-14 23:45:24 +04:00
int max_count ;
int start_index ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplretq ) ;
1998-08-14 21:38:29 +04:00
2007-08-14 23:45:24 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplretq ) ;
return ;
}
2008-11-02 14:20:47 +03:00
max_count = SVAL ( req - > vwv + 0 , 0 ) ;
start_index = SVAL ( req - > vwv + 1 , 0 ) ;
2007-08-14 23:45:24 +04:00
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 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplretq ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1998-08-14 21:38:29 +04:00
2007-08-14 23:45:24 +04:00
reply_outbuf ( req , 2 , 3 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " printqueue start_index=%d max_count=%d \n " ,
start_index , max_count ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
{
print_queue_struct * queue = NULL ;
2001-12-29 12:52:24 +03:00
print_status_struct status ;
int count = print_queue_status ( SNUM ( conn ) , & queue , & status ) ;
1998-08-14 21:38:29 +04:00
int num_to_get = ABS ( max_count ) ;
int first = ( max_count > 0 ? start_index : start_index + max_count + 1 ) ;
int i ;
if ( first > = count )
num_to_get = 0 ;
else
num_to_get = MIN ( num_to_get , count - first ) ;
2008-10-19 17:30:12 +04:00
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
for ( i = first ; i < first + num_to_get ; i + + ) {
2007-08-14 23:45:24 +04:00
char blob [ 28 ] ;
char * p = blob ;
2005-11-05 07:21:55 +03:00
srv_put_dos_date2 ( p , 0 , queue [ i ] . time ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( p , 4 , ( queue [ i ] . status = = LPQ_PRINTING ? 2 : 3 ) ) ;
2000-04-16 10:22:31 +04:00
SSVAL ( p , 5 , queue [ i ] . job ) ;
1998-08-14 21:38:29 +04:00
SIVAL ( p , 7 , queue [ i ] . size ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( p , 11 , 0 ) ;
2007-08-14 23:45:24 +04:00
srvstr_push ( blob , req - > flags2 , p + 12 ,
2007-08-02 21:37:38 +04:00
queue [ i ] . fs_user , 16 , STR_ASCII ) ;
2007-08-14 23:45:24 +04:00
if ( message_push_blob (
& req - > outbuf ,
data_blob_const (
blob , sizeof ( blob ) ) ) = = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBsplretq ) ;
return ;
}
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( count > 0 ) {
2007-08-14 23:45:24 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , count ) ;
SSVAL ( req - > outbuf , smb_vwv1 ,
( max_count > 0 ? first + count : first - 1 ) ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , 28 * count ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-17 15:25:41 +04:00
SAFE_FREE ( queue ) ;
2008-10-19 17:30:12 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " %d entries returned in queue \n " , count ) ) ;
}
2008-10-19 17:30:12 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplretq ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printwrite .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_printwrite ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-12-04 02:57:45 +03:00
int numtowrite ;
2008-11-01 19:35:48 +03:00
const char * data ;
2007-08-14 23:45:24 +04:00
files_struct * fsp ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplwr ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:45:24 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:45:24 +04:00
END_PROFILE ( SMBsplwr ) ;
return ;
}
2002-12-04 02:57:45 +03:00
if ( ! CAN_PRINT ( conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-14 23:45:24 +04:00
END_PROFILE ( SMBsplwr ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-01 19:35:48 +03:00
numtowrite = SVAL ( req - > buf , 1 ) ;
2007-08-14 23:45:24 +04:00
2008-11-01 18:24:42 +03:00
if ( req - > buflen < numtowrite + 3 ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplwr ) ;
return ;
}
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 3 ;
2007-08-14 23:45:24 +04:00
2010-03-24 22:47:01 +03:00
if ( write_file ( req , fsp , data , ( SMB_OFF_T ) - 1 , numtowrite ) ! = numtowrite ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2000-10-06 07:21:49 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " printwrite fnum=%d num=%d \n " , fsp - > fnum , numtowrite ) ) ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2000-07-25 17:15:16 +04:00
/****************************************************************************
2001-08-31 02:20:02 +04:00
Reply to a mkdir .
2000-07-25 17:15:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-31 02:20:02 +04:00
2008-01-05 02:37:24 +03:00
void reply_mkdir ( struct smb_request * req )
2000-07-25 17:15:16 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_dname = NULL ;
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-03-15 04:19:58 +03:00
2001-08-31 02:20:02 +04:00
START_PROFILE ( SMBmkdir ) ;
2007-09-11 22:31:29 +04:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & directory , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2000-07-25 17:15:16 +04:00
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx , conn ,
2007-07-30 15:35:39 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
directory ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_dname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-30 15:35:39 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2002-08-17 19:27:10 +04:00
2009-06-10 21:37:57 +04:00
status = create_directory ( conn , req , smb_dname ) ;
2006-12-19 19:36:54 +03:00
2006-12-29 00:34:31 +03:00
DEBUG ( 5 , ( " create_directory returned %s \n " , nt_errstr ( status ) ) ) ;
2005-04-02 03:11:28 +04:00
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
2006-12-24 14:13:32 +03:00
if ( ! use_nt_status ( )
& & NT_STATUS_EQUAL ( status ,
NT_STATUS_OBJECT_NAME_COLLISION ) ) {
2006-07-11 22:01:26 +04:00
/*
* Yes , in the DOS error code case we get a
* ERRDOS : ERRnoaccess here . See BASE - SAMBA3ERROR
* samba4 torture test .
*/
status = NT_STATUS_DOS ( ERRDOS , ERRnoaccess ) ;
}
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2001-09-04 11:13:01 +04:00
2007-07-30 15:35:39 +04:00
reply_outbuf ( req , 0 , 0 ) ;
1998-08-01 02:39:15 +04:00
2009-06-10 21:37:57 +04:00
DEBUG ( 3 , ( " mkdir %s \n " , smb_dname - > base_name ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_dname ) ;
2001-08-31 02:20:02 +04:00
END_PROFILE ( SMBmkdir ) ;
2007-07-30 15:35:39 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
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
2008-01-05 02:37:24 +03:00
void reply_rmdir ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_dname = NULL ;
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2009-12-04 00:01:10 +03:00
files_struct * fsp = NULL ;
int info = 0 ;
2010-06-12 13:48:06 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBrmdir ) ;
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & directory , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx , conn ,
2007-07-30 18:07:29 +04:00
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
directory ,
2009-07-24 23:13:07 +04:00
0 ,
NULL ,
2009-07-21 21:28:28 +04:00
& smb_dname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-30 18:07:29 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-01-16 23:49:51 +03:00
2009-07-09 07:15:02 +04:00
if ( is_ntfs_stream_smb_fname ( smb_dname ) ) {
reply_nterror ( req , NT_STATUS_NOT_A_DIRECTORY ) ;
goto out ;
}
2009-12-04 00:01:10 +03:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
smb_dname , /* fname */
DELETE_ACCESS , /* access_mask */
( FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE ) ,
FILE_OPEN , /* create_disposition*/
FILE_DIRECTORY_FILE , /* create_options */
FILE_ATTRIBUTE_DIRECTORY , /* file_attributes */
0 , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2009-12-04 00:01:10 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
& info ) ; /* pinfo */
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( open_was_deferred ( req - > mid ) ) {
/* We have re-scheduled this call. */
goto out ;
}
reply_nterror ( req , status ) ;
goto out ;
}
status = can_set_delete_on_close ( fsp , FILE_ATTRIBUTE_DIRECTORY ) ;
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-12-04 00:01:10 +03:00
close_file ( req , fsp , ERROR_CLOSE ) ;
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-09-13 01:48:20 +04:00
2009-12-04 00:01:10 +03:00
if ( ! set_delete_on_close ( fsp , true , & conn - > server_info - > utok ) ) {
close_file ( req , fsp , ERROR_CLOSE ) ;
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
goto out ;
}
2010-01-13 03:50:40 +03:00
status = close_file ( req , fsp , NORMAL_CLOSE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
} else {
reply_outbuf ( req , 0 , 0 ) ;
}
2007-09-13 01:48:20 +04:00
2009-12-04 00:01:10 +03:00
dptr_closepath ( sconn , smb_dname - > base_name , req - > smbpid ) ;
2009-07-09 07:15:02 +04:00
DEBUG ( 3 , ( " rmdir %s \n " , smb_fname_str_dbg ( smb_dname ) ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_dname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-07-30 18:07:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2002-09-25 19:19:00 +04:00
Resolve wildcards in a filename rename .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2007-10-19 04:40:25 +04:00
static bool resolve_wildcards ( TALLOC_CTX * ctx ,
2007-09-08 00:57:01 +04:00
const char * name1 ,
const char * name2 ,
char * * pp_newname )
1996-05-04 11:50:46 +04:00
{
2007-09-08 00:57:01 +04:00
char * name2_copy = NULL ;
char * root1 = NULL ;
char * root2 = NULL ;
char * ext1 = NULL ;
char * ext2 = NULL ;
2003-04-12 03:48:24 +04:00
char * p , * p2 , * pname1 , * pname2 ;
2008-10-19 17:30:12 +04:00
2007-09-08 00:57:01 +04:00
name2_copy = talloc_strdup ( ctx , name2 ) ;
if ( ! name2_copy ) {
return False ;
}
2003-04-12 03:48:24 +04:00
pname1 = strrchr_m ( name1 , ' / ' ) ;
2007-09-08 00:57:01 +04:00
pname2 = strrchr_m ( name2_copy , ' / ' ) ;
2002-12-04 02:57:45 +03:00
2007-09-08 00:57:01 +04:00
if ( ! pname1 | | ! pname2 ) {
return False ;
}
2008-10-19 17:30:12 +04:00
2007-09-08 00:57:01 +04:00
/* Truncate the copy of name2 at the last '/' */
* pname2 = ' \0 ' ;
/* Now go past the '/' */
pname1 + + ;
pname2 + + ;
root1 = talloc_strdup ( ctx , pname1 ) ;
root2 = talloc_strdup ( ctx , pname2 ) ;
if ( ! root1 | | ! root2 ) {
return False ;
}
2002-12-04 02:57:45 +03:00
p = strrchr_m ( root1 , ' . ' ) ;
if ( p ) {
* p = 0 ;
2007-09-08 00:57:01 +04:00
ext1 = talloc_strdup ( ctx , p + 1 ) ;
2002-12-04 02:57:45 +03:00
} else {
2007-09-08 00:57:01 +04:00
ext1 = talloc_strdup ( ctx , " " ) ;
2002-12-04 02:57:45 +03:00
}
p = strrchr_m ( root2 , ' . ' ) ;
if ( p ) {
* p = 0 ;
2007-09-08 00:57:01 +04:00
ext2 = talloc_strdup ( ctx , p + 1 ) ;
2002-12-04 02:57:45 +03:00
} else {
2007-09-08 00:57:01 +04:00
ext2 = talloc_strdup ( ctx , " " ) ;
}
if ( ! ext1 | | ! ext2 ) {
return False ;
2002-12-04 02:57:45 +03:00
}
p = root1 ;
p2 = root2 ;
while ( * p2 ) {
if ( * p2 = = ' ? ' ) {
2007-09-08 00:57:01 +04:00
/* Hmmm. Should this be mb-aware ? */
2002-12-04 02:57:45 +03:00
* p2 = * p ;
p2 + + ;
2004-04-03 05:21:13 +04:00
} else if ( * p2 = = ' * ' ) {
2007-09-08 00:57:01 +04:00
* p2 = ' \0 ' ;
root2 = talloc_asprintf ( ctx , " %s%s " ,
root2 ,
p ) ;
if ( ! root2 ) {
return False ;
}
2004-04-03 05:21:13 +04:00
break ;
2002-12-04 02:57:45 +03:00
} else {
p2 + + ;
}
2007-09-08 00:57:01 +04:00
if ( * p ) {
2002-12-04 02:57:45 +03:00
p + + ;
2007-09-08 00:57:01 +04:00
}
2002-12-04 02:57:45 +03:00
}
p = ext1 ;
p2 = ext2 ;
while ( * p2 ) {
if ( * p2 = = ' ? ' ) {
2007-09-08 00:57:01 +04:00
/* Hmmm. Should this be mb-aware ? */
2002-12-04 02:57:45 +03:00
* p2 = * p ;
p2 + + ;
2004-04-03 05:21:13 +04:00
} else if ( * p2 = = ' * ' ) {
2007-09-08 00:57:01 +04:00
* p2 = ' \0 ' ;
ext2 = talloc_asprintf ( ctx , " %s%s " ,
ext2 ,
p ) ;
if ( ! ext2 ) {
return False ;
}
2004-04-03 05:21:13 +04:00
break ;
2002-12-04 02:57:45 +03:00
} else {
p2 + + ;
}
2007-09-08 00:57:01 +04:00
if ( * p ) {
2002-12-04 02:57:45 +03:00
p + + ;
2007-09-08 00:57:01 +04:00
}
2002-12-04 02:57:45 +03:00
}
2007-09-08 00:57:01 +04:00
if ( * ext2 ) {
* pp_newname = talloc_asprintf ( ctx , " %s/%s.%s " ,
name2_copy ,
root2 ,
ext2 ) ;
2003-04-14 03:45:35 +04:00
} else {
2007-09-08 00:57:01 +04:00
* pp_newname = talloc_asprintf ( ctx , " %s/%s " ,
name2_copy ,
root2 ) ;
2002-12-04 02:57:45 +03:00
}
2007-09-08 00:57:01 +04:00
if ( ! * pp_newname ) {
return False ;
}
return True ;
1996-05-04 11:50:46 +04:00
}
2003-08-16 06:34:03 +04:00
/****************************************************************************
2005-12-13 21:11:50 +03:00
Ensure open files have their names updated . Updated to notify other smbd ' s
asynchronously .
2003-08-16 06:34:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-14 16:03:46 +04:00
static void rename_open_files ( connection_struct * conn ,
struct share_mode_lock * lck ,
2009-07-01 04:04:38 +04:00
const struct smb_filename * smb_fname_dst )
2003-08-16 06:34:03 +04:00
{
files_struct * fsp ;
2007-10-19 04:40:25 +04:00
bool did_rename = False ;
2009-07-01 04:04:38 +04:00
NTSTATUS status ;
2007-06-14 16:03:46 +04:00
for ( fsp = file_find_di_first ( lck - > id ) ; fsp ;
fsp = file_find_di_next ( fsp ) ) {
2005-12-14 20:46:29 +03:00
/* fsp_name is a relative path under the fsp. To change this for other
sharepaths we need to manipulate relative paths . */
/* TODO - create the absolute path and manipulate the newname
relative to the sharepath . */
2008-03-11 23:38:25 +03:00
if ( ! strequal ( fsp - > conn - > connectpath , conn - > connectpath ) ) {
2005-12-14 20:46:29 +03:00
continue ;
}
2009-07-01 04:04:38 +04:00
DEBUG ( 10 , ( " rename_open_files: renaming file fnum %d "
" (file_id %s) from %s -> %s \n " , fsp - > fnum ,
2009-07-11 01:50:37 +04:00
file_id_string_tos ( & fsp - > file_id ) , fsp_str_dbg ( fsp ) ,
2009-07-01 04:04:38 +04:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2009-07-09 03:22:44 +04:00
2009-07-11 01:50:37 +04:00
status = fsp_set_smb_fname ( fsp , smb_fname_dst ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
did_rename = True ;
2009-07-09 03:22:44 +04:00
}
2003-08-16 06:34:03 +04:00
}
2005-12-13 21:11:50 +03:00
if ( ! did_rename ) {
2009-07-01 04:04:38 +04:00
DEBUG ( 10 , ( " rename_open_files: no open files on file_id %s "
" for %s \n " , file_id_string_tos ( & lck - > id ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
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 ,
2009-07-09 03:22:44 +04:00
smb_fname_dst ) ;
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 > .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-01 04:04:38 +04:00
static bool rename_path_prefix_equal ( const struct smb_filename * smb_fname_src ,
const struct smb_filename * smb_fname_dst )
2005-09-27 21:42:11 +04:00
{
2009-07-01 04:04:38 +04:00
const char * psrc = smb_fname_src - > base_name ;
const char * pdst = smb_fname_dst - > base_name ;
2005-09-27 21:42:11 +04:00
size_t slen ;
if ( psrc [ 0 ] = = ' . ' & & psrc [ 1 ] = = ' / ' ) {
psrc + = 2 ;
}
if ( pdst [ 0 ] = = ' . ' & & pdst [ 1 ] = = ' / ' ) {
pdst + = 2 ;
}
if ( ( slen = strlen ( psrc ) ) > strlen ( pdst ) ) {
return False ;
}
return ( ( memcmp ( psrc , pdst , slen ) = = 0 ) & & pdst [ slen ] = = ' / ' ) ;
}
2007-06-14 19:50:47 +04:00
/*
* Do the notify calls from a rename
*/
2007-10-19 04:40:25 +04:00
static void notify_rename ( connection_struct * conn , bool is_dir ,
2009-07-01 04:04:38 +04:00
const struct smb_filename * smb_fname_src ,
const struct smb_filename * smb_fname_dst )
2007-06-14 19:50:47 +04:00
{
2009-07-01 04:04:38 +04:00
char * parent_dir_src = NULL ;
char * parent_dir_dst = NULL ;
2007-06-14 19:50:47 +04:00
uint32 mask ;
mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME ;
2009-07-01 04:04:38 +04:00
if ( ! parent_dirname ( talloc_tos ( ) , smb_fname_src - > base_name ,
& parent_dir_src , NULL ) | |
! parent_dirname ( talloc_tos ( ) , smb_fname_dst - > base_name ,
& parent_dir_dst , NULL ) ) {
goto out ;
2007-06-14 19:50:47 +04:00
}
2009-07-01 04:04:38 +04:00
if ( strcmp ( parent_dir_src , parent_dir_dst ) = = 0 ) {
2009-07-21 22:35:17 +04:00
notify_fname ( conn , NOTIFY_ACTION_OLD_NAME , mask ,
smb_fname_src - > base_name ) ;
notify_fname ( conn , NOTIFY_ACTION_NEW_NAME , mask ,
smb_fname_dst - > base_name ) ;
2007-06-14 19:50:47 +04:00
}
else {
2009-07-21 22:35:17 +04:00
notify_fname ( conn , NOTIFY_ACTION_REMOVED , mask ,
smb_fname_src - > base_name ) ;
notify_fname ( conn , NOTIFY_ACTION_ADDED , mask ,
smb_fname_dst - > base_name ) ;
2007-06-14 19:50:47 +04:00
}
/* 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 ,
2009-07-21 22:35:17 +04:00
smb_fname_dst - > base_name ) ;
2007-06-14 19:50:47 +04:00
}
2009-07-01 04:04:38 +04:00
out :
TALLOC_FREE ( parent_dir_src ) ;
TALLOC_FREE ( parent_dir_dst ) ;
2007-06-14 19:50:47 +04:00
}
2003-08-16 06:34:03 +04:00
/****************************************************************************
Rename an open file - given an fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-08 00:57:01 +04:00
NTSTATUS rename_internals_fsp ( connection_struct * conn ,
files_struct * fsp ,
2009-07-01 04:04:38 +04:00
const struct smb_filename * smb_fname_dst_in ,
2007-09-08 00:57:01 +04:00
uint32 attrs ,
2007-10-19 04:40:25 +04:00
bool replace_if_exists )
2003-08-16 06:34:03 +04:00
{
2007-09-08 00:57:01 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2009-07-01 04:04:38 +04:00
struct smb_filename * smb_fname_dst = NULL ;
2007-01-13 02:47:16 +03:00
NTSTATUS status = NT_STATUS_OK ;
2005-12-14 20:46:29 +03:00
struct share_mode_lock * lck = NULL ;
2009-01-04 21:45:34 +03:00
bool dst_exists , old_is_stream , new_is_stream ;
2003-08-16 06:34:03 +04:00
2009-07-01 04:04:38 +04:00
status = check_name ( conn , smb_fname_dst_in - > base_name ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-09-08 00:57:01 +04:00
2009-10-03 00:45:38 +04:00
/* Make a copy of the dst smb_fname structs */
2009-07-01 04:04:38 +04:00
2009-07-11 01:50:37 +04:00
status = copy_smb_filename ( ctx , smb_fname_dst_in , & smb_fname_dst ) ;
2009-07-01 04:04:38 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
/* Ensure the dst smb_fname contains a '/' */
if ( strrchr_m ( smb_fname_dst - > base_name , ' / ' ) = = 0 ) {
char * tmp ;
tmp = talloc_asprintf ( smb_fname_dst , " ./%s " ,
smb_fname_dst - > base_name ) ;
if ( ! tmp ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
2007-09-08 00:57:01 +04:00
}
2009-07-01 04:04:38 +04:00
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = tmp ;
2003-08-16 06:34:03 +04:00
}
/*
* Check for special case with case preserving and not
* case sensitive . If the old last component differs from the original
* last component only by case , then we should allow
* the rename ( user is trying to change the case of the
* filename ) .
*/
2004-05-07 22:37:47 +04:00
if ( ( conn - > case_sensitive = = False ) & & ( conn - > case_preserve = = True ) & &
2009-10-03 00:45:38 +04:00
strequal ( fsp - > fsp_name - > base_name , smb_fname_dst - > base_name ) & &
strequal ( fsp - > fsp_name - > stream_name , smb_fname_dst - > stream_name ) ) {
2009-07-01 04:04:38 +04:00
char * last_slash ;
char * fname_dst_lcomp_base_mod = NULL ;
struct smb_filename * smb_fname_orig_lcomp = NULL ;
/*
* Get the last component of the destination name . Note that
* we guarantee that destination name contains a ' / ' character
* above .
*/
last_slash = strrchr_m ( smb_fname_dst - > base_name , ' / ' ) ;
fname_dst_lcomp_base_mod = talloc_strdup ( ctx , last_slash + 1 ) ;
if ( ! fname_dst_lcomp_base_mod ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2003-08-16 06:34:03 +04:00
/*
2009-07-01 04:04:38 +04:00
* Create an smb_filename struct using the original last
* component of the destination .
2003-08-16 06:34:03 +04:00
*/
2009-07-01 04:04:38 +04:00
status = create_synthetic_smb_fname_split ( ctx ,
smb_fname_dst - > original_lcomp , NULL ,
& smb_fname_orig_lcomp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( fname_dst_lcomp_base_mod ) ;
goto out ;
2007-09-08 00:57:01 +04:00
}
2009-07-01 04:04:38 +04:00
/* If the base names only differ by case, use original. */
if ( ! strcsequal ( fname_dst_lcomp_base_mod ,
smb_fname_orig_lcomp - > base_name ) ) {
char * tmp ;
2003-08-16 06:34:03 +04:00
/*
2009-07-01 04:04:38 +04:00
* Replace the modified last component with the
* original .
2003-08-16 06:34:03 +04:00
*/
2009-07-01 04:04:38 +04:00
* last_slash = ' \0 ' ; /* Truncate at the '/' */
tmp = talloc_asprintf ( smb_fname_dst ,
2007-09-08 00:57:01 +04:00
" %s/%s " ,
2009-07-01 04:04:38 +04:00
smb_fname_dst - > base_name ,
smb_fname_orig_lcomp - > base_name ) ;
if ( tmp = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
TALLOC_FREE ( fname_dst_lcomp_base_mod ) ;
TALLOC_FREE ( smb_fname_orig_lcomp ) ;
goto out ;
}
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = tmp ;
2003-08-16 06:34:03 +04:00
}
2009-07-01 04:04:38 +04:00
/* If the stream_names only differ by case, use original. */
if ( ! strcsequal ( smb_fname_dst - > stream_name ,
smb_fname_orig_lcomp - > stream_name ) ) {
char * tmp = NULL ;
/* Use the original stream. */
tmp = talloc_strdup ( smb_fname_dst ,
smb_fname_orig_lcomp - > stream_name ) ;
if ( tmp = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
TALLOC_FREE ( fname_dst_lcomp_base_mod ) ;
TALLOC_FREE ( smb_fname_orig_lcomp ) ;
goto out ;
}
TALLOC_FREE ( smb_fname_dst - > stream_name ) ;
smb_fname_dst - > stream_name = tmp ;
}
TALLOC_FREE ( fname_dst_lcomp_base_mod ) ;
TALLOC_FREE ( smb_fname_orig_lcomp ) ;
2003-08-16 06:34:03 +04:00
}
/*
* If the src and dest names are identical - including case ,
* don ' t do the rename , just return success .
*/
2009-10-03 00:45:38 +04:00
if ( strcsequal ( fsp - > fsp_name - > base_name , smb_fname_dst - > base_name ) & &
strcsequal ( fsp - > fsp_name - > stream_name ,
2009-07-01 04:04:38 +04:00
smb_fname_dst - > stream_name ) ) {
DEBUG ( 3 , ( " rename_internals_fsp: identical names in rename %s "
" - returning success \n " ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
status = NT_STATUS_OK ;
goto out ;
2003-08-16 06:34:03 +04:00
}
2009-10-03 00:45:38 +04:00
old_is_stream = is_ntfs_stream_smb_fname ( fsp - > fsp_name ) ;
2009-07-01 04:04:38 +04:00
new_is_stream = is_ntfs_stream_smb_fname ( smb_fname_dst ) ;
2009-01-04 21:45:34 +03:00
/* Return the correct error code if both names aren't streams. */
if ( ! old_is_stream & & new_is_stream ) {
2009-07-01 04:04:38 +04:00
status = NT_STATUS_OBJECT_NAME_INVALID ;
goto out ;
2009-01-04 21:45:34 +03:00
}
if ( old_is_stream & & ! new_is_stream ) {
2009-07-01 04:04:38 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
2009-01-04 21:45:34 +03:00
}
2009-07-01 04:04:38 +04:00
dst_exists = SMB_VFS_STAT ( conn , smb_fname_dst ) = = 0 ;
2007-06-14 18:45:37 +04:00
if ( ! replace_if_exists & & dst_exists ) {
2009-07-01 04:04:38 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: dest exists doing rename "
2009-10-03 00:45:38 +04:00
" %s -> %s \n " , smb_fname_str_dbg ( fsp - > fsp_name ) ,
2009-07-01 04:04:38 +04:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
status = NT_STATUS_OBJECT_NAME_COLLISION ;
goto out ;
2003-08-16 06:34:03 +04:00
}
2007-07-17 06:06:38 +04:00
if ( dst_exists ) {
2009-07-01 04:04:38 +04:00
struct file_id fileid = vfs_file_id_from_sbuf ( conn ,
& smb_fname_dst - > st ) ;
2007-08-02 12:53:24 +04:00
files_struct * dst_fsp = file_find_di_first ( fileid ) ;
2009-01-04 21:45:34 +03:00
/* The file can be open when renaming a stream */
if ( dst_fsp & & ! new_is_stream ) {
2007-07-17 06:06:38 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: Target file open \n " ) ) ;
2009-07-01 04:04:38 +04:00
status = NT_STATUS_ACCESS_DENIED ;
goto out ;
2007-07-17 06:06:38 +04:00
}
2007-06-14 18:45:37 +04:00
}
2007-05-24 01:32:10 +04:00
/* Ensure we have a valid stat struct for the source. */
2009-10-03 00:45:38 +04:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
2007-05-24 01:32:10 +04:00
}
2003-08-16 06:34:03 +04:00
2009-11-18 03:06:08 +03:00
status = can_rename ( conn , fsp , attrs ) ;
2007-05-24 01:32:10 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-07-01 04:04:38 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: Error %s rename %s -> %s \n " ,
2009-10-03 00:45:38 +04:00
nt_errstr ( status ) , smb_fname_str_dbg ( fsp - > fsp_name ) ,
2009-07-01 04:04:38 +04:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2007-01-13 02:47:16 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) )
status = NT_STATUS_ACCESS_DENIED ;
2009-07-01 04:04:38 +04:00
goto out ;
2003-08-16 06:34:03 +04:00
}
2009-10-03 00:45:38 +04:00
if ( rename_path_prefix_equal ( fsp - > fsp_name , smb_fname_dst ) ) {
2009-07-01 04:04:38 +04:00
status = NT_STATUS_ACCESS_DENIED ;
2005-09-27 21:42:11 +04:00
}
2008-03-12 17:32:47 +03:00
lck = get_share_mode_lock ( talloc_tos ( ) , fsp - > file_id , NULL , NULL ,
NULL ) ;
2005-12-14 20:46:29 +03:00
2007-06-14 16:03:46 +04:00
/*
* We have the file open ourselves , so not being able to get the
* corresponding share mode lock is a fatal error .
*/
SMB_ASSERT ( lck ! = NULL ) ;
2009-10-03 00:45:38 +04:00
if ( SMB_VFS_RENAME ( conn , fsp - > fsp_name , smb_fname_dst ) = = 0 ) {
2007-05-24 01:32:10 +04:00
uint32 create_options = fsp - > fh - > private_options ;
2009-07-01 04:04:38 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: succeeded doing rename on "
2009-10-03 00:45:38 +04:00
" %s -> %s \n " , smb_fname_str_dbg ( fsp - > fsp_name ) ,
2009-07-01 04:04:38 +04:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2007-05-24 01:32:10 +04:00
2010-03-31 09:16:37 +04:00
if ( lp_map_archive ( SNUM ( conn ) ) | |
lp_store_dos_attributes ( SNUM ( conn ) ) ) {
/* We must set the archive bit on the newly
renamed file . */
if ( SMB_VFS_STAT ( conn , smb_fname_dst ) = = 0 ) {
uint32_t old_dosmode = dos_mode ( conn ,
smb_fname_dst ) ;
file_set_dosmode ( conn ,
smb_fname_dst ,
old_dosmode | FILE_ATTRIBUTE_ARCHIVE ,
NULL ,
true ) ;
}
}
2009-10-03 00:45:38 +04:00
notify_rename ( conn , fsp - > is_directory , fsp - > fsp_name ,
2009-07-01 04:04:38 +04:00
smb_fname_dst ) ;
2007-06-14 19:50:47 +04:00
2009-07-01 04:04:38 +04:00
rename_open_files ( conn , lck , smb_fname_dst ) ;
2008-10-01 00:26:41 +04:00
2007-05-24 01:32:10 +04:00
/*
* A rename acts as a new file create w . r . t . allowing an initial delete
* on close , probably because in Windows there is a new handle to the
* new file . If initial delete on close was requested but not
* originally set , we need to set it here . This is probably not 100 % correct ,
* but will work for the CIFSFS client which in non - posix mode
* depends on these semantics . JRA .
*/
if ( create_options & FILE_DELETE_ON_CLOSE ) {
2009-12-03 05:06:40 +03:00
status = can_set_delete_on_close ( fsp , 0 ) ;
2007-05-24 01:32:10 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
/* Note that here we set the *inital* delete on close flag,
* not the regular one . The magic gets handled in close . */
fsp - > initial_delete_on_close = True ;
}
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2009-07-01 04:04:38 +04:00
status = NT_STATUS_OK ;
goto out ;
2003-08-16 06:34:03 +04:00
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2005-12-14 20:46:29 +03:00
2005-12-13 21:11:50 +03:00
if ( errno = = ENOTDIR | | errno = = EISDIR ) {
2007-01-13 02:47:16 +03:00
status = NT_STATUS_OBJECT_NAME_COLLISION ;
2005-12-13 21:11:50 +03:00
} else {
2007-01-13 02:47:16 +03:00
status = map_nt_error_from_unix ( errno ) ;
2005-12-13 21:11:50 +03:00
}
2007-09-08 00:57:01 +04:00
2009-07-01 04:04:38 +04:00
DEBUG ( 3 , ( " rename_internals_fsp: Error %s rename %s -> %s \n " ,
2009-10-03 00:45:38 +04:00
nt_errstr ( status ) , smb_fname_str_dbg ( fsp - > fsp_name ) ,
2009-07-01 04:04:38 +04:00
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
out :
TALLOC_FREE ( smb_fname_dst ) ;
2003-08-16 06:34:03 +04:00
2007-01-13 02:47:16 +03:00
return status ;
2003-08-16 06:34:03 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1998-07-11 04:28:34 +04:00
The guts of the rename command , split out so it may be called by the NT SMB
2007-09-13 01:48:20 +04:00
code .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-05 00:11:35 +03:00
2007-09-13 01:48:20 +04:00
NTSTATUS rename_internals ( TALLOC_CTX * ctx ,
connection_struct * conn ,
struct smb_request * req ,
2009-07-24 22:39:56 +04:00
struct smb_filename * smb_fname_src ,
struct smb_filename * smb_fname_dst ,
2007-09-13 01:48:20 +04:00
uint32 attrs ,
2007-10-19 04:40:25 +04:00
bool replace_if_exists ,
bool src_has_wild ,
2008-03-11 23:27:33 +03:00
bool dest_has_wild ,
uint32_t access_mask )
1996-05-04 11:50:46 +04:00
{
2009-06-11 06:49:31 +04:00
char * fname_src_dir = NULL ;
char * fname_src_mask = NULL ;
1998-08-14 21:38:29 +04:00
int count = 0 ;
2007-01-13 02:47:16 +03:00
NTSTATUS status = NT_STATUS_OK ;
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 ;
2009-11-16 11:49:23 +03:00
const char * dname = NULL ;
char * talloced = 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
long offset = 0 ;
2008-11-21 05:55:24 +03:00
int create_options = 0 ;
2009-02-05 03:33:52 +03:00
bool posix_pathnames = lp_posix_pathnames ( ) ;
1998-08-14 21:38:29 +04:00
/*
* Split the old name into directory and last component
2007-09-13 01:48:20 +04:00
* strings . Note that unix_convert may have stripped off a
* leading . / from both name and newname if the rename is
1998-08-14 21:38:29 +04:00
* at the root of the share . We need to make sure either both
* name and newname contain a / character or neither of them do
* as this is checked in resolve_wildcards ( ) .
*/
2004-02-25 04:35:14 +03:00
2009-06-11 06:49:31 +04:00
/* Split up the directory from the filename/mask. */
status = split_fname_dir_mask ( ctx , smb_fname_src - > base_name ,
& fname_src_dir , & fname_src_mask ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
1998-08-14 21:38:29 +04:00
}
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 > .
*/
2009-06-11 06:49:31 +04:00
if ( ! VALID_STAT ( smb_fname_src - > st ) & &
mangle_is_mangled ( fname_src_mask , conn - > params ) ) {
2007-09-08 00:57:01 +04:00
char * new_mask = NULL ;
2009-06-11 06:49:31 +04:00
mangle_lookup_name_from_8_3 ( ctx , fname_src_mask , & new_mask ,
conn - > params ) ;
2007-09-08 00:57:01 +04:00
if ( new_mask ) {
2009-06-11 06:49:31 +04:00
TALLOC_FREE ( fname_src_mask ) ;
fname_src_mask = new_mask ;
2007-09-08 00:57:01 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
1997-02-18 20:20:14 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! src_has_wild ) {
2007-06-16 14:02:51 +04:00
files_struct * fsp ;
1998-08-14 21:38:29 +04:00
/*
2009-07-01 04:04:38 +04:00
* Only one file needs to be renamed . Append the mask back
2009-06-11 06:49:31 +04:00
* onto the directory .
1998-08-14 21:38:29 +04:00
*/
2009-06-11 06:49:31 +04:00
TALLOC_FREE ( smb_fname_src - > base_name ) ;
smb_fname_src - > base_name = talloc_asprintf ( smb_fname_src ,
" %s/%s " ,
fname_src_dir ,
fname_src_mask ) ;
if ( ! smb_fname_src - > base_name ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
2007-09-13 01:48:20 +04:00
}
2007-09-08 00:57:01 +04:00
2009-06-11 06:49:31 +04:00
/* Ensure dst fname contains a '/' also */
if ( strrchr_m ( smb_fname_dst - > base_name , ' / ' ) = = 0 ) {
char * tmp ;
tmp = talloc_asprintf ( smb_fname_dst , " ./%s " ,
smb_fname_dst - > base_name ) ;
if ( ! tmp ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
2007-09-08 00:57:01 +04:00
}
2009-06-11 06:49:31 +04:00
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = tmp ;
1998-08-14 21:38:29 +04:00
}
2007-09-08 00:57:01 +04:00
2007-01-31 15:55:39 +03:00
DEBUG ( 3 , ( " rename_internals: case_sensitive = %d, "
" case_preserve = %d, short case preserve = %d, "
" directory = %s, newname = %s, "
2009-05-15 03:03:18 +04:00
" last_component_dest = %s \n " ,
2007-01-31 15:55:39 +03:00
conn - > case_sensitive , conn - > case_preserve ,
2009-06-12 23:54:11 +04:00
conn - > short_case_preserve ,
smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ,
2009-06-11 06:49:31 +04:00
smb_fname_dst - > original_lcomp ) ) ;
1998-08-14 21:38:29 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
/* The dest name still may have wildcards. */
if ( dest_has_wild ) {
2009-06-11 06:49:31 +04:00
char * fname_dst_mod = NULL ;
if ( ! resolve_wildcards ( smb_fname_dst ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ,
& fname_dst_mod ) ) {
2007-09-13 01:48:20 +04:00
DEBUG ( 6 , ( " rename_internals: resolve_wildcards "
2009-06-11 06:49:31 +04:00
" %s %s failed \n " ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
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
}
2009-06-11 06:49:31 +04:00
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = fname_dst_mod ;
}
ZERO_STRUCT ( smb_fname_src - > st ) ;
2009-02-05 03:33:52 +03:00
if ( posix_pathnames ) {
2009-06-23 02:26:56 +04:00
SMB_VFS_LSTAT ( conn , smb_fname_src ) ;
2009-02-05 03:33:52 +03:00
} else {
2009-06-23 02:26:56 +04:00
SMB_VFS_STAT ( conn , smb_fname_src ) ;
2009-02-05 03:33:52 +03:00
}
2007-06-16 14:02:51 +04:00
2009-06-11 06:49:31 +04:00
if ( S_ISDIR ( smb_fname_src - > st . st_ex_mode ) ) {
2008-11-21 05:55:24 +03:00
create_options | = FILE_DIRECTORY_FILE ;
}
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname_src , /* fname */
2008-11-21 05:55:24 +03:00
access_mask , /* access_mask */
( FILE_SHARE_READ | /* share_access */
FILE_SHARE_WRITE ) ,
FILE_OPEN , /* create_disposition*/
create_options , /* create_options */
2009-02-05 03:33:52 +03:00
posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS | 0777 : 0 , /* file_attributes */
2008-11-21 05:55:24 +03:00
0 , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-11-21 05:55:24 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2009-06-12 23:54:11 +04:00
NULL ) ; /* pinfo */
2002-01-05 00:11:35 +03:00
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-06-16 14:02:51 +04:00
DEBUG ( 3 , ( " Could not open rename source %s: %s \n " ,
2009-06-12 23:54:11 +04:00
smb_fname_str_dbg ( smb_fname_src ) ,
nt_errstr ( status ) ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-01-05 00:11:35 +03:00
}
2009-07-01 04:04:38 +04:00
status = rename_internals_fsp ( conn , fsp , smb_fname_dst ,
2007-08-19 23:57:55 +04:00
attrs , replace_if_exists ) ;
2005-12-14 20:46:29 +03:00
2008-10-09 18:27:49 +04:00
close_file ( req , fsp , NORMAL_CLOSE ) ;
2002-01-05 00:11:35 +03:00
2007-06-16 14:02:51 +04:00
DEBUG ( 3 , ( " rename_internals: Error %s rename %s -> %s \n " ,
2009-06-12 23:54:11 +04:00
nt_errstr ( status ) , smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2002-01-05 00:11:35 +03:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
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 .
*/
2009-06-11 06:49:31 +04:00
if ( strequal ( fname_src_mask , " ????????.??? " ) ) {
TALLOC_FREE ( fname_src_mask ) ;
fname_src_mask = talloc_strdup ( ctx , " * " ) ;
if ( ! fname_src_mask ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
2009-06-11 06:49:31 +04:00
status = check_name ( conn , fname_src_dir ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
2009-06-11 06:49:31 +04:00
dir_hnd = OpenDir ( talloc_tos ( ) , conn , fname_src_dir , fname_src_mask ,
attrs ) ;
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 ( dir_hnd = = NULL ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = map_nt_error_from_unix ( errno ) ;
goto out ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
status = NT_STATUS_NO_SUCH_FILE ;
/*
* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
* - gentest fix . JRA
*/
2007-09-13 01:48:20 +04:00
2009-11-16 11:49:23 +03:00
while ( ( dname = ReadDirName ( dir_hnd , & offset , & smb_fname_src - > st ,
& talloced ) ) ) {
2007-09-13 01:48:20 +04:00
files_struct * fsp = NULL ;
char * destname = NULL ;
2007-10-19 04:40:25 +04:00
bool sysdir_entry = False ;
2000-03-29 11:44:23 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
/* Quick check for "." and ".." */
2007-09-13 01:48:20 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
if ( attrs & aDIR ) {
sysdir_entry = True ;
} else {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-09-13 01:48:20 +04:00
continue ;
2007-01-17 05:09:37 +03:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2004-02-25 03:48:35 +03:00
2009-06-11 06:49:31 +04:00
if ( ! is_visible_file ( conn , fname_src_dir , dname ,
& smb_fname_src - > st , false ) ) {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
continue ;
}
2005-02-01 21:33:50 +03:00
2009-11-23 18:34:07 +03:00
if ( ! mask_match ( dname , fname_src_mask , conn - > case_sensitive ) ) {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( sysdir_entry ) {
status = NT_STATUS_OBJECT_NAME_INVALID ;
break ;
}
2004-03-03 23:55:59 +03:00
2009-06-11 06:49:31 +04:00
TALLOC_FREE ( smb_fname_src - > base_name ) ;
smb_fname_src - > base_name = talloc_asprintf ( smb_fname_src ,
" %s/%s " ,
fname_src_dir ,
dname ) ;
if ( ! smb_fname_src - > base_name ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
2007-09-13 01:48:20 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
2009-06-11 06:49:31 +04:00
if ( ! resolve_wildcards ( ctx , smb_fname_src - > base_name ,
smb_fname_dst - > base_name ,
& destname ) ) {
2007-09-13 01:48:20 +04:00
DEBUG ( 6 , ( " resolve_wildcards %s %s failed \n " ,
2009-06-11 06:49:31 +04:00
smb_fname_src - > base_name , destname ) ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
if ( ! destname ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
2007-09-13 01:48:20 +04:00
}
2009-06-11 06:49:31 +04:00
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = destname ;
ZERO_STRUCT ( smb_fname_src - > st ) ;
2009-02-05 03:33:52 +03:00
if ( posix_pathnames ) {
2009-06-23 02:26:56 +04:00
SMB_VFS_LSTAT ( conn , smb_fname_src ) ;
2009-02-05 03:33:52 +03:00
} else {
2009-06-23 02:26:56 +04:00
SMB_VFS_STAT ( conn , smb_fname_src ) ;
2009-02-05 03:33:52 +03:00
}
2007-06-16 14:02:51 +04:00
2008-11-21 05:55:24 +03:00
create_options = 0 ;
2009-06-11 06:49:31 +04:00
if ( S_ISDIR ( smb_fname_src - > st . st_ex_mode ) ) {
2008-11-21 05:55:24 +03:00
create_options | = FILE_DIRECTORY_FILE ;
}
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname_src , /* fname */
2008-11-21 05:55:24 +03:00
access_mask , /* access_mask */
( FILE_SHARE_READ | /* share_access */
FILE_SHARE_WRITE ) ,
FILE_OPEN , /* create_disposition*/
create_options , /* create_options */
2009-02-05 03:33:52 +03:00
posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS | 0777 : 0 , /* file_attributes */
2008-11-21 05:55:24 +03:00
0 , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-11-21 05:55:24 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2009-06-12 23:54:11 +04:00
NULL ) ; /* pinfo */
2007-06-16 14:02:51 +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 ( ! NT_STATUS_IS_OK ( status ) ) {
2008-11-21 05:55:24 +03:00
DEBUG ( 3 , ( " rename_internals: SMB_VFS_CREATE_FILE "
2007-06-16 14:02:51 +04:00
" returned %s rename %s -> %s \n " ,
2009-06-12 23:54:11 +04:00
nt_errstr ( status ) ,
smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2007-06-18 16:22:42 +04:00
break ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2004-04-02 23:51:27 +04:00
2009-07-01 04:04:38 +04:00
smb_fname_dst - > original_lcomp = talloc_strdup ( smb_fname_dst ,
dname ) ;
if ( ! smb_fname_dst - > original_lcomp ) {
status = NT_STATUS_NO_MEMORY ;
2009-06-12 23:54:11 +04:00
goto out ;
}
2009-07-01 04:04:38 +04:00
status = rename_internals_fsp ( conn , fsp , smb_fname_dst ,
2007-08-19 23:57:55 +04:00
attrs , replace_if_exists ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
2008-10-09 18:27:49 +04:00
close_file ( req , fsp , NORMAL_CLOSE ) ;
2007-06-16 14:02:51 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " rename_internals_fsp returned %s for "
" rename %s -> %s \n " , nt_errstr ( status ) ,
2009-06-12 23:54:11 +04:00
smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2007-06-18 16:22:42 +04:00
break ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2005-09-27 21:42:11 +04:00
2007-06-16 14:02:51 +04:00
count + + ;
2005-12-14 20:46:29 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
DEBUG ( 3 , ( " rename_internals: doing rename on %s -> "
2009-06-12 23:54:11 +04:00
" %s \n " , smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_src ) ) ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-01-17 05:09:37 +03:00
}
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2007-01-13 02:47:16 +03:00
2008-08-10 04:43:36 +04:00
if ( count = = 0 & & NT_STATUS_IS_OK ( status ) & & errno ! = 0 ) {
2007-01-13 02:47:16 +03:00
status = map_nt_error_from_unix ( errno ) ;
1998-08-14 21:38:29 +04:00
}
2007-09-13 01:48:20 +04:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2009-06-11 06:49:31 +04:00
TALLOC_FREE ( fname_src_dir ) ;
TALLOC_FREE ( fname_src_mask ) ;
2007-01-13 02:47:16 +03:00
return status ;
1998-07-11 04:28:34 +04:00
}
/****************************************************************************
Reply to a mv .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_mv ( struct smb_request * req )
1998-07-11 04:28:34 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-09-11 22:31:29 +04:00
char * name = NULL ;
char * newname = NULL ;
2008-11-01 19:35:48 +03:00
const char * p ;
2007-08-14 18:50:49 +04:00
uint32 attrs ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2007-10-19 04:40:25 +04:00
bool src_has_wcard = False ;
bool dest_has_wcard = False ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2009-07-24 22:39:56 +04:00
struct smb_filename * smb_fname_src = NULL ;
struct smb_filename * smb_fname_dst = NULL ;
2000-03-09 01:14:30 +03:00
2001-09-04 11:13:01 +04:00
START_PROFILE ( SMBmv ) ;
1998-07-11 04:28:34 +04:00
2007-08-14 18:50:49 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-08-14 18:50:49 +04:00
}
2007-07-05 20:26:27 +04:00
2008-11-02 14:20:47 +03:00
attrs = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-14 18:50:49 +04:00
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req_wcard ( ctx , req , & name , p , STR_TERMINATE ,
& status , & src_has_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2001-09-04 11:13:01 +04:00
p + + ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req_wcard ( ctx , req , & newname , p , STR_TERMINATE ,
& status , & dest_has_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2007-09-11 22:31:29 +04:00
2009-07-24 22:39:56 +04:00
status = filename_convert ( ctx ,
conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
name ,
2009-07-25 05:38:40 +04:00
UCF_COND_ALLOW_WCARD_LCOMP ,
2009-07-24 22:39:56 +04:00
& src_has_wcard ,
& smb_fname_src ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 18:50:49 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
2009-07-24 22:39:56 +04:00
status = filename_convert ( ctx ,
conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
newname ,
2009-07-25 05:38:40 +04:00
UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP ,
2009-07-24 22:39:56 +04:00
& dest_has_wcard ,
& smb_fname_dst ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 18:50:49 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2009-07-24 22:39:56 +04:00
DEBUG ( 3 , ( " reply_mv : %s -> %s \n " , smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2007-09-11 22:31:29 +04:00
2009-07-24 22:39:56 +04:00
status = rename_internals ( ctx , conn , req , smb_fname_src , smb_fname_dst ,
attrs , False , src_has_wcard , dest_has_wcard ,
DELETE_ACCESS ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-07-24 22:39:56 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2001-09-04 11:13:01 +04:00
}
2000-09-20 23:00:21 +04:00
2007-08-14 18:50:49 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2009-07-24 22:39:56 +04:00
out :
TALLOC_FREE ( smb_fname_src ) ;
TALLOC_FREE ( smb_fname_dst ) ;
2001-09-04 11:13:01 +04:00
END_PROFILE ( SMBmv ) ;
2007-08-14 18:50:49 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2001-09-04 23:10:30 +04:00
Copy a file as part of a reply_copy .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-23 04:58:28 +04:00
2007-01-05 16:13:15 +03:00
/*
* TODO : check error codes on all callers
*/
2007-09-13 01:48:20 +04:00
NTSTATUS copy_file ( TALLOC_CTX * ctx ,
connection_struct * conn ,
2009-06-10 21:37:57 +04:00
struct smb_filename * smb_fname_src ,
struct smb_filename * smb_fname_dst ,
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
int ofun ,
int count ,
2007-10-19 04:40:25 +04:00
bool target_is_directory )
1996-05-04 11:50:46 +04:00
{
2009-06-10 21:37:57 +04:00
struct smb_filename * smb_fname_dst_tmp = NULL ;
2001-09-04 23:10:30 +04:00
SMB_OFF_T ret = - 1 ;
files_struct * fsp1 , * fsp2 ;
2004-04-02 22:46:19 +04:00
uint32 dosattrs ;
2005-07-08 08:51:27 +04:00
uint32 new_create_disposition ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
2007-09-13 01:48:20 +04:00
2009-06-10 21:37:57 +04:00
status = copy_smb_filename ( ctx , smb_fname_dst , & smb_fname_dst_tmp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2007-09-13 01:48:20 +04:00
}
2009-06-10 21:37:57 +04:00
/*
* If the target is a directory , extract the last component from the
* src filename and append it to the dst filename
*/
2001-09-04 23:10:30 +04:00
if ( target_is_directory ) {
2009-06-10 21:37:57 +04:00
const char * p ;
/* dest/target can't be a stream if it's a directory. */
SMB_ASSERT ( smb_fname_dst - > stream_name = = NULL ) ;
p = strrchr_m ( smb_fname_src - > base_name , ' / ' ) ;
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 {
2009-06-10 21:37:57 +04:00
p = smb_fname_src - > base_name ;
2005-07-08 08:51:27 +04:00
}
2009-06-10 21:37:57 +04:00
smb_fname_dst_tmp - > base_name =
talloc_asprintf_append ( smb_fname_dst_tmp - > base_name , " /%s " ,
p ) ;
if ( ! smb_fname_dst_tmp - > base_name ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
2007-09-13 01:48:20 +04:00
}
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2009-06-10 21:37:57 +04:00
status = vfs_file_exist ( conn , smb_fname_src ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
2005-07-08 08:51:27 +04:00
}
if ( ! target_is_directory & & count ) {
new_create_disposition = FILE_OPEN ;
} else {
2009-07-21 20:29:59 +04:00
if ( ! map_open_params_to_ntcreate ( smb_fname_dst_tmp , 0 , ofun ,
NULL , NULL ,
2009-06-10 21:37:57 +04:00
& new_create_disposition ,
2010-03-06 02:10:30 +03:00
NULL ,
2009-06-10 21:37:57 +04:00
NULL ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
2005-07-08 08:51:27 +04:00
}
}
1996-05-04 11:50:46 +04:00
2009-06-10 21:37:57 +04:00
/* Open the src file for reading. */
2008-11-21 05:55:24 +03:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
NULL , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname_src , /* fname */
2008-11-21 05:55:24 +03:00
FILE_GENERIC_READ , /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE , /* share_access */
FILE_OPEN , /* create_disposition*/
0 , /* create_options */
FILE_ATTRIBUTE_NORMAL , /* file_attributes */
INTERNAL_OPEN_ONLY , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-11-21 05:55:24 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp1 , /* result */
2009-06-12 23:54:11 +04:00
NULL ) ; /* psbuf */
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
}
1996-05-04 11:50:46 +04:00
2009-07-08 23:24:03 +04:00
dosattrs = dos_mode ( conn , smb_fname_src ) ;
2009-06-12 23:54:11 +04:00
2009-06-23 02:26:56 +04:00
if ( SMB_VFS_STAT ( conn , smb_fname_dst_tmp ) = = - 1 ) {
2009-06-10 21:37:57 +04:00
ZERO_STRUCTP ( & smb_fname_dst_tmp - > st ) ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2009-06-10 21:37:57 +04:00
/* Open the dst file for writing. */
2008-11-21 05:55:24 +03:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
NULL , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname_dst , /* fname */
2008-11-21 05:55:24 +03:00
FILE_GENERIC_WRITE , /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE , /* share_access */
new_create_disposition , /* create_disposition*/
0 , /* create_options */
dosattrs , /* file_attributes */
INTERNAL_OPEN_ONLY , /* oplock_request */
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-11-21 05:55:24 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp2 , /* result */
2009-06-12 23:54:11 +04:00
NULL ) ; /* psbuf */
2007-09-13 01:48:20 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-10-09 18:27:49 +04:00
close_file ( NULL , fsp1 , ERROR_CLOSE ) ;
2009-06-10 21:37:57 +04:00
goto out ;
2001-09-04 23:10:30 +04:00
}
if ( ( ofun & 3 ) = = 1 ) {
2008-01-07 12:15:08 +03:00
if ( SMB_VFS_LSEEK ( fsp2 , 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 ;
2009-06-10 21:37:57 +04:00
smb_fname_src - > st . st_ex_size = 0 ;
2001-09-04 23:10:30 +04:00
}
}
2007-09-13 01:48:20 +04:00
2009-06-10 21:37:57 +04:00
/* Do the actual copy. */
if ( smb_fname_src - > st . st_ex_size ) {
ret = vfs_transfer_file ( fsp1 , fsp2 , smb_fname_src - > st . st_ex_size ) ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-10-09 18:27:49 +04:00
close_file ( NULL , fsp1 , NORMAL_CLOSE ) ;
2002-01-03 23:49:06 +03:00
/* Ensure the modtime is set correctly on the destination file. */
2009-11-06 09:58:12 +03:00
set_close_write_time ( fsp2 , smb_fname_src - > st . st_ex_mtime ) ;
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 .
*/
2008-10-09 18:27:49 +04:00
status = close_file ( NULL , 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 ) ) {
2009-06-10 21:37:57 +04:00
goto out ;
2007-01-05 16:13:15 +03:00
}
2009-06-10 21:37:57 +04:00
if ( ret ! = ( SMB_OFF_T ) smb_fname_src - > st . st_ex_size ) {
status = NT_STATUS_DISK_FULL ;
goto out ;
2007-01-05 16:13:15 +03:00
}
2009-06-10 21:37:57 +04:00
status = NT_STATUS_OK ;
out :
TALLOC_FREE ( smb_fname_dst_tmp ) ;
return status ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a file copy .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_copy ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-10 21:37:57 +04:00
struct smb_filename * smb_fname_src = NULL ;
struct smb_filename * smb_fname_dst = NULL ;
char * fname_src = NULL ;
char * fname_dst = NULL ;
char * fname_src_mask = NULL ;
char * fname_src_dir = NULL ;
2008-11-01 19:30:37 +03:00
const char * p ;
2002-12-04 02:57:45 +03:00
int count = 0 ;
int error = ERRnoaccess ;
2007-08-15 01:21:52 +04:00
int tid2 ;
int ofun ;
int flags ;
2007-10-19 04:40:25 +04:00
bool target_is_directory = False ;
bool source_has_wild = False ;
bool dest_has_wild = False ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-08-15 01:21:52 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-15 01:21:52 +04:00
}
2008-11-02 14:20:47 +03:00
tid2 = SVAL ( req - > vwv + 0 , 0 ) ;
ofun = SVAL ( req - > vwv + 1 , 0 ) ;
flags = SVAL ( req - > vwv + 2 , 0 ) ;
2007-08-15 01:21:52 +04:00
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf ;
2009-06-10 21:37:57 +04:00
p + = srvstr_get_path_req_wcard ( ctx , req , & fname_src , p , STR_TERMINATE ,
2008-11-02 02:59:03 +03:00
& status , & source_has_wild ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2009-06-10 21:37:57 +04:00
p + = srvstr_get_path_req_wcard ( ctx , req , & fname_dst , p , STR_TERMINATE ,
2008-11-02 02:59:03 +03:00
& status , & dest_has_wild ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2007-09-11 22:31:29 +04:00
2009-06-10 21:37:57 +04:00
DEBUG ( 3 , ( " reply_copy : %s -> %s \n " , fname_src , fname_dst ) ) ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
if ( tid2 ! = conn - > cnum ) {
/* can't currently handle inter share copies XXXX */
DEBUG ( 3 , ( " Rejecting inter-share copy \n " ) ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_BAD_DEVICE_TYPE ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
1999-12-13 16:27:58 +03:00
}
1996-05-04 11:50:46 +04:00
2009-07-25 05:38:40 +04:00
status = filename_convert ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
fname_src ,
UCF_COND_ALLOW_WCARD_LCOMP ,
& source_has_wild ,
& smb_fname_src ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-15 01:21:52 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
2009-07-25 05:38:40 +04:00
status = filename_convert ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
fname_dst ,
UCF_COND_ALLOW_WCARD_LCOMP ,
& dest_has_wild ,
& smb_fname_dst ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-15 01:21:52 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
1996-05-04 11:50:46 +04:00
2009-06-10 21:37:57 +04:00
target_is_directory = VALID_STAT_OF_DIR ( smb_fname_dst - > st ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( ( flags & 1 ) & & target_is_directory ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_SUCH_FILE ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( ( flags & 2 ) & & ! target_is_directory ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_OBJECT_PATH_NOT_FOUND ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2009-06-10 21:37:57 +04:00
if ( ( flags & ( 1 < < 5 ) ) & & VALID_STAT_OF_DIR ( smb_fname_src - > st ) ) {
2002-12-04 02:57:45 +03:00
/* wants a tree copy! XXXX */
DEBUG ( 3 , ( " Rejecting tree copy \n " ) ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2009-06-10 21:37:57 +04:00
/* Split up the directory from the filename/mask. */
2009-06-11 03:02:00 +04:00
status = split_fname_dir_mask ( ctx , smb_fname_src - > base_name ,
& fname_src_dir , & fname_src_mask ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-11-01 19:30:37 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
/*
* We should only check the mangled cache
* here if unix_convert failed . This means
* that the path in ' mask ' doesn ' t exist
* on the file system and so we need to look
* for a possible mangle . This patch from
* Tine Smukavec < valentin . smukavec @ hermes . si > .
*/
2009-06-10 21:37:57 +04:00
if ( ! VALID_STAT ( smb_fname_src - > st ) & &
mangle_is_mangled ( fname_src_mask , conn - > params ) ) {
2007-09-08 00:57:01 +04:00
char * new_mask = NULL ;
2009-06-10 21:37:57 +04:00
mangle_lookup_name_from_8_3 ( ctx , fname_src_mask ,
& new_mask , conn - > params ) ;
/* Use demangled name if one was successfully found. */
2007-09-08 00:57:01 +04:00
if ( new_mask ) {
2009-06-10 21:37:57 +04:00
TALLOC_FREE ( fname_src_mask ) ;
fname_src_mask = new_mask ;
2007-09-08 00:57:01 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2002-12-04 02:57:45 +03:00
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! source_has_wild ) {
2009-06-10 21:37:57 +04:00
/*
* Only one file needs to be copied . Append the mask back onto
* the directory .
*/
TALLOC_FREE ( smb_fname_src - > base_name ) ;
smb_fname_src - > base_name = talloc_asprintf ( smb_fname_src ,
" %s/%s " ,
fname_src_dir ,
fname_src_mask ) ;
if ( ! smb_fname_src - > base_name ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
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 ) {
2009-06-10 21:37:57 +04:00
char * fname_dst_mod = NULL ;
if ( ! resolve_wildcards ( smb_fname_dst ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ,
& fname_dst_mod ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
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
}
2009-06-10 21:37:57 +04:00
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = fname_dst_mod ;
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
}
2009-06-10 21:37:57 +04:00
status = check_name ( conn , smb_fname_src - > base_name ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-09-12 03:57:59 +04:00
2009-06-10 21:37:57 +04:00
status = check_name ( conn , smb_fname_dst - > base_name ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
2009-06-10 21:37:57 +04:00
status = copy_file ( ctx , conn , smb_fname_src , smb_fname_dst ,
ofun , count , target_is_directory ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
} else {
count + + ;
2002-12-04 02:57:45 +03:00
}
} else {
2005-02-01 03:28:20 +03:00
struct smb_Dir * dir_hnd = NULL ;
2009-11-16 11:49:23 +03:00
const char * dname = NULL ;
char * talloced = NULL ;
2007-01-17 05:09:37 +03:00
long offset = 0 ;
2002-12-04 02:57:45 +03:00
2009-06-10 21:37:57 +04:00
/*
* There is a wildcard that requires us to actually read the
* src dir and copy each file matching the mask to the dst .
* Right now streams won ' t be copied , but this could
* presumably be added with a nested loop for reach dir entry .
*/
SMB_ASSERT ( ! smb_fname_src - > stream_name ) ;
SMB_ASSERT ( ! smb_fname_dst - > stream_name ) ;
smb_fname_src - > stream_name = NULL ;
smb_fname_dst - > stream_name = NULL ;
if ( strequal ( fname_src_mask , " ????????.??? " ) ) {
TALLOC_FREE ( fname_src_mask ) ;
fname_src_mask = talloc_strdup ( ctx , " * " ) ;
if ( ! fname_src_mask ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
2007-09-13 01:48:20 +04:00
}
2005-06-25 07:03:44 +04:00
2009-06-10 21:37:57 +04:00
status = check_name ( conn , fname_src_dir ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
2007-09-13 01:48:20 +04:00
2009-06-10 21:37:57 +04:00
dir_hnd = OpenDir ( ctx , conn , fname_src_dir , fname_src_mask , 0 ) ;
2007-01-17 05:09:37 +03:00
if ( dir_hnd = = NULL ) {
status = map_nt_error_from_unix ( errno ) ;
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
error = ERRbadfile ;
2002-12-04 02:57:45 +03:00
2009-06-10 21:37:57 +04:00
/* Iterate over the src dir copying each entry to the dst. */
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
while ( ( dname = ReadDirName ( dir_hnd , & offset ,
2009-11-16 11:49:23 +03:00
& smb_fname_src - > st , & talloced ) ) ) {
2007-09-13 01:48:20 +04:00
char * destname = NULL ;
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-09-13 01:48:20 +04:00
continue ;
}
2009-06-10 21:37:57 +04:00
if ( ! is_visible_file ( conn , fname_src_dir , dname ,
& smb_fname_src - > st , false ) ) {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-01-17 05:09:37 +03:00
continue ;
}
2005-02-01 21:33:50 +03:00
2009-11-23 18:34:07 +03:00
if ( ! mask_match ( dname , fname_src_mask ,
2009-06-10 21:37:57 +04:00
conn - > case_sensitive ) ) {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-01-17 05:09:37 +03:00
continue ;
}
2002-12-04 02:57:45 +03:00
2007-01-17 05:09:37 +03:00
error = ERRnoaccess ;
2009-06-10 21:37:57 +04:00
/* Get the src smb_fname struct setup. */
TALLOC_FREE ( smb_fname_src - > base_name ) ;
smb_fname_src - > base_name =
talloc_asprintf ( smb_fname_src , " %s/%s " ,
fname_src_dir , dname ) ;
if ( ! smb_fname_src - > base_name ) {
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-09-13 01:48:20 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-09-13 01:48:20 +04:00
}
2009-06-10 21:37:57 +04:00
if ( ! resolve_wildcards ( ctx , smb_fname_src - > base_name ,
smb_fname_dst - > base_name ,
& destname ) ) {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
continue ;
}
2007-09-13 01:48:20 +04:00
if ( ! destname ) {
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-09-13 01:48:20 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-09-13 01:48:20 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
2009-06-10 21:37:57 +04:00
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = destname ;
status = check_name ( conn , smb_fname_src - > base_name ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
2009-06-10 21:37:57 +04:00
status = check_name ( conn , smb_fname_dst - > base_name ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2007-08-15 01:21:52 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
}
2007-09-13 01:48:20 +04:00
2009-06-10 21:37:57 +04:00
DEBUG ( 3 , ( " reply_copy : doing copy on %s -> %s \n " ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ) ) ;
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
2009-06-10 21:37:57 +04:00
status = copy_file ( ctx , conn , smb_fname_src ,
smb_fname_dst , ofun , count ,
target_is_directory ) ;
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
2007-01-17 05:09:37 +03:00
count + + ;
2002-12-04 02:57:45 +03:00
}
2009-08-27 01:56:09 +04:00
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2002-12-04 02:57:45 +03:00
}
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( dir_hnd ) ;
2002-12-04 02:57:45 +03:00
}
2007-09-13 01:48:20 +04:00
2002-12-04 02:57:45 +03:00
if ( count = = 0 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , dos_to_ntstatus ( ERRDOS , error ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-08-15 01:21:52 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , count ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-06-10 21:37:57 +04:00
TALLOC_FREE ( smb_fname_src ) ;
TALLOC_FREE ( smb_fname_dst ) ;
TALLOC_FREE ( fname_src ) ;
TALLOC_FREE ( fname_dst ) ;
TALLOC_FREE ( fname_src_mask ) ;
TALLOC_FREE ( fname_src_dir ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
2001-07-02 06:42:41 +04:00
/****************************************************************************
Get a lock pid , dealing with large count requests .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-07 17:20:50 +04:00
uint64_t get_lock_pid ( const uint8_t * data , int data_offset ,
2008-11-01 19:22:15 +03:00
bool large_file_format )
2001-07-02 06:42:41 +04:00
{
if ( ! large_file_format )
2010-05-07 17:20:50 +04:00
return ( uint64_t ) SVAL ( data , SMB_LPID_OFFSET ( data_offset ) ) ;
2001-07-02 06:42:41 +04:00
else
2010-05-07 17:20:50 +04:00
return ( uint64_t ) 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-11-01 19:22:15 +03:00
uint64_t get_lock_count ( const uint8_t * data , int data_offset ,
bool large_file_format )
1999-12-13 16:27:58 +03:00
{
2008-10-14 03:59:36 +04:00
uint64_t count = 0 ;
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
if ( ! large_file_format ) {
2008-10-14 03:59:36 +04:00
count = ( uint64_t ) IVAL ( data , SMB_LKLEN_OFFSET ( data_offset ) ) ;
2002-12-04 02:57:45 +03:00
} else {
1999-12-13 16:27:58 +03:00
2000-04-11 23:44:54 +04:00
# if defined(HAVE_LONGLONG)
2008-10-14 03:59:36 +04:00
count = ( ( ( uint64_t ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_HIGH ( data_offset ) ) ) < < 32 ) |
( ( uint64_t ) 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 ) ;
}
2008-10-14 03:59:36 +04:00
count = ( uint64_t ) 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 ;
2008-10-19 17:30:12 +04:00
2001-09-07 02:43:21 +04:00
/*
* Try and find out how many significant bits there are in high .
*/
2008-10-19 17:30:12 +04:00
2001-09-07 02:43:21 +04:00
for ( i = 0 ; highcopy ; i + + )
highcopy > > = 1 ;
2008-10-19 17:30:12 +04:00
2001-09-07 02:43:21 +04:00
/*
* We use 31 bits not 32 here as POSIX
* lock offsets may not be negative .
*/
2008-10-19 17:30:12 +04:00
2001-09-07 02:43:21 +04:00
mask = ( ~ 0 ) < < ( 31 - i ) ;
2008-10-19 17:30:12 +04:00
2001-09-07 02:43:21 +04:00
if ( low & mask )
return 0 ; /* Fail. */
2008-10-19 17:30:12 +04:00
2001-09-07 02:43:21 +04:00
high < < = ( 31 - i ) ;
2008-10-19 17:30:12 +04:00
2001-09-07 02:43:21 +04:00
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-11-01 19:22:15 +03:00
uint64_t get_lock_offset ( const uint8_t * data , int data_offset ,
bool large_file_format , bool * err )
1999-12-13 16:27:58 +03:00
{
2008-10-14 03:59:36 +04:00
uint64_t 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 ) {
2008-10-14 03:59:36 +04:00
offset = ( uint64_t ) IVAL ( data , SMB_LKOFF_OFFSET ( data_offset ) ) ;
2002-12-04 02:57:45 +03:00
} else {
1999-12-13 16:27:58 +03:00
2000-04-11 23:44:54 +04:00
# if defined(HAVE_LONGLONG)
2008-10-14 03:59:36 +04:00
offset = ( ( ( uint64_t ) IVAL ( data , SMB_LARGE_LKOFF_OFFSET_HIGH ( data_offset ) ) ) < < 32 ) |
( ( uint64_t ) 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.
*/
2008-10-19 17:30:12 +04: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 ;
2008-10-14 03:59:36 +04:00
return ( uint64_t ) - 1 ;
2002-12-04 02:57:45 +03:00
}
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 ) ;
}
2008-10-14 03:59:36 +04:00
offset = ( uint64_t ) 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
}
2009-07-07 20:09:16 +04:00
NTSTATUS smbd_do_locking ( struct smb_request * req ,
files_struct * fsp ,
uint8_t type ,
int32_t timeout ,
uint16_t num_ulocks ,
struct smbd_lock_element * ulocks ,
uint16_t num_locks ,
struct smbd_lock_element * locks ,
bool * async )
2009-07-07 19:24:25 +04:00
{
connection_struct * conn = req - > conn ;
int i ;
NTSTATUS status = NT_STATUS_OK ;
* async = false ;
/* Data now points at the beginning of the list
of smb_unlkrng structs */
for ( i = 0 ; i < ( int ) num_ulocks ; i + + ) {
struct smbd_lock_element * e = & ulocks [ i ] ;
DEBUG ( 10 , ( " smbd_do_locking: unlock start=%.0f, len=%.0f for "
" pid %u, file %s \n " ,
( double ) e - > offset ,
( double ) e - > count ,
2010-05-07 17:20:50 +04:00
( unsigned int ) e - > smblctx ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2009-07-07 19:24:25 +04:00
if ( e - > brltype ! = UNLOCK_LOCK ) {
/* this can only happen with SMB2 */
return NT_STATUS_INVALID_PARAMETER ;
}
status = do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2010-05-07 17:20:50 +04:00
e - > smblctx ,
2009-07-07 19:24:25 +04:00
e - > count ,
e - > offset ,
WINDOWS_LOCK ) ;
DEBUG ( 10 , ( " smbd_do_locking: unlock returned %s \n " ,
nt_errstr ( status ) ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
/* Setup the timeout in seconds. */
if ( ! lp_blocking_locks ( SNUM ( conn ) ) ) {
timeout = 0 ;
}
/* Data now points at the beginning of the list
of smb_lkrng structs */
for ( i = 0 ; i < ( int ) num_locks ; i + + ) {
struct smbd_lock_element * e = & locks [ i ] ;
2010-05-07 17:20:50 +04:00
DEBUG ( 10 , ( " smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
" %llu, file %s timeout = %d \n " ,
2009-07-07 19:24:25 +04:00
( double ) e - > offset ,
( double ) e - > count ,
2010-05-07 17:20:50 +04:00
( unsigned long long ) e - > smblctx ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ,
2009-07-07 19:24:25 +04:00
( int ) timeout ) ) ;
if ( type & LOCKING_ANDX_CANCEL_LOCK ) {
struct blocking_lock_record * blr = NULL ;
2009-12-05 01:04:08 +03:00
if ( num_locks > 1 ) {
/*
* MS - CIFS ( 2.2 .4 .32 .1 ) states that a cancel is honored if and only
* if the lock vector contains one entry . When given mutliple cancel
* requests in a single PDU we expect the server to return an
* error . Windows servers seem to accept the request but only
* cancel the first lock .
* JRA - Do what Windows does ( tm ) : - ) .
*/
#if 0
/* MS-CIFS (2.2.4.32.1) behavior. */
return NT_STATUS_DOS ( ERRDOS ,
ERRcancelviolation ) ;
# else
/* Windows behavior. */
if ( i ! = 0 ) {
DEBUG ( 10 , ( " smbd_do_locking: ignoring subsequent "
" cancel request \n " ) ) ;
continue ;
}
# endif
}
2009-07-07 19:24:25 +04:00
if ( lp_blocking_locks ( SNUM ( conn ) ) ) {
/* Schedule a message to ourselves to
remove the blocking lock record and
return the right error . */
2010-04-30 04:08:12 +04:00
blr = blocking_lock_cancel_smb1 ( fsp ,
2010-05-07 17:20:50 +04:00
e - > smblctx ,
2009-07-07 19:24:25 +04:00
e - > offset ,
e - > count ,
WINDOWS_LOCK ,
type ,
NT_STATUS_FILE_LOCK_CONFLICT ) ;
if ( blr = = NULL ) {
return NT_STATUS_DOS (
ERRDOS ,
ERRcancelviolation ) ;
}
}
/* Remove a matching pending lock. */
status = do_lock_cancel ( fsp ,
2010-05-07 17:20:50 +04:00
e - > smblctx ,
2009-07-07 19:24:25 +04:00
e - > count ,
e - > offset ,
WINDOWS_LOCK ,
blr ) ;
} else {
bool blocking_lock = timeout ? true : false ;
bool defer_lock = false ;
struct byte_range_lock * br_lck ;
2010-05-07 17:20:50 +04:00
uint64_t block_smblctx ;
2009-07-07 19:24:25 +04:00
br_lck = do_lock ( smbd_messaging_context ( ) ,
fsp ,
2010-05-07 17:20:50 +04:00
e - > smblctx ,
2009-07-07 19:24:25 +04:00
e - > count ,
e - > offset ,
e - > brltype ,
WINDOWS_LOCK ,
blocking_lock ,
& status ,
2010-05-07 17:20:50 +04:00
& block_smblctx ,
2009-07-07 19:24:25 +04:00
NULL ) ;
if ( br_lck & & blocking_lock & & ERROR_WAS_LOCK_DENIED ( status ) ) {
/* Windows internal resolution for blocking locks seems
to be about 200 ms . . . Don ' t wait for less than that . JRA . */
if ( timeout ! = - 1 & & timeout < lp_lock_spin_time ( ) ) {
timeout = lp_lock_spin_time ( ) ;
}
defer_lock = true ;
}
2010-02-13 02:42:50 +03:00
/* If a lock sent with timeout of zero would fail, and
* this lock has been requested multiple times ,
* according to brl_lock_failed ( ) we convert this
* request to a blocking lock with a timeout of between
* 150 - 300 milliseconds .
*
* If lp_lock_spin_time ( ) has been set to 0 , we skip
* this blocking retry and fail immediately .
*
* Replacement for do_lock_spin ( ) . JRA . */
2009-07-07 19:24:25 +04:00
2010-06-12 13:49:02 +04:00
if ( ! req - > sconn - > using_smb2 & &
2010-05-20 07:09:08 +04:00
br_lck & & lp_blocking_locks ( SNUM ( conn ) ) & &
2010-02-13 02:42:50 +03:00
lp_lock_spin_time ( ) & & ! blocking_lock & &
NT_STATUS_EQUAL ( ( status ) ,
NT_STATUS_FILE_LOCK_CONFLICT ) )
{
2009-07-07 19:24:25 +04:00
defer_lock = true ;
timeout = lp_lock_spin_time ( ) ;
}
if ( br_lck & & defer_lock ) {
/*
* A blocking lock was requested . Package up
* this smb into a queued request and push it
* onto the blocking lock queue .
*/
if ( push_blocking_lock_request ( br_lck ,
req ,
fsp ,
timeout ,
i ,
2010-05-07 17:20:50 +04:00
e - > smblctx ,
2009-07-07 19:24:25 +04:00
e - > brltype ,
WINDOWS_LOCK ,
e - > offset ,
e - > count ,
2010-05-07 17:20:50 +04:00
block_smblctx ) ) {
2009-07-07 19:24:25 +04:00
TALLOC_FREE ( br_lck ) ;
* async = true ;
return NT_STATUS_OK ;
}
}
TALLOC_FREE ( br_lck ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
break ;
}
}
/* If any of the above locks failed, then we must unlock
all of the previous locks ( X / Open spec ) . */
if ( num_locks ! = 0 & & ! NT_STATUS_IS_OK ( status ) ) {
if ( type & LOCKING_ANDX_CANCEL_LOCK ) {
i = - 1 ; /* we want to skip the for loop */
}
/*
* 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 - - ) {
struct smbd_lock_element * e = & locks [ i ] ;
do_unlock ( smbd_messaging_context ( ) ,
fsp ,
2010-05-07 17:20:50 +04:00
e - > smblctx ,
2009-07-07 19:24:25 +04:00
e - > count ,
e - > offset ,
WINDOWS_LOCK ) ;
}
return status ;
}
DEBUG ( 3 , ( " smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d \n " ,
fsp - > fnum , ( unsigned int ) type , num_locks , num_ulocks ) ) ;
return NT_STATUS_OK ;
}
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
2008-01-05 02:37:24 +03:00
void reply_lockingX ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-14 14:27:27 +04:00
files_struct * fsp ;
unsigned char locktype ;
unsigned char oplocklevel ;
uint16 num_ulocks ;
uint16 num_locks ;
int32 lock_timeout ;
2001-08-27 12:19:43 +04:00
int i ;
2008-11-01 19:35:48 +03:00
const uint8_t * data ;
2007-10-19 04:40:25 +04:00
bool large_file_format ;
bool err ;
2005-11-02 03:19:26 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2009-07-07 19:24:25 +04:00
struct smbd_lock_element * ulocks ;
struct smbd_lock_element * locks ;
bool async = false ;
1999-12-13 16:27:58 +03:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBlockingX ) ;
2007-08-14 14:27:27 +04:00
2007-08-14 17:38:14 +04:00
if ( req - > wct < 8 ) {
2007-08-14 14:47:47 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
2007-08-14 14:27:27 +04:00
}
2008-10-19 17:30:12 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 2 , 0 ) ) ;
locktype = CVAL ( req - > vwv + 3 , 0 ) ;
oplocklevel = CVAL ( req - > vwv + 3 , 1 ) ;
num_ulocks = SVAL ( req - > vwv + 6 , 0 ) ;
num_locks = SVAL ( req - > vwv + 7 , 0 ) ;
lock_timeout = IVAL ( req - > vwv + 4 , 0 ) ;
2007-08-14 14:27:27 +04:00
large_file_format = ( locktype & LOCKING_ANDX_LARGE_FILES ) ? True : False ;
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 17:38:14 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
}
2008-10-19 17:30:12 +04:00
2008-11-01 19:35:48 +03:00
data = req - > buf ;
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 ) */
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRDOS , ERRnoatomiclocks ) ;
2007-08-14 14:47:47 +04:00
END_PROFILE ( SMBlockingX ) ;
return ;
2002-03-11 04:34:14 +03:00
}
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/* Check if this is an oplock break on a file
we have granted an oplock on .
*/
if ( ( locktype & LOCKING_ANDX_OPLOCK_RELEASE ) ) {
/* Client can insist on breaking to none. */
2007-10-19 04:40:25 +04:00
bool break_to_none = ( oplocklevel = = 0 ) ;
bool result ;
2005-09-30 21:13:37 +04:00
DEBUG ( 5 , ( " reply_lockingX: oplock break reply (%u) from client "
" for fnum = %d \n " , ( unsigned int ) oplocklevel ,
fsp - > fnum ) ) ;
1999-12-13 16:27:58 +03:00
2001-08-27 12:19:43 +04:00
/*
2005-09-30 21:13:37 +04:00
* Make sure we have granted an exclusive or batch oplock on
* this file .
2001-08-27 12:19:43 +04:00
*/
2008-10-19 17:30:12 +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 " ,
2009-07-11 01:50:37 +04:00
fsp - > fnum , fsp - > oplock_type ,
fsp_str_dbg ( fsp ) ) ) ;
2005-09-30 21:13:37 +04:00
/* if this is a pure oplock break request then don't
* send a reply */
2001-08-27 12:19:43 +04:00
if ( num_locks = = 0 & & num_ulocks = = 0 ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
} else {
END_PROFILE ( SMBlockingX ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
}
1998-09-11 05:24:30 +04:00
2005-09-30 21:13:37 +04:00
if ( ( fsp - > sent_oplock_break = = BREAK_TO_NONE_SENT ) | |
( break_to_none ) ) {
result = remove_oplock ( fsp ) ;
} else {
result = downgrade_oplock ( fsp ) ;
2001-08-27 12:19:43 +04:00
}
2008-10-19 17:30:12 +04:00
2005-09-30 21:13:37 +04:00
if ( ! result ) {
DEBUG ( 0 , ( " reply_lockingX: error in removing "
2009-07-11 01:50:37 +04:00
" oplock on file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2005-09-30 21:13:37 +04:00
/* 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 . */
2008-11-02 14:20:47 +03:00
if ( CVAL ( req - > vwv + 0 , 0 ) ! = 0xff )
2005-09-30 21:13:37 +04:00
DEBUG ( 0 , ( " reply_lockingX: Error : pure oplock "
" break is a chained %d request ! \n " ,
2008-11-02 14:20:47 +03:00
( unsigned int ) CVAL ( req - > vwv + 0 , 0 ) ) ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
}
1999-12-13 16:27:58 +03:00
2008-11-01 18:24:42 +03:00
if ( req - > buflen <
2007-08-14 17:38:14 +04:00
( num_ulocks + num_locks ) * ( large_file_format ? 20 : 10 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2009-07-07 19:24:25 +04:00
ulocks = talloc_array ( req , struct smbd_lock_element , num_ulocks ) ;
if ( ulocks = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
locks = talloc_array ( req , struct smbd_lock_element , num_locks ) ;
if ( locks = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
2001-08-27 12:19:43 +04:00
/* Data now points at the beginning of the list
of smb_unlkrng structs */
for ( i = 0 ; i < ( int ) num_ulocks ; i + + ) {
2010-05-07 17:20:50 +04:00
ulocks [ i ] . smblctx = get_lock_pid ( data , i , large_file_format ) ;
2009-07-07 19:24:25 +04:00
ulocks [ i ] . count = get_lock_count ( data , i , large_file_format ) ;
ulocks [ i ] . offset = get_lock_offset ( data , i , large_file_format , & err ) ;
ulocks [ i ] . brltype = UNLOCK_LOCK ;
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/*
* There is no error code marked " stupid client bug " . . . . : - ) .
*/
if ( err ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
2006-07-18 01:09:02 +04:00
}
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/* Now do any requested locks */
data + = ( ( large_file_format ? 20 : 10 ) * num_ulocks ) ;
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/* Data now points at the beginning of the list
of smb_lkrng structs */
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
for ( i = 0 ; i < ( int ) num_locks ; i + + ) {
2010-05-07 17:20:50 +04:00
locks [ i ] . smblctx = get_lock_pid ( data , i , large_file_format ) ;
2009-07-07 19:24:25 +04:00
locks [ i ] . count = get_lock_count ( data , i , large_file_format ) ;
locks [ i ] . offset = get_lock_offset ( data , i , large_file_format , & err ) ;
if ( locktype & LOCKING_ANDX_SHARED_LOCK ) {
if ( locktype & LOCKING_ANDX_CANCEL_LOCK ) {
locks [ i ] . brltype = PENDING_READ_LOCK ;
} else {
locks [ i ] . brltype = READ_LOCK ;
}
} else {
if ( locktype & LOCKING_ANDX_CANCEL_LOCK ) {
locks [ i ] . brltype = PENDING_WRITE_LOCK ;
} else {
locks [ i ] . brltype = WRITE_LOCK ;
}
}
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/*
* There is no error code marked " stupid client bug " . . . . : - ) .
*/
if ( err ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
}
2008-10-19 17:30:12 +04:00
2009-07-07 19:24:25 +04:00
status = smbd_do_locking ( req , fsp ,
locktype , lock_timeout ,
num_ulocks , ulocks ,
num_locks , locks ,
& async ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
reply_nterror ( req , status ) ;
return ;
2001-08-27 12:19:43 +04:00
}
2009-07-07 19:24:25 +04:00
if ( async ) {
END_PROFILE ( SMBlockingX ) ;
return ;
}
1998-09-11 05:24:30 +04:00
2007-08-14 17:38:14 +04:00
reply_outbuf ( req , 2 , 0 ) ;
2008-10-19 17:30:12 +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 ) ) ;
2008-10-19 17:30:12 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBreadbmpx ( read block multiplex ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-19 04:56:03 +04:00
2008-01-05 02:37:24 +03:00
void reply_readbmpx ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-10-19 04:56:03 +04:00
START_PROFILE ( SMBreadBmpx ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2007-08-15 13:52:09 +04:00
END_PROFILE ( SMBreadBmpx ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2007-08-15 13:52:09 +04:00
/****************************************************************************
Reply to a SMBreadbs ( read block multiplex secondary ) request .
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
2008-01-05 02:37:24 +03:00
void reply_readbs ( struct smb_request * req )
2007-08-15 13:52:09 +04:00
{
START_PROFILE ( SMBreadBs ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2007-08-15 13:52:09 +04:00
END_PROFILE ( SMBreadBs ) ;
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBsetattrE .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_setattrE ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-01-24 01:40:19 +03:00
struct smb_file_time ft ;
2007-08-15 00:55:24 +04:00
files_struct * fsp ;
2008-03-12 17:39:38 +03:00
NTSTATUS status ;
2007-08-15 00:55:24 +04:00
2002-03-20 03:46:53 +03:00
START_PROFILE ( SMBsetattrE ) ;
2009-01-24 01:40:19 +03:00
ZERO_STRUCT ( ft ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
if ( req - > wct < 7 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-03 00:39:20 +04:00
goto out ;
2007-08-15 00:55:24 +04:00
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2009-07-03 00:39:20 +04:00
goto out ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
/*
2009-01-24 01:40:19 +03:00
* Convert the DOS times into unix times .
2002-03-20 03:46:53 +03:00
*/
2009-01-24 01:40:19 +03:00
ft . atime = convert_time_t_to_timespec (
srv_make_unix_date2 ( req - > vwv + 3 ) ) ;
ft . mtime = convert_time_t_to_timespec (
srv_make_unix_date2 ( req - > vwv + 5 ) ) ;
ft . create_time = convert_time_t_to_timespec (
srv_make_unix_date2 ( req - > vwv + 1 ) ) ;
2008-10-19 17:30:12 +04:00
2007-08-15 00:55:24 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2002-03-20 03:46:53 +03:00
/*
* Patch from Ray Frush < frush @ engr . colostate . edu >
* Sometimes times are sent as zero - ignore them .
*/
1997-09-23 23:19:06 +04:00
2008-03-12 17:39:38 +03:00
/* Ensure we have a valid stat struct for the source. */
2009-10-03 00:45:38 +04:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
2002-03-20 03:46:53 +03:00
}
1997-09-23 23:19:06 +04:00
2009-07-11 01:50:37 +04:00
status = smb_set_file_time ( conn , fsp , fsp - > fsp_name , & ft , true ) ;
2008-03-12 17:39:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , status ) ;
2009-07-03 00:39:20 +04:00
goto out ;
2002-03-20 03:46:53 +03:00
}
2008-10-19 17:30:12 +04:00
2009-01-24 01:40:19 +03:00
DEBUG ( 3 , ( " reply_setattrE fnum=%d actime=%u modtime=%u "
" createtime=%u \n " ,
2007-03-06 02:40:03 +03:00
fsp - > fnum ,
2009-01-24 01:40:19 +03:00
( unsigned int ) ft . atime . tv_sec ,
( unsigned int ) ft . mtime . tv_sec ,
( unsigned int ) ft . create_time . tv_sec
) ) ;
2009-07-03 00:39:20 +04:00
out :
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBsetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2001-10-19 04:56:03 +04:00
/* Back from the dead for OS/2..... JRA. */
/****************************************************************************
Reply to a SMBwritebmpx ( write block multiplex primary ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
2001-10-19 04:56:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_writebmpx ( struct smb_request * req )
2001-10-19 04:56:03 +04:00
{
START_PROFILE ( SMBwriteBmpx ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBmpx ) ;
2007-08-15 13:52:09 +04:00
return ;
2001-10-19 04:56:03 +04:00
}
/****************************************************************************
Reply to a SMBwritebs ( write block multiplex secondary ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
2001-10-19 04:56:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_writebs ( struct smb_request * req )
2001-10-19 04:56:03 +04:00
{
START_PROFILE ( SMBwriteBs ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBs ) ;
2007-08-15 13:52:09 +04:00
return ;
2001-10-19 04:56:03 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBgetattrE .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_getattrE ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-03-20 03:46:53 +03:00
int mode ;
2007-08-15 00:55:24 +04:00
files_struct * fsp ;
2008-08-28 02:06:14 +04:00
struct timespec create_ts ;
2007-08-15 00:55:24 +04:00
2002-03-20 03:46:53 +03:00
START_PROFILE ( SMBgetattrE ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBgetattrE ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
/* Do an fstat on this file */
2009-11-17 01:55:21 +03:00
if ( fsp_stat ( fsp ) ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
2008-10-19 17:30:12 +04:00
2009-07-11 01:50:37 +04:00
mode = dos_mode ( conn , fsp - > fsp_name ) ;
2008-10-19 17:30:12 +04:00
2002-03-20 03:46:53 +03:00
/*
* Convert the times into dos times . Set create
* date to be last modify date as UNIX doesn ' t save
* this .
*/
2007-08-15 00:55:24 +04:00
reply_outbuf ( req , 11 , 0 ) ;
2009-08-13 00:00:54 +04:00
create_ts = get_create_timespec ( conn , fsp , fsp - > fsp_name ) ;
2008-08-28 02:06:14 +04:00
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv0 , create_ts . tv_sec ) ;
2009-05-14 17:34:42 +04:00
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv2 ,
2009-11-17 01:55:21 +03:00
convert_timespec_to_time_t ( fsp - > fsp_name - > st . st_ex_atime ) ) ;
2005-03-10 04:30:14 +03:00
/* Should we check pending modtime here ? JRA */
2009-05-14 17:34:42 +04:00
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv4 ,
2009-11-17 01:55:21 +03:00
convert_timespec_to_time_t ( fsp - > fsp_name - > st . st_ex_mtime ) ) ;
2002-03-20 03:46:53 +03:00
if ( mode & aDIR ) {
2007-08-15 00:55:24 +04:00
SIVAL ( req - > outbuf , smb_vwv6 , 0 ) ;
SIVAL ( req - > outbuf , smb_vwv8 , 0 ) ;
2002-03-20 03:46:53 +03:00
} else {
2009-11-17 01:55:21 +03:00
uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE ( conn , fsp , & fsp - > fsp_name - > st ) ;
SIVAL ( req - > outbuf , smb_vwv6 , ( uint32 ) fsp - > fsp_name - > st . st_ex_size ) ;
2007-08-15 00:55:24 +04:00
SIVAL ( req - > outbuf , smb_vwv8 , allocation_size ) ;
2002-03-20 03:46:53 +03:00
}
2007-08-15 00:55:24 +04:00
SSVAL ( req - > outbuf , smb_vwv10 , mode ) ;
2008-10-19 17:30:12 +04:00
2002-03-20 03:46:53 +03:00
DEBUG ( 3 , ( " reply_getattrE fnum=%d \n " , fsp - > fnum ) ) ;
2008-10-19 17:30:12 +04:00
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}