2000-04-25 18:04:06 +04:00
/*
Unix SMB / Netbios implementation .
Version 3.0
client file operations
Copyright ( C ) Andrew Tridgell 1994 - 1998
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# define NO_SYSLOG
# include "includes.h"
/****************************************************************************
rename a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_rename ( struct cli_state * cli , char * fname_src , char * fname_dst )
{
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 15:45:50 +03:00
set_message ( cli - > outbuf , 1 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBmv ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , aSYSTEM | aHIDDEN | aDIR ) ;
p = smb_buf ( cli - > outbuf ) ;
* p + + = 4 ;
2001-02-20 15:45:50 +03:00
p + = clistr_push ( cli , p , fname_src , - 1 ,
2001-07-04 11:15:53 +04:00
STR_TERMINATE ) ;
2000-04-25 18:04:06 +04:00
* p + + = 4 ;
2001-02-20 15:45:50 +03:00
p + = clistr_push ( cli , p , fname_dst , - 1 ,
2001-07-04 11:15:53 +04:00
STR_TERMINATE ) ;
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
return True ;
}
/****************************************************************************
delete a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_unlink ( struct cli_state * cli , char * fname )
{
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 15:45:50 +03:00
set_message ( cli - > outbuf , 1 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBunlink ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , aSYSTEM | aHIDDEN ) ;
p = smb_buf ( cli - > outbuf ) ;
* p + + = 4 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , fname , - 1 , STR_TERMINATE ) ;
2000-04-25 18:04:06 +04:00
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
return True ;
}
/****************************************************************************
create a directory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_mkdir ( struct cli_state * cli , char * dname )
{
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 13:19:02 +03:00
set_message ( cli - > outbuf , 0 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBmkdir ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
p = smb_buf ( cli - > outbuf ) ;
* p + + = 4 ;
2001-08-21 07:50:31 +04:00
p + = clistr_push ( cli , p , dname , - 1 , STR_TERMINATE ) ;
2001-02-20 13:19:02 +03:00
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
return True ;
}
/****************************************************************************
remove a directory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_rmdir ( struct cli_state * cli , char * dname )
{
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 15:30:01 +03:00
set_message ( cli - > outbuf , 0 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBrmdir ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
p = smb_buf ( cli - > outbuf ) ;
* p + + = 4 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , dname , - 1 , STR_TERMINATE ) ;
2001-02-20 15:30:01 +03:00
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
return True ;
This is a big, rather ugly patch. Whilst investigating the files not truncated
when copying to a full disk problem, I discovered that we were not allowing
the delete on close flag to be set properly, this led to other things, and
after investigation of the proper delete on close semantics and their relationship
to the file_share_delete flag I discovered there were some cases where we
weren't doing the deny modes properly. And this after only 5 years working
on them..... :-) :-).
So here's the latest attempt. I realised the delete on close flag needs to
be set across all smbds with a dev/ino pair open - in addition, the delete
on close flag, allow share delete and delete access requested all need to
be stored in the share mode tdb.
The "delete_on_close" entry in the fsp struct is now redundant and should
really be removed. This may also mean we can get rid of the "iterate_fsp"
calls that I didn't like adding in the first place. Whilst doing this patch,
I also discovered we needed to do the se_map_generic() call for file opens
and POSIX ACL mapping, so I added that also.
This code, although ugly, now passes the deny mode torture tests plus the
delete on close tests I added. I do need to add one more multiple connection
delete on close test to make sure I got the semantics exactly right, plus we
should also (as Andrew suggested) move to random testing here.
The good news is that NT should now correctly delete the file on disk
full error when copying to a disk :-).
Jeremy.
(This used to be commit 51987684bd231c744da2e5f3705fd236d5616173)
2001-03-30 12:57:24 +04:00
}
/****************************************************************************
2001-03-29 06:58:47 +04:00
Set or clear the delete on close flag .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cli_nt_delete_on_close ( struct cli_state * cli , int fnum , BOOL flag )
{
int data_len = 1 ;
int param_len = 6 ;
uint16 setup = TRANSACT2_SETFILEINFO ;
pstring param ;
unsigned char data ;
char * rparam = NULL , * rdata = NULL ;
memset ( param , 0 , param_len ) ;
SSVAL ( param , 0 , fnum ) ;
SSVAL ( param , 2 , SMB_SET_FILE_DISPOSITION_INFO ) ;
data = flag ? 1 : 0 ;
if ( ! cli_send_trans ( cli , SMBtrans2 ,
This is a big, rather ugly patch. Whilst investigating the files not truncated
when copying to a full disk problem, I discovered that we were not allowing
the delete on close flag to be set properly, this led to other things, and
after investigation of the proper delete on close semantics and their relationship
to the file_share_delete flag I discovered there were some cases where we
weren't doing the deny modes properly. And this after only 5 years working
on them..... :-) :-).
So here's the latest attempt. I realised the delete on close flag needs to
be set across all smbds with a dev/ino pair open - in addition, the delete
on close flag, allow share delete and delete access requested all need to
be stored in the share mode tdb.
The "delete_on_close" entry in the fsp struct is now redundant and should
really be removed. This may also mean we can get rid of the "iterate_fsp"
calls that I didn't like adding in the first place. Whilst doing this patch,
I also discovered we needed to do the se_map_generic() call for file opens
and POSIX ACL mapping, so I added that also.
This code, although ugly, now passes the deny mode torture tests plus the
delete on close tests I added. I do need to add one more multiple connection
delete on close test to make sure I got the semantics exactly right, plus we
should also (as Andrew suggested) move to random testing here.
The good news is that NT should now correctly delete the file on disk
full error when copying to a disk :-).
Jeremy.
(This used to be commit 51987684bd231c744da2e5f3705fd236d5616173)
2001-03-30 12:57:24 +04:00
NULL , /* name */
2001-03-29 06:58:47 +04:00
- 1 , 0 , /* fid, flags */
& setup , 1 , 0 , /* setup, length, max */
param , param_len , 2 , /* param, length, max */
2001-05-17 08:09:08 +04:00
( char * ) & data , data_len , cli - > max_xmit /* data, length, max */
2001-03-29 06:58:47 +04:00
) ) {
return False ;
}
if ( ! cli_receive_trans ( cli , SMBtrans2 ,
& rparam , & param_len ,
& rdata , & data_len ) ) {
return False ;
}
2001-09-17 07:33:37 +04:00
SAFE_FREE ( rdata ) ;
SAFE_FREE ( rparam ) ;
2001-03-29 06:58:47 +04:00
return True ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-03-29 04:58:52 +04:00
open a file - exposing the full horror of the NT API : - ) .
Used in smbtorture .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-03-29 04:58:52 +04:00
2001-11-04 02:34:24 +03:00
int cli_nt_create_full ( struct cli_state * cli , const char * fname , uint32 DesiredAccess ,
2001-03-29 04:58:52 +04:00
uint32 FileAttributes , uint32 ShareAccess ,
uint32 CreateDisposition , uint32 CreateOptions )
2000-04-25 18:04:06 +04:00
{
char * p ;
2001-02-21 02:52:27 +03:00
int len ;
2000-04-25 18:04:06 +04:00
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 15:49:55 +03:00
set_message ( cli - > outbuf , 24 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBntcreateX ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
2000-11-16 03:59:18 +03:00
if ( cli - > use_oplocks )
SIVAL ( cli - > outbuf , smb_ntcreate_Flags , REQUEST_OPLOCK | REQUEST_BATCH_OPLOCK ) ;
else
SIVAL ( cli - > outbuf , smb_ntcreate_Flags , 0 ) ;
2000-04-25 18:04:06 +04:00
SIVAL ( cli - > outbuf , smb_ntcreate_RootDirectoryFid , 0x0 ) ;
2000-12-04 10:26:56 +03:00
SIVAL ( cli - > outbuf , smb_ntcreate_DesiredAccess , DesiredAccess ) ;
2001-03-29 04:58:52 +04:00
SIVAL ( cli - > outbuf , smb_ntcreate_FileAttributes , FileAttributes ) ;
SIVAL ( cli - > outbuf , smb_ntcreate_ShareAccess , ShareAccess ) ;
SIVAL ( cli - > outbuf , smb_ntcreate_CreateDisposition , CreateDisposition ) ;
SIVAL ( cli - > outbuf , smb_ntcreate_CreateOptions , CreateOptions ) ;
2000-04-25 18:04:06 +04:00
SIVAL ( cli - > outbuf , smb_ntcreate_ImpersonationLevel , 0x02 ) ;
p = smb_buf ( cli - > outbuf ) ;
2001-02-21 02:52:27 +03:00
/* this alignment and termination is critical for netapp filers. Don't change */
2001-07-04 11:15:53 +04:00
p + = clistr_align_out ( cli , p , 0 ) ;
len = clistr_push ( cli , p , fname , - 1 , 0 ) ;
2001-02-21 02:52:27 +03:00
p + = len ;
SSVAL ( cli - > outbuf , smb_ntcreate_NameLength , len ) ;
2001-02-22 06:38:21 +03:00
/* sigh. this copes with broken netapp filer behaviour */
2001-03-10 14:35:25 +03:00
p + = clistr_push ( cli , p , " " , - 1 , STR_TERMINATE ) ;
2001-02-20 15:49:55 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return - 1 ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return - 1 ;
}
return SVAL ( cli - > inbuf , smb_vwv2 + 1 ) ;
}
2001-03-29 04:58:52 +04:00
/****************************************************************************
open a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 02:34:24 +03:00
int cli_nt_create ( struct cli_state * cli , const char * fname , uint32 DesiredAccess )
2001-03-29 04:58:52 +04:00
{
return cli_nt_create_full ( cli , fname , DesiredAccess , 0 ,
FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_EXISTS_OPEN , 0x0 ) ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
open a file
WARNING : if you open with O_WRONLY then getattrE won ' t work !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 02:34:24 +03:00
int cli_open ( struct cli_state * cli , const char * fname , int flags , int share_mode )
2000-04-25 18:04:06 +04:00
{
char * p ;
unsigned openfn = 0 ;
unsigned accessmode = 0 ;
if ( flags & O_CREAT )
openfn | = ( 1 < < 4 ) ;
if ( ! ( flags & O_EXCL ) ) {
if ( flags & O_TRUNC )
openfn | = ( 1 < < 1 ) ;
else
openfn | = ( 1 < < 0 ) ;
}
accessmode = ( share_mode < < 4 ) ;
if ( ( flags & O_ACCMODE ) = = O_RDWR ) {
accessmode | = 2 ;
} else if ( ( flags & O_ACCMODE ) = = O_WRONLY ) {
accessmode | = 1 ;
}
# if defined(O_SYNC)
if ( ( flags & O_SYNC ) = = O_SYNC ) {
accessmode | = ( 1 < < 14 ) ;
}
# endif /* O_SYNC */
if ( share_mode = = DENY_FCB ) {
accessmode = 0xFF ;
}
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 15:30:01 +03:00
set_message ( cli - > outbuf , 15 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBopenX ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
SSVAL ( cli - > outbuf , smb_vwv2 , 0 ) ; /* no additional info */
SSVAL ( cli - > outbuf , smb_vwv3 , accessmode ) ;
SSVAL ( cli - > outbuf , smb_vwv4 , aSYSTEM | aHIDDEN ) ;
SSVAL ( cli - > outbuf , smb_vwv5 , 0 ) ;
SSVAL ( cli - > outbuf , smb_vwv8 , openfn ) ;
if ( cli - > use_oplocks ) {
/* if using oplocks then ask for a batch oplock via
core and extended methods */
CVAL ( cli - > outbuf , smb_flg ) | =
FLAG_REQUEST_OPLOCK | FLAG_REQUEST_BATCH_OPLOCK ;
SSVAL ( cli - > outbuf , smb_vwv2 , SVAL ( cli - > outbuf , smb_vwv2 ) | 6 ) ;
}
p = smb_buf ( cli - > outbuf ) ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , fname , - 1 , STR_TERMINATE ) ;
2001-02-20 15:30:01 +03:00
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return - 1 ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return - 1 ;
}
return SVAL ( cli - > inbuf , smb_vwv2 ) ;
}
/****************************************************************************
close a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_close ( struct cli_state * cli , int fnum )
{
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 3 , 0 , True ) ;
CVAL ( cli - > outbuf , smb_com ) = SMBclose ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , fnum ) ;
SIVALS ( cli - > outbuf , smb_vwv1 , - 1 ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
return ! cli_is_error ( cli ) ;
2000-04-25 18:04:06 +04:00
}
/****************************************************************************
lock a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_lock ( struct cli_state * cli , int fnum ,
uint32 offset , uint32 len , int timeout , enum brl_type lock_type )
{
char * p ;
int saved_timeout = cli - > timeout ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 16:16:01 +03:00
set_message ( cli - > outbuf , 8 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBlockingX ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
CVAL ( cli - > outbuf , smb_vwv0 ) = 0xFF ;
SSVAL ( cli - > outbuf , smb_vwv2 , fnum ) ;
CVAL ( cli - > outbuf , smb_vwv3 ) = ( lock_type = = READ_LOCK ? 1 : 0 ) ;
SIVALS ( cli - > outbuf , smb_vwv4 , timeout ) ;
SSVAL ( cli - > outbuf , smb_vwv6 , 0 ) ;
SSVAL ( cli - > outbuf , smb_vwv7 , 1 ) ;
p = smb_buf ( cli - > outbuf ) ;
SSVAL ( p , 0 , cli - > pid ) ;
SIVAL ( p , 2 , offset ) ;
SIVAL ( p , 6 , len ) ;
2001-02-20 16:16:01 +03:00
p + = 10 ;
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
cli - > timeout = ( timeout = = - 1 ) ? 0x7FFFFFFF : ( timeout + 2 * 1000 ) ;
if ( ! cli_receive_smb ( cli ) ) {
cli - > timeout = saved_timeout ;
return False ;
}
cli - > timeout = saved_timeout ;
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
return True ;
}
/****************************************************************************
unlock a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_unlock ( struct cli_state * cli , int fnum , uint32 offset , uint32 len )
{
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 16:16:01 +03:00
set_message ( cli - > outbuf , 8 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBlockingX ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
CVAL ( cli - > outbuf , smb_vwv0 ) = 0xFF ;
SSVAL ( cli - > outbuf , smb_vwv2 , fnum ) ;
CVAL ( cli - > outbuf , smb_vwv3 ) = 0 ;
SIVALS ( cli - > outbuf , smb_vwv4 , 0 ) ;
SSVAL ( cli - > outbuf , smb_vwv6 , 1 ) ;
SSVAL ( cli - > outbuf , smb_vwv7 , 0 ) ;
p = smb_buf ( cli - > outbuf ) ;
SSVAL ( p , 0 , cli - > pid ) ;
SIVAL ( p , 2 , offset ) ;
SIVAL ( p , 6 , len ) ;
2001-02-20 16:16:01 +03:00
p + = 10 ;
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
return True ;
}
2000-09-29 08:41:52 +04:00
/****************************************************************************
lock a file with 64 bit offsets
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_lock64 ( struct cli_state * cli , int fnum ,
SMB_BIG_UINT offset , SMB_BIG_UINT len , int timeout , enum brl_type lock_type )
{
char * p ;
int saved_timeout = cli - > timeout ;
int ltype ;
2001-08-24 03:15:18 +04:00
if ( ! ( cli - > capabilities & CAP_LARGE_FILES ) ) {
return cli_lock ( cli , fnum , offset , len , timeout , lock_type ) ;
}
2000-09-29 08:41:52 +04:00
ltype = ( lock_type = = READ_LOCK ? 1 : 0 ) ;
ltype | = LOCKING_ANDX_LARGE_FILES ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 16:16:01 +03:00
set_message ( cli - > outbuf , 8 , 0 , True ) ;
2000-09-29 08:41:52 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBlockingX ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
CVAL ( cli - > outbuf , smb_vwv0 ) = 0xFF ;
SSVAL ( cli - > outbuf , smb_vwv2 , fnum ) ;
CVAL ( cli - > outbuf , smb_vwv3 ) = ltype ;
SIVALS ( cli - > outbuf , smb_vwv4 , timeout ) ;
SSVAL ( cli - > outbuf , smb_vwv6 , 0 ) ;
SSVAL ( cli - > outbuf , smb_vwv7 , 1 ) ;
p = smb_buf ( cli - > outbuf ) ;
SIVAL ( p , 0 , cli - > pid ) ;
2001-04-22 06:54:04 +04:00
SOFF_T_R ( p , 4 , offset ) ;
SOFF_T_R ( p , 12 , len ) ;
2001-02-20 16:16:01 +03:00
p + = 20 ;
cli_setup_bcc ( cli , p ) ;
2000-09-29 08:41:52 +04:00
cli_send_smb ( cli ) ;
cli - > timeout = ( timeout = = - 1 ) ? 0x7FFFFFFF : ( timeout + 2 * 1000 ) ;
if ( ! cli_receive_smb ( cli ) ) {
cli - > timeout = saved_timeout ;
return False ;
}
cli - > timeout = saved_timeout ;
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-09-29 08:41:52 +04:00
return False ;
}
return True ;
}
/****************************************************************************
unlock a file with 64 bit offsets
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_unlock64 ( struct cli_state * cli , int fnum , SMB_BIG_UINT offset , SMB_BIG_UINT len )
{
char * p ;
2001-08-24 03:15:18 +04:00
if ( ! ( cli - > capabilities & CAP_LARGE_FILES ) ) {
return cli_unlock ( cli , fnum , offset , len ) ;
}
2000-09-29 08:41:52 +04:00
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 16:16:01 +03:00
set_message ( cli - > outbuf , 8 , 0 , True ) ;
2000-09-29 08:41:52 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBlockingX ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
CVAL ( cli - > outbuf , smb_vwv0 ) = 0xFF ;
SSVAL ( cli - > outbuf , smb_vwv2 , fnum ) ;
CVAL ( cli - > outbuf , smb_vwv3 ) = LOCKING_ANDX_LARGE_FILES ;
SIVALS ( cli - > outbuf , smb_vwv4 , 0 ) ;
SSVAL ( cli - > outbuf , smb_vwv6 , 1 ) ;
SSVAL ( cli - > outbuf , smb_vwv7 , 0 ) ;
p = smb_buf ( cli - > outbuf ) ;
SIVAL ( p , 0 , cli - > pid ) ;
2001-04-22 06:54:04 +04:00
SOFF_T_R ( p , 4 , offset ) ;
SOFF_T_R ( p , 12 , len ) ;
2001-02-20 16:16:01 +03:00
p + = 20 ;
cli_setup_bcc ( cli , p ) ;
2000-09-29 08:41:52 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-09-29 08:41:52 +04:00
return False ;
}
return True ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
do a SMBgetattrE call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_getattrE ( struct cli_state * cli , int fd ,
uint16 * attr , size_t * size ,
time_t * c_time , time_t * a_time , time_t * m_time )
{
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 1 , 0 , True ) ;
CVAL ( cli - > outbuf , smb_com ) = SMBgetattrE ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , fd ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
if ( size ) {
* size = IVAL ( cli - > inbuf , smb_vwv6 ) ;
}
if ( attr ) {
* attr = SVAL ( cli - > inbuf , smb_vwv10 ) ;
}
if ( c_time ) {
* c_time = make_unix_date3 ( cli - > inbuf + smb_vwv0 ) ;
}
if ( a_time ) {
* a_time = make_unix_date3 ( cli - > inbuf + smb_vwv2 ) ;
}
if ( m_time ) {
* m_time = make_unix_date3 ( cli - > inbuf + smb_vwv4 ) ;
}
return True ;
}
/****************************************************************************
do a SMBgetatr call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_getatr ( struct cli_state * cli , char * fname ,
uint16 * attr , size_t * size , time_t * t )
{
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 15:49:55 +03:00
set_message ( cli - > outbuf , 0 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBgetatr ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
p = smb_buf ( cli - > outbuf ) ;
2001-02-20 15:49:55 +03:00
* p + + = 4 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , fname , - 1 , STR_TERMINATE ) ;
2001-02-20 15:49:55 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
if ( size ) {
* size = IVAL ( cli - > inbuf , smb_vwv3 ) ;
}
if ( t ) {
* t = make_unix_date3 ( cli - > inbuf + smb_vwv1 ) ;
}
if ( attr ) {
* attr = SVAL ( cli - > inbuf , smb_vwv0 ) ;
}
return True ;
}
/****************************************************************************
do a SMBsetatr call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_setatr ( struct cli_state * cli , char * fname , uint16 attr , time_t t )
{
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-02-20 16:16:01 +03:00
set_message ( cli - > outbuf , 8 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBsetatr ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , attr ) ;
put_dos_date3 ( cli - > outbuf , smb_vwv1 , t ) ;
p = smb_buf ( cli - > outbuf ) ;
2001-02-20 16:16:01 +03:00
* p + + = 4 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , fname , - 1 , STR_TERMINATE ) ;
2001-02-20 16:16:01 +03:00
* p + + = 4 ;
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
return True ;
}
/****************************************************************************
check for existance of a dir
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_chkpath ( struct cli_state * cli , char * path )
{
pstring path2 ;
char * p ;
safe_strcpy ( path2 , path , sizeof ( pstring ) ) ;
trim_string ( path2 , NULL , " \\ " ) ;
if ( ! * path2 ) * path2 = ' \\ ' ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
2001-02-20 15:25:42 +03:00
set_message ( cli - > outbuf , 0 , 0 , True ) ;
2000-04-25 18:04:06 +04:00
SCVAL ( cli - > outbuf , smb_com , SMBchkpth ) ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
p = smb_buf ( cli - > outbuf ) ;
* p + + = 4 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , path2 , - 1 , STR_TERMINATE ) ;
2001-02-20 15:25:42 +03:00
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
2001-08-10 10:00:33 +04:00
if ( cli_is_error ( cli ) ) return False ;
2000-04-25 18:04:06 +04:00
return True ;
}
/****************************************************************************
query disk space
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_dskattr ( struct cli_state * cli , int * bsize , int * total , int * avail )
{
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 0 , 0 , True ) ;
CVAL ( cli - > outbuf , smb_com ) = SMBdskattr ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return False ;
}
* bsize = SVAL ( cli - > inbuf , smb_vwv1 ) * SVAL ( cli - > inbuf , smb_vwv2 ) ;
* total = SVAL ( cli - > inbuf , smb_vwv0 ) ;
* avail = SVAL ( cli - > inbuf , smb_vwv3 ) ;
return True ;
}
2001-04-22 06:54:04 +04:00
/****************************************************************************
create and open a temporary file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cli_ctemp ( struct cli_state * cli , char * path , char * * tmp_path )
{
2001-09-17 08:23:48 +04:00
int len ;
2001-04-22 06:54:04 +04:00
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
2001-09-17 08:23:48 +04:00
set_message ( cli - > outbuf , 3 , 0 , True ) ;
2001-04-22 06:54:04 +04:00
CVAL ( cli - > outbuf , smb_com ) = SMBctemp ;
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , 0 ) ;
2001-09-17 08:23:48 +04:00
SIVALS ( cli - > outbuf , smb_vwv1 , - 1 ) ;
2001-04-22 06:54:04 +04:00
p = smb_buf ( cli - > outbuf ) ;
* p + + = 4 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , path , - 1 , STR_TERMINATE ) ;
2001-04-22 06:54:04 +04:00
2001-06-21 09:38:28 +04:00
cli_setup_bcc ( cli , p ) ;
2001-04-22 06:54:04 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return - 1 ;
}
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) ) {
2001-04-22 06:54:04 +04:00
return - 1 ;
}
2001-09-17 08:23:48 +04:00
/* despite the spec, the result has a -1, followed by
length , followed by name */
p = smb_buf ( cli - > inbuf ) ;
p + = 4 ;
len = smb_buflen ( cli - > inbuf ) - 4 ;
if ( len < = 0 ) return - 1 ;
2001-04-22 06:54:04 +04:00
if ( tmp_path ) {
pstring path2 ;
2001-09-17 08:23:48 +04:00
clistr_pull ( cli , path2 , p ,
sizeof ( path2 ) , len , STR_ASCII ) ;
2001-04-22 06:54:04 +04:00
* tmp_path = strdup ( path2 ) ;
}
return SVAL ( cli - > inbuf , smb_vwv0 ) ;
}