1996-05-04 11:50:46 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
SMB transaction2 handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) Jeremy Allison 1994 - 1998
1996-05-04 11:50:46 +04:00
Extensively modified by Andrew Tridgell , 1995
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 .
*/
# include "includes.h"
# include "trans2.h"
extern int DEBUGLEVEL ;
extern int Protocol ;
extern BOOL case_sensitive ;
extern int Client ;
1997-11-19 02:30:49 +03:00
extern int smb_read_error ;
1998-02-11 14:07:14 +03:00
extern fstring local_machine ;
1998-04-01 00:55:14 +04:00
extern int global_oplock_break ;
1999-12-13 16:27:58 +03:00
extern uint32 global_client_caps ;
1996-05-04 11:50:46 +04:00
/****************************************************************************
Send the required number of replies back .
We assume all fields other than the data fields are
set correctly for the type of call .
HACK ! Always assumes smb_setup field is zero .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int send_trans2_replies ( char * outbuf , int bufsize , char * params ,
1998-08-14 21:38:29 +04:00
int paramsize , char * pdata , int datasize )
1996-05-04 11:50:46 +04:00
{
1997-02-28 23:39:36 +03:00
/* As we are using a protocol > LANMAN1 then the max_send
1996-05-04 11:50:46 +04:00
variable must have been set in the sessetupX call .
This takes precedence over the max_xmit field in the
global struct . These different max_xmit variables should
be merged as this is now too confusing */
1997-02-28 23:39:36 +03:00
extern int max_send ;
1996-05-04 11:50:46 +04:00
int data_to_send = datasize ;
int params_to_send = paramsize ;
int useable_space ;
char * pp = params ;
char * pd = pdata ;
int params_sent_thistime , data_sent_thistime , total_sent_thistime ;
1998-01-25 18:36:11 +03:00
int alignment_offset = 3 ;
int data_alignment_offset = 0 ;
1996-05-04 11:50:46 +04:00
/* Initially set the wcnt area to be 10 - this is true for all
trans2 replies */
set_message ( outbuf , 10 , 0 , True ) ;
/* If there genuinely are no parameters or data to send just send
the empty packet */
if ( params_to_send = = 0 & & data_to_send = = 0 )
1998-07-09 04:41:32 +04:00
{
send_smb ( Client , outbuf ) ;
return 0 ;
}
1996-05-04 11:50:46 +04:00
1998-01-28 16:11:58 +03:00
/* When sending params and data ensure that both are nicely aligned */
/* Only do this alignment when there is also data to send - else
can cause NT redirector problems . */
if ( ( ( params_to_send % 4 ) ! = 0 ) & & ( data_to_send ! = 0 ) )
1998-07-09 04:41:32 +04:00
data_alignment_offset = 4 - ( params_to_send % 4 ) ;
1998-01-25 18:36:11 +03:00
1996-05-04 11:50:46 +04:00
/* Space is bufsize minus Netbios over TCP header minus SMB header */
1998-01-25 18:36:11 +03:00
/* The alignment_offset is to align the param bytes on an even byte
1996-05-04 11:50:46 +04:00
boundary . NT 4.0 Beta needs this to work correctly . */
1998-01-25 18:36:11 +03:00
useable_space = bufsize - ( ( smb_buf ( outbuf ) +
1998-07-09 04:41:32 +04:00
alignment_offset + data_alignment_offset ) -
outbuf ) ;
1998-01-25 18:36:11 +03:00
1997-02-28 23:39:36 +03:00
/* useable_space can never be more than max_send minus the
1996-12-03 22:05:27 +03:00
alignment offset . */
1998-01-25 18:36:11 +03:00
useable_space = MIN ( useable_space ,
1998-07-09 04:41:32 +04:00
max_send - ( alignment_offset + data_alignment_offset ) ) ;
1998-01-25 18:36:11 +03:00
1996-05-04 11:50:46 +04:00
1998-01-25 18:36:11 +03:00
while ( params_to_send | | data_to_send )
1998-07-09 04:41:32 +04:00
{
/* Calculate whether we will totally or partially fill this packet */
total_sent_thistime = params_to_send + data_to_send +
alignment_offset + data_alignment_offset ;
/* We can never send more than useable_space */
2000-01-15 02:50:38 +03:00
/*
* Note that ' useable_space ' does not include the alignment offsets ,
* but we must include the alignment offsets in the calculation of
* the length of the data we send over the wire , as the alignment offsets
* are sent here . Fix from Marc_Jacobsen @ hp . com .
*/
2000-03-09 01:14:30 +03:00
total_sent_thistime = MIN ( total_sent_thistime , useable_space +
alignment_offset + data_alignment_offset ) ;
1998-07-09 04:41:32 +04:00
set_message ( outbuf , 10 , total_sent_thistime , True ) ;
/* Set total params and data to be sent */
SSVAL ( outbuf , smb_tprcnt , paramsize ) ;
SSVAL ( outbuf , smb_tdrcnt , datasize ) ;
/* Calculate how many parameters and data we can fit into
this packet . Parameters get precedence */
params_sent_thistime = MIN ( params_to_send , useable_space ) ;
data_sent_thistime = useable_space - params_sent_thistime ;
data_sent_thistime = MIN ( data_sent_thistime , data_to_send ) ;
SSVAL ( outbuf , smb_prcnt , params_sent_thistime ) ;
2000-03-28 06:20:57 +04:00
/* smb_proff is the offset from the start of the SMB header to the
parameter bytes , however the first 4 bytes of outbuf are
the Netbios over TCP header . Thus use smb_base ( ) to subtract
them from the calculation */
SSVAL ( outbuf , smb_proff , ( ( smb_buf ( outbuf ) + alignment_offset ) - smb_base ( outbuf ) ) ) ;
1998-07-09 04:41:32 +04:00
if ( params_sent_thistime = = 0 )
SSVAL ( outbuf , smb_prdisp , 0 ) ;
else
/* Absolute displacement of param bytes sent in this packet */
SSVAL ( outbuf , smb_prdisp , pp - params ) ;
SSVAL ( outbuf , smb_drcnt , data_sent_thistime ) ;
if ( data_sent_thistime = = 0 )
{
SSVAL ( outbuf , smb_droff , 0 ) ;
SSVAL ( outbuf , smb_drdisp , 0 ) ;
}
else
{
/* The offset of the data bytes is the offset of the
parameter bytes plus the number of parameters being sent this time */
SSVAL ( outbuf , smb_droff , ( ( smb_buf ( outbuf ) + alignment_offset ) -
smb_base ( outbuf ) ) + params_sent_thistime + data_alignment_offset ) ;
SSVAL ( outbuf , smb_drdisp , pd - pdata ) ;
}
/* Copy the param bytes into the packet */
if ( params_sent_thistime )
memcpy ( ( smb_buf ( outbuf ) + alignment_offset ) , pp , params_sent_thistime ) ;
/* Copy in the data bytes */
if ( data_sent_thistime )
memcpy ( smb_buf ( outbuf ) + alignment_offset + params_sent_thistime +
data_alignment_offset , pd , data_sent_thistime ) ;
DEBUG ( 9 , ( " t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d \n " ,
params_sent_thistime , data_sent_thistime , useable_space ) ) ;
DEBUG ( 9 , ( " t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d \n " ,
params_to_send , data_to_send , paramsize , datasize ) ) ;
/* Send the packet */
send_smb ( Client , outbuf ) ;
pp + = params_sent_thistime ;
pd + = data_sent_thistime ;
params_to_send - = params_sent_thistime ;
data_to_send - = data_sent_thistime ;
/* Sanity check */
if ( params_to_send < 0 | | data_to_send < 0 )
1996-05-04 11:50:46 +04:00
{
1998-07-09 04:41:32 +04:00
DEBUG ( 0 , ( " send_trans2_replies failed sanity check pts = %d, dts = %d \n !!! " ,
params_to_send , data_to_send ) ) ;
return - 1 ;
1996-05-04 11:50:46 +04:00
}
1998-07-09 04:41:32 +04:00
}
1996-05-04 11:50:46 +04:00
return 0 ;
}
/****************************************************************************
reply to a TRANSACT2_OPEN
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_trans2open ( connection_struct * conn , char * inbuf , char * outbuf ,
int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
char * params = * pparams ;
int16 open_mode = SVAL ( params , 2 ) ;
int16 open_attr = SVAL ( params , 6 ) ;
1997-09-26 23:26:56 +04:00
BOOL oplock_request = ( ( ( SVAL ( params , 0 ) | ( 1 < < 1 ) ) > > 1 ) | ( ( SVAL ( params , 0 ) | ( 1 < < 2 ) ) > > 1 ) ) ;
1996-05-04 11:50:46 +04:00
#if 0
BOOL return_additional_info = BITSETW ( params , 0 ) ;
int16 open_sattr = SVAL ( params , 4 ) ;
time_t open_time = make_unix_date3 ( params + 8 ) ;
# endif
int16 open_ofun = SVAL ( params , 12 ) ;
int32 open_size = IVAL ( params , 14 ) ;
char * pname = & params [ 28 ] ;
int16 namelen = strlen ( pname ) + 1 ;
pstring fname ;
1998-09-17 23:16:12 +04:00
mode_t unixmode ;
1998-09-03 22:40:31 +04:00
SMB_OFF_T size = 0 ;
int fmode = 0 , mtime = 0 , rmode ;
1998-09-01 00:20:54 +04:00
SMB_INO_T inode = 0 ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT sbuf ;
1996-05-04 11:50:46 +04:00
int smb_action = 0 ;
1997-08-21 00:32:23 +04:00
BOOL bad_path = False ;
1998-07-31 01:18:57 +04:00
files_struct * fsp ;
1996-05-04 11:50:46 +04:00
StrnCpy ( fname , pname , namelen ) ;
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " trans2open %s mode=%d attr=%d ofun=%d size=%d \n " ,
fname , open_mode , open_attr , open_ofun , open_size ) ) ;
1996-05-04 11:50:46 +04:00
/* XXXX we need to handle passed times, sattr and flags */
1999-12-13 16:27:58 +03:00
unix_convert ( fname , conn , 0 , & bad_path , NULL ) ;
1996-05-04 11:50:46 +04:00
1998-08-16 06:32:55 +04:00
fsp = file_new ( ) ;
1998-08-15 11:27:34 +04:00
if ( ! fsp )
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRSRV , ERRnofids ) ) ;
1998-08-14 21:38:29 +04:00
if ( ! check_name ( fname , conn ) )
1997-08-21 00:32:23 +04:00
{
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1998-08-15 11:27:34 +04:00
file_free ( fsp ) ;
1996-05-04 11:50:46 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1997-08-21 00:32:23 +04:00
}
1996-05-04 11:50:46 +04:00
2000-01-14 04:41:04 +03:00
unixmode = unix_mode ( conn , open_attr | aARCH , fname ) ;
1996-05-04 11:50:46 +04:00
1998-08-15 11:27:34 +04:00
open_file_shared ( fsp , conn , fname , open_mode , open_ofun , unixmode ,
1997-09-26 23:26:56 +04:00
oplock_request , & rmode , & smb_action ) ;
1996-05-04 11:50:46 +04:00
1998-07-31 01:18:57 +04:00
if ( ! fsp - > open )
1997-08-21 00:32:23 +04:00
{
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1998-08-15 11:27:34 +04:00
file_free ( fsp ) ;
1996-05-04 11:50:46 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1997-08-21 00:32:23 +04:00
}
1996-05-04 11:50:46 +04:00
2000-02-03 08:17:25 +03:00
if ( fsp - > conn - > vfs_ops . fstat ( fsp - > fd_ptr - > fd , & sbuf ) ! = 0 ) {
1998-08-15 11:27:34 +04:00
close_file ( fsp , False ) ;
1998-10-04 13:42:51 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1996-05-04 11:50:46 +04:00
}
size = sbuf . st_size ;
1998-08-14 21:38:29 +04:00
fmode = dos_mode ( conn , fname , & sbuf ) ;
1996-05-04 11:50:46 +04:00
mtime = sbuf . st_mtime ;
inode = sbuf . st_ino ;
if ( fmode & aDIR ) {
1998-08-15 11:27:34 +04:00
close_file ( fsp , False ) ;
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
}
/* Realloc the size of parameters and data we will return */
params = * pparams = Realloc ( * pparams , 28 ) ;
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
1999-12-13 16:27:58 +03:00
memset ( ( char * ) params , ' \0 ' , 28 ) ;
1998-08-15 11:27:34 +04:00
SSVAL ( params , 0 , fsp - > fnum ) ;
1996-05-04 11:50:46 +04:00
SSVAL ( params , 2 , fmode ) ;
put_dos_date2 ( params , 4 , mtime ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( params , 8 , ( uint32 ) size ) ;
1996-05-04 11:50:46 +04:00
SSVAL ( params , 12 , rmode ) ;
1998-08-14 21:38:29 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
1997-09-26 23:26:56 +04:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
1996-10-05 14:41:13 +04:00
}
1996-05-04 11:50:46 +04:00
SSVAL ( params , 18 , smb_action ) ;
1998-09-01 00:20:54 +04:00
/*
* WARNING - this may need to be changed if SMB_INO_T < > 4 bytes .
*/
1996-05-04 11:50:46 +04:00
SIVAL ( params , 20 , inode ) ;
/* Send the required number of replies */
send_trans2_replies ( outbuf , bufsize , params , 28 , * ppdata , 0 ) ;
return - 1 ;
}
/****************************************************************************
get a level dependent lanman2 dir entry .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static BOOL get_lanman2_dir_entry ( connection_struct * conn ,
1998-08-14 21:38:29 +04:00
char * path_mask , int dirtype , int info_level ,
1996-05-04 11:50:46 +04:00
int requires_resume_key ,
BOOL dont_descend , char * * ppdata ,
char * base_data , int space_remaining ,
1999-12-13 16:27:58 +03:00
BOOL * out_of_space , BOOL * got_exact_match ,
1996-05-04 11:50:46 +04:00
int * last_name_off )
{
char * dname ;
BOOL found = False ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT sbuf ;
1996-05-04 11:50:46 +04:00
pstring mask ;
pstring pathreal ;
pstring fname ;
char * p , * pdata = * ppdata ;
1998-02-26 22:53:55 +03:00
uint32 reskey = 0 ;
int prev_dirpos = 0 ;
1996-05-04 11:50:46 +04:00
int mode = 0 ;
1998-09-03 22:40:31 +04:00
SMB_OFF_T size = 0 ;
uint32 len ;
1998-09-17 23:16:12 +04:00
time_t mdate = 0 , adate = 0 , cdate = 0 ;
1996-06-04 10:42:03 +04:00
char * nameptr ;
1996-05-04 11:50:46 +04:00
BOOL was_8_3 ;
1997-02-23 08:18:09 +03:00
int nt_extmode ; /* Used for NT connections instead of mode */
1998-08-14 21:38:29 +04:00
BOOL needslash = ( conn - > dirpath [ strlen ( conn - > dirpath ) - 1 ] ! = ' / ' ) ;
1996-05-04 11:50:46 +04:00
* fname = 0 ;
* out_of_space = False ;
1999-12-13 16:27:58 +03:00
* got_exact_match = False ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( ! conn - > dirptr )
1996-05-04 11:50:46 +04:00
return ( False ) ;
p = strrchr ( path_mask , ' / ' ) ;
if ( p ! = NULL )
1998-09-03 22:40:31 +04:00
{
if ( p [ 1 ] = = ' \0 ' )
pstrcpy ( mask , " *.* " ) ;
else
pstrcpy ( mask , p + 1 ) ;
}
1996-05-04 11:50:46 +04:00
else
1997-09-26 22:55:29 +04:00
pstrcpy ( mask , path_mask ) ;
1996-05-04 11:50:46 +04:00
while ( ! found )
1998-09-03 22:40:31 +04:00
{
1999-12-13 16:27:58 +03:00
BOOL got_match ;
1998-09-03 22:40:31 +04:00
/* Needed if we run out of space */
prev_dirpos = TellDir ( conn - > dirptr ) ;
dname = ReadDirName ( conn - > dirptr ) ;
1996-05-04 11:50:46 +04:00
1998-09-03 22:40:31 +04:00
/*
* Due to bugs in NT client redirectors we are not using
* resume keys any more - set them to zero .
* Check out the related comments in findfirst / findnext .
* JRA .
*/
1998-02-26 22:53:55 +03:00
1998-09-03 22:40:31 +04:00
reskey = 0 ;
1996-05-04 11:50:46 +04:00
1998-10-05 16:36:23 +04:00
DEBUG ( 8 , ( " get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d \n " ,
( long ) conn - > dirptr , TellDir ( conn - > dirptr ) ) ) ;
1996-05-04 11:50:46 +04:00
1998-09-03 22:40:31 +04:00
if ( ! dname )
return ( False ) ;
1996-05-04 11:50:46 +04:00
1998-09-03 22:40:31 +04:00
pstrcpy ( fname , dname ) ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
if ( ! ( got_match = * got_exact_match = exact_match ( fname , mask , case_sensitive ) ) )
got_match = mask_match ( fname , mask , case_sensitive , True ) ;
if ( ! got_match & & ! is_8_3 ( fname , False ) ) {
/*
* It turns out that NT matches wildcards against
* both long * and * short names . This may explain some
* of the wildcard wierdness from old DOS clients
* that some people have been seeing . . . . JRA .
*/
pstring newname ;
pstrcpy ( newname , fname ) ;
name_map_mangle ( newname , True , False , SNUM ( conn ) ) ;
if ( ! ( got_match = * got_exact_match = exact_match ( newname , mask , case_sensitive ) ) )
got_match = mask_match ( newname , mask , case_sensitive , True ) ;
}
if ( got_match )
1998-09-03 22:40:31 +04:00
{
BOOL isdots = ( strequal ( fname , " .. " ) | | strequal ( fname , " . " ) ) ;
if ( dont_descend & & ! isdots )
continue ;
1996-05-04 11:50:46 +04:00
1998-09-03 22:40:31 +04:00
pstrcpy ( pathreal , conn - > dirpath ) ;
if ( needslash )
pstrcat ( pathreal , " / " ) ;
pstrcat ( pathreal , dname ) ;
2000-02-03 08:17:25 +03:00
if ( conn - > vfs_ops . stat ( dos_to_unix ( pathreal , False ) , & sbuf ) ! = 0 )
1998-09-03 22:40:31 +04:00
{
DEBUG ( 5 , ( " get_lanman2_dir_entry:Couldn't stat [%s] (%s) \n " , pathreal , strerror ( errno ) ) ) ;
continue ;
}
mode = dos_mode ( conn , pathreal , & sbuf ) ;
if ( ! dir_check_ftype ( conn , mode , & sbuf , dirtype ) ) {
DEBUG ( 5 , ( " [%s] attribs didn't match %x \n " , fname , dirtype ) ) ;
continue ;
}
size = sbuf . st_size ;
mdate = sbuf . st_mtime ;
adate = sbuf . st_atime ;
cdate = get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ;
if ( mode & aDIR )
size = 0 ;
DEBUG ( 5 , ( " get_lanman2_dir_entry found %s fname=%s \n " , pathreal , fname ) ) ;
1996-05-04 11:50:46 +04:00
1998-09-03 22:40:31 +04:00
found = True ;
1996-05-04 11:50:46 +04:00
}
1998-09-03 22:40:31 +04:00
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
name_map_mangle ( fname , False , True , SNUM ( conn ) ) ;
1997-08-29 02:54:41 +04:00
1996-05-04 11:50:46 +04:00
p = pdata ;
1996-06-04 10:42:03 +04:00
nameptr = p ;
1996-05-04 11:50:46 +04:00
1998-05-26 23:37:31 +04:00
nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL ;
1997-02-23 08:18:09 +03:00
1996-05-04 11:50:46 +04:00
switch ( info_level )
1998-09-03 22:40:31 +04:00
{
1996-05-04 11:50:46 +04:00
case 1 :
if ( requires_resume_key ) {
1998-09-11 23:14:27 +04:00
SIVAL ( p , 0 , reskey ) ;
p + = 4 ;
1996-05-04 11:50:46 +04:00
}
put_dos_date2 ( p , l1_fdateCreation , cdate ) ;
put_dos_date2 ( p , l1_fdateLastAccess , adate ) ;
put_dos_date2 ( p , l1_fdateLastWrite , mdate ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( p , l1_cbFile , ( uint32 ) size ) ;
1998-11-16 02:07:54 +03:00
SIVAL ( p , l1_cbFileAlloc , SMB_ROUNDUP ( size , 1024 ) ) ;
1996-05-04 11:50:46 +04:00
SSVAL ( p , l1_attrFile , mode ) ;
SCVAL ( p , l1_cchName , strlen ( fname ) ) ;
1998-05-12 04:55:32 +04:00
pstrcpy ( p + l1_achName , fname ) ;
1996-06-04 10:42:03 +04:00
nameptr = p + l1_achName ;
1996-05-04 11:50:46 +04:00
p + = l1_achName + strlen ( fname ) + 1 ;
break ;
case 2 :
/* info_level 2 */
if ( requires_resume_key ) {
1998-09-11 23:14:27 +04:00
SIVAL ( p , 0 , reskey ) ;
p + = 4 ;
1996-05-04 11:50:46 +04:00
}
put_dos_date2 ( p , l2_fdateCreation , cdate ) ;
put_dos_date2 ( p , l2_fdateLastAccess , adate ) ;
put_dos_date2 ( p , l2_fdateLastWrite , mdate ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( p , l2_cbFile , ( uint32 ) size ) ;
1998-11-16 02:07:54 +03:00
SIVAL ( p , l2_cbFileAlloc , SMB_ROUNDUP ( size , 1024 ) ) ;
1996-05-04 11:50:46 +04:00
SSVAL ( p , l2_attrFile , mode ) ;
SIVAL ( p , l2_cbList , 0 ) ; /* No extended attributes */
SCVAL ( p , l2_cchName , strlen ( fname ) ) ;
1998-05-12 04:55:32 +04:00
pstrcpy ( p + l2_achName , fname ) ;
1996-06-04 10:42:03 +04:00
nameptr = p + l2_achName ;
1996-05-04 11:50:46 +04:00
p + = l2_achName + strlen ( fname ) + 1 ;
break ;
case 3 :
SIVAL ( p , 0 , reskey ) ;
put_dos_date2 ( p , 4 , cdate ) ;
put_dos_date2 ( p , 8 , adate ) ;
put_dos_date2 ( p , 12 , mdate ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( p , 16 , ( uint32 ) size ) ;
1998-11-16 02:07:54 +03:00
SIVAL ( p , 20 , SMB_ROUNDUP ( size , 1024 ) ) ;
1996-05-04 11:50:46 +04:00
SSVAL ( p , 24 , mode ) ;
SIVAL ( p , 26 , 4 ) ;
CVAL ( p , 30 ) = strlen ( fname ) ;
1998-05-12 04:55:32 +04:00
pstrcpy ( p + 31 , fname ) ;
1996-06-04 10:42:03 +04:00
nameptr = p + 31 ;
1996-05-04 11:50:46 +04:00
p + = 31 + strlen ( fname ) + 1 ;
break ;
case 4 :
if ( requires_resume_key ) {
1998-09-11 23:14:27 +04:00
SIVAL ( p , 0 , reskey ) ;
p + = 4 ;
1996-05-04 11:50:46 +04:00
}
SIVAL ( p , 0 , 33 + strlen ( fname ) + 1 ) ;
put_dos_date2 ( p , 4 , cdate ) ;
put_dos_date2 ( p , 8 , adate ) ;
put_dos_date2 ( p , 12 , mdate ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( p , 16 , ( uint32 ) size ) ;
1998-11-16 02:07:54 +03:00
SIVAL ( p , 20 , SMB_ROUNDUP ( size , 1024 ) ) ;
1996-05-04 11:50:46 +04:00
SSVAL ( p , 24 , mode ) ;
CVAL ( p , 32 ) = strlen ( fname ) ;
1998-05-12 04:55:32 +04:00
pstrcpy ( p + 33 , fname ) ;
1996-06-04 10:42:03 +04:00
nameptr = p + 33 ;
1996-05-04 11:50:46 +04:00
p + = 33 + strlen ( fname ) + 1 ;
break ;
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO :
1997-02-12 01:53:29 +03:00
was_8_3 = is_8_3 ( fname , True ) ;
1996-05-04 11:50:46 +04:00
len = 94 + strlen ( fname ) ;
len = ( len + 3 ) & ~ 3 ;
SIVAL ( p , 0 , len ) ; p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
put_long_date ( p , cdate ) ; p + = 8 ;
put_long_date ( p , adate ) ; p + = 8 ;
put_long_date ( p , mdate ) ; p + = 8 ;
put_long_date ( p , mdate ) ; p + = 8 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( p , 0 , size ) ;
SOFF_T ( p , 8 , size ) ;
1998-09-11 23:14:27 +04:00
p + = 16 ;
1997-02-23 08:18:09 +03:00
SIVAL ( p , 0 , nt_extmode ) ; p + = 4 ;
1996-05-04 11:50:46 +04:00
SIVAL ( p , 0 , strlen ( fname ) ) ; p + = 4 ;
SIVAL ( p , 0 , 0 ) ; p + = 4 ;
if ( ! was_8_3 ) {
1998-09-11 23:14:27 +04:00
pstrcpy ( p + 2 , fname ) ;
1999-12-13 16:27:58 +03:00
if ( ! name_map_mangle ( p + 2 , True , True , SNUM ( conn ) ) )
1998-09-11 23:14:27 +04:00
( p + 2 ) [ 12 ] = 0 ;
1996-05-04 11:50:46 +04:00
} else
1998-09-11 23:14:27 +04:00
* ( p + 2 ) = 0 ;
1996-05-04 11:50:46 +04:00
strupper ( p + 2 ) ;
SSVAL ( p , 0 , strlen ( p + 2 ) ) ;
p + = 2 + 24 ;
1996-06-04 10:42:03 +04:00
/* nameptr = p; */
1998-05-12 04:55:32 +04:00
pstrcpy ( p , fname ) ; p + = strlen ( p ) ;
1996-05-04 11:50:46 +04:00
p = pdata + len ;
break ;
case SMB_FIND_FILE_DIRECTORY_INFO :
len = 64 + strlen ( fname ) ;
len = ( len + 3 ) & ~ 3 ;
SIVAL ( p , 0 , len ) ; p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
put_long_date ( p , cdate ) ; p + = 8 ;
put_long_date ( p , adate ) ; p + = 8 ;
put_long_date ( p , mdate ) ; p + = 8 ;
put_long_date ( p , mdate ) ; p + = 8 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( p , 0 , size ) ;
SOFF_T ( p , 8 , size ) ;
1998-09-11 23:14:27 +04:00
p + = 16 ;
1997-02-23 08:18:09 +03:00
SIVAL ( p , 0 , nt_extmode ) ; p + = 4 ;
1996-05-04 11:50:46 +04:00
SIVAL ( p , 0 , strlen ( fname ) ) ; p + = 4 ;
1998-05-12 04:55:32 +04:00
pstrcpy ( p , fname ) ;
1996-05-04 11:50:46 +04:00
p = pdata + len ;
break ;
case SMB_FIND_FILE_FULL_DIRECTORY_INFO :
len = 68 + strlen ( fname ) ;
len = ( len + 3 ) & ~ 3 ;
SIVAL ( p , 0 , len ) ; p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
put_long_date ( p , cdate ) ; p + = 8 ;
put_long_date ( p , adate ) ; p + = 8 ;
put_long_date ( p , mdate ) ; p + = 8 ;
put_long_date ( p , mdate ) ; p + = 8 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( p , 0 , size ) ;
SOFF_T ( p , 8 , size ) ;
1998-09-11 23:14:27 +04:00
p + = 16 ;
1997-02-23 08:18:09 +03:00
SIVAL ( p , 0 , nt_extmode ) ; p + = 4 ;
1996-05-04 11:50:46 +04:00
SIVAL ( p , 0 , strlen ( fname ) ) ; p + = 4 ;
SIVAL ( p , 0 , 0 ) ; p + = 4 ;
1998-05-12 04:55:32 +04:00
pstrcpy ( p , fname ) ;
1996-05-04 11:50:46 +04:00
p = pdata + len ;
break ;
case SMB_FIND_FILE_NAMES_INFO :
len = 12 + strlen ( fname ) ;
len = ( len + 3 ) & ~ 3 ;
SIVAL ( p , 0 , len ) ; p + = 4 ;
SIVAL ( p , 0 , reskey ) ; p + = 4 ;
SIVAL ( p , 0 , strlen ( fname ) ) ; p + = 4 ;
1998-05-12 04:55:32 +04:00
pstrcpy ( p , fname ) ;
1996-05-04 11:50:46 +04:00
p = pdata + len ;
break ;
default :
return ( False ) ;
}
if ( PTR_DIFF ( p , pdata ) > space_remaining ) {
/* Move the dirptr back to prev_dirpos */
1998-08-14 21:38:29 +04:00
SeekDir ( conn - > dirptr , prev_dirpos ) ;
1996-05-04 11:50:46 +04:00
* out_of_space = True ;
DEBUG ( 9 , ( " get_lanman2_dir_entry: out of space \n " ) ) ;
return False ; /* Not finished - just out of space */
}
/* Setup the last_filename pointer, as an offset from base_data */
1996-06-04 10:42:03 +04:00
* last_name_off = PTR_DIFF ( nameptr , base_data ) ;
1996-05-04 11:50:46 +04:00
/* Advance the data pointer to the next slot */
* ppdata = p ;
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
return ( found ) ;
}
1998-07-29 04:27:23 +04:00
/****************************************************************************
Convert the directory masks formated for the wire .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void mask_convert ( char * mask )
{
/*
* We know mask is a pstring .
*/
char * p = mask ;
while ( * p ) {
if ( * p = = ' < ' ) {
pstring expnd ;
if ( p [ 1 ] ! = ' " ' & & p [ 1 ] ! = ' . ' ) {
pstrcpy ( expnd , p + 1 ) ;
* p + + = ' * ' ;
* p = ' . ' ;
safe_strcpy ( p + 1 , expnd , sizeof ( pstring ) - ( p - mask ) - 2 ) ;
} else
* p = ' * ' ;
}
if ( * p = = ' > ' ) * p = ' ? ' ;
if ( * p = = ' " ' ) * p = ' . ' ;
p + + ;
}
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a TRANS2_FINDFIRST .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-08-14 21:38:29 +04:00
static int call_trans2findfirst ( connection_struct * conn ,
char * inbuf , char * outbuf , int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
/* We must be careful here that we don't return more than the
allowed number of data bytes . If this means returning fewer than
maxentries then so be it . We assume that the redirector has
enough room for the fixed number of parameter bytes it has
requested . */
uint32 max_data_bytes = SVAL ( inbuf , smb_mdrcnt ) ;
char * params = * pparams ;
char * pdata = * ppdata ;
int dirtype = SVAL ( params , 0 ) ;
int maxentries = SVAL ( params , 2 ) ;
BOOL close_after_first = BITSETW ( params + 4 , 0 ) ;
BOOL close_if_end = BITSETW ( params + 4 , 1 ) ;
BOOL requires_resume_key = BITSETW ( params + 4 , 2 ) ;
int info_level = SVAL ( params , 6 ) ;
pstring directory ;
pstring mask ;
char * p , * wcard ;
int last_name_off = 0 ;
int dptr_num = - 1 ;
int numentries = 0 ;
int i ;
BOOL finished = False ;
BOOL dont_descend = False ;
BOOL out_of_space = False ;
int space_remaining ;
1997-08-21 00:32:23 +04:00
BOOL bad_path = False ;
1996-05-04 11:50:46 +04:00
* directory = * mask = 0 ;
DEBUG ( 3 , ( " call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d \n " ,
dirtype , maxentries , close_after_first , close_if_end , requires_resume_key ,
info_level , max_data_bytes ) ) ;
switch ( info_level )
{
case 1 :
case 2 :
case 3 :
case 4 :
case SMB_FIND_FILE_DIRECTORY_INFO :
case SMB_FIND_FILE_FULL_DIRECTORY_INFO :
case SMB_FIND_FILE_NAMES_INFO :
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO :
break ;
default :
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
}
1997-09-26 22:55:29 +04:00
pstrcpy ( directory , params + 12 ) ; /* Complete directory path with
1996-05-04 11:50:46 +04:00
wildcard mask appended */
2000-03-09 01:14:30 +03:00
RESOLVE_FINDFIRST_DFSPATH ( directory , conn , inbuf , outbuf ) ;
1996-05-04 11:50:46 +04:00
DEBUG ( 5 , ( " path=%s \n " , directory ) ) ;
1999-12-13 16:27:58 +03:00
unix_convert ( directory , conn , 0 , & bad_path , NULL ) ;
1998-08-14 21:38:29 +04:00
if ( ! check_name ( directory , conn ) ) {
1997-08-21 00:32:23 +04:00
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1997-10-04 00:36:06 +04:00
1997-10-09 22:40:52 +04:00
#if 0
/* Ugly - NT specific hack - maybe not needed ? (JRA) */
1997-10-04 00:36:06 +04:00
if ( ( errno = = ENOTDIR ) & & ( Protocol > = PROTOCOL_NT1 ) & &
( get_remote_arch ( ) = = RA_WINNT ) )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbaddirectory ;
}
1997-10-09 22:40:52 +04:00
# endif
1997-10-04 00:36:06 +04:00
1998-10-04 13:42:51 +04:00
return ( UNIXERROR ( ERRDOS , ERRbadpath ) ) ;
1996-05-04 11:50:46 +04:00
}
p = strrchr ( directory , ' / ' ) ;
if ( p = = NULL ) {
1998-05-12 04:55:32 +04:00
pstrcpy ( mask , directory ) ;
pstrcpy ( directory , " ./ " ) ;
1996-05-04 11:50:46 +04:00
} else {
1998-05-12 04:55:32 +04:00
pstrcpy ( mask , p + 1 ) ;
1996-05-04 11:50:46 +04:00
* p = 0 ;
}
DEBUG ( 5 , ( " dir=%s, mask = %s \n " , directory , mask ) ) ;
pdata = * ppdata = Realloc ( * ppdata , max_data_bytes + 1024 ) ;
if ( ! * ppdata )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
1999-12-13 16:27:58 +03:00
memset ( ( char * ) pdata , ' \0 ' , max_data_bytes + 1024 ) ;
1996-05-04 11:50:46 +04:00
/* Realloc the params space */
params = * pparams = Realloc ( * pparams , 10 ) ;
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
1999-12-13 16:27:58 +03:00
dptr_num = dptr_create ( conn , directory , False , True , SVAL ( inbuf , smb_pid ) ) ;
1996-05-04 11:50:46 +04:00
if ( dptr_num < 0 )
1998-10-04 13:42:51 +04:00
return ( UNIXERROR ( ERRDOS , ERRbadfile ) ) ;
1996-05-04 11:50:46 +04:00
1998-07-29 04:27:23 +04:00
/* Convert the formatted mask. */
mask_convert ( mask ) ;
1998-05-26 23:37:31 +04:00
1996-05-04 11:50:46 +04:00
/* Save the wildcard match and attribs we are using on this directory -
needed as lanman2 assumes these are being saved between calls */
if ( ! ( wcard = strdup ( mask ) ) ) {
1999-12-13 16:27:58 +03:00
dptr_close ( & dptr_num ) ;
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
}
dptr_set_wcard ( dptr_num , wcard ) ;
dptr_set_attr ( dptr_num , dirtype ) ;
DEBUG ( 4 , ( " dptr_num is %d, wcard = %s, attr = %d \n " , dptr_num , wcard , dirtype ) ) ;
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call . */
DEBUG ( 8 , ( " dirpath=<%s> dontdescend=<%s> \n " ,
1998-08-14 21:38:29 +04:00
conn - > dirpath , lp_dontdescend ( SNUM ( conn ) ) ) ) ;
if ( in_list ( conn - > dirpath , lp_dontdescend ( SNUM ( conn ) ) , case_sensitive ) )
1996-05-04 11:50:46 +04:00
dont_descend = True ;
p = pdata ;
space_remaining = max_data_bytes ;
out_of_space = False ;
for ( i = 0 ; ( i < maxentries ) & & ! finished & & ! out_of_space ; i + + )
1999-12-13 16:27:58 +03:00
{
BOOL got_exact_match ;
/* this is a heuristic to avoid seeking the dirptr except when
absolutely necessary . It allows for a filename of about 40 chars */
if ( space_remaining < DIRLEN_GUESS & & numentries > 0 )
1996-05-04 11:50:46 +04:00
{
1999-12-13 16:27:58 +03:00
out_of_space = True ;
finished = False ;
}
else
{
finished = ! get_lanman2_dir_entry ( conn , mask , dirtype , info_level ,
requires_resume_key , dont_descend ,
& p , pdata , space_remaining , & out_of_space , & got_exact_match ,
& last_name_off ) ;
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
if ( finished & & out_of_space )
finished = False ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
if ( ! finished & & ! out_of_space )
numentries + + ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
/*
* As an optimisation if we know we aren ' t looking
* for a wildcard name ( ie . the name matches the wildcard exactly )
* then we can finish on any ( first ) match .
* This speeds up large directory searches . JRA .
*/
if ( got_exact_match )
finished = True ;
space_remaining = max_data_bytes - PTR_DIFF ( p , pdata ) ;
}
1996-05-04 11:50:46 +04:00
/* Check if we can close the dirptr */
if ( close_after_first | | ( finished & & close_if_end ) )
1999-12-13 16:27:58 +03:00
{
DEBUG ( 5 , ( " call_trans2findfirst - (2) closing dptr_num %d \n " , dptr_num ) ) ;
dptr_close ( & dptr_num ) ;
}
1996-05-04 11:50:46 +04:00
1997-12-20 08:25:37 +03:00
/*
* If there are no matching entries we must return ERRDOS / ERRbadfile -
* from observation of NT .
*/
if ( numentries = = 0 )
1999-12-13 16:27:58 +03:00
{
dptr_close ( & dptr_num ) ;
1997-12-20 08:25:37 +03:00
return ( ERROR ( ERRDOS , ERRbadfile ) ) ;
1999-12-13 16:27:58 +03:00
}
1997-12-20 08:25:37 +03:00
1996-05-04 11:50:46 +04:00
/* At this point pdata points to numentries directory entries. */
/* Set up the return parameter block */
SSVAL ( params , 0 , dptr_num ) ;
SSVAL ( params , 2 , numentries ) ;
SSVAL ( params , 4 , finished ) ;
SSVAL ( params , 6 , 0 ) ; /* Never an EA error */
SSVAL ( params , 8 , last_name_off ) ;
send_trans2_replies ( outbuf , bufsize , params , 10 , pdata , PTR_DIFF ( p , pdata ) ) ;
if ( ( ! * directory ) & & dptr_path ( dptr_num ) )
1998-05-11 10:38:36 +04:00
slprintf ( directory , sizeof ( directory ) - 1 , " (%s) " , dptr_path ( dptr_num ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 4 , ( " %s mask=%s directory=%s dirtype=%d numentries=%d \n " ,
1998-08-01 02:39:15 +04:00
smb_fn_name ( CVAL ( inbuf , smb_com ) ) ,
1998-08-14 21:38:29 +04:00
mask , directory , dirtype , numentries ) ) ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
/*
* Force a name mangle here to ensure that the
* mask as an 8.3 name is top of the mangled cache .
* The reasons for this are subtle . Don ' t remove
* this code unless you know what you are doing
* ( see PR # 13758 ) . JRA .
*/
if ( ! is_8_3 ( mask , False ) )
name_map_mangle ( mask , True , True , SNUM ( conn ) ) ;
1996-05-04 11:50:46 +04:00
return ( - 1 ) ;
}
/****************************************************************************
reply to a TRANS2_FINDNEXT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_trans2findnext ( connection_struct * conn ,
char * inbuf , char * outbuf ,
int length , int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
/* We must be careful here that we don't return more than the
allowed number of data bytes . If this means returning fewer than
maxentries then so be it . We assume that the redirector has
enough room for the fixed number of parameter bytes it has
requested . */
int max_data_bytes = SVAL ( inbuf , smb_mdrcnt ) ;
char * params = * pparams ;
char * pdata = * ppdata ;
1999-12-13 16:27:58 +03:00
int dptr_num = SVAL ( params , 0 ) ;
1996-05-04 11:50:46 +04:00
int maxentries = SVAL ( params , 2 ) ;
uint16 info_level = SVAL ( params , 4 ) ;
uint32 resume_key = IVAL ( params , 6 ) ;
BOOL close_after_request = BITSETW ( params + 10 , 0 ) ;
BOOL close_if_end = BITSETW ( params + 10 , 1 ) ;
BOOL requires_resume_key = BITSETW ( params + 10 , 2 ) ;
BOOL continue_bit = BITSETW ( params + 10 , 3 ) ;
1998-02-26 22:53:55 +03:00
pstring resume_name ;
1996-05-04 11:50:46 +04:00
pstring mask ;
pstring directory ;
char * p ;
uint16 dirtype ;
int numentries = 0 ;
int i , last_name_off = 0 ;
BOOL finished = False ;
BOOL dont_descend = False ;
BOOL out_of_space = False ;
int space_remaining ;
1998-02-26 22:53:55 +03:00
* mask = * directory = * resume_name = 0 ;
pstrcpy ( resume_name , params + 12 ) ;
1996-05-04 11:50:46 +04:00
1998-02-26 22:53:55 +03:00
DEBUG ( 3 , ( " call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
close_after_request = % d , close_if_end = % d requires_resume_key = % d \
resume_key = % d resume name = % s continue = % d level = % d \ n " ,
1996-05-04 11:50:46 +04:00
dptr_num , max_data_bytes , maxentries , close_after_request , close_if_end ,
1998-02-26 22:53:55 +03:00
requires_resume_key , resume_key , resume_name , continue_bit , info_level ) ) ;
1996-05-04 11:50:46 +04:00
switch ( info_level )
{
case 1 :
case 2 :
case 3 :
case 4 :
case SMB_FIND_FILE_DIRECTORY_INFO :
case SMB_FIND_FILE_FULL_DIRECTORY_INFO :
case SMB_FIND_FILE_NAMES_INFO :
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO :
break ;
default :
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
}
pdata = * ppdata = Realloc ( * ppdata , max_data_bytes + 1024 ) ;
if ( ! * ppdata )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
1999-12-13 16:27:58 +03:00
memset ( ( char * ) pdata , ' \0 ' , max_data_bytes + 1024 ) ;
1996-05-04 11:50:46 +04:00
/* Realloc the params space */
params = * pparams = Realloc ( * pparams , 6 * SIZEOFWORD ) ;
if ( ! params )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
/* Check that the dptr is valid */
1998-08-14 21:38:29 +04:00
if ( ! ( conn - > dirptr = dptr_fetch_lanman2 ( dptr_num ) ) )
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRDOS , ERRnofiles ) ) ;
1998-08-14 21:38:29 +04:00
string_set ( & conn - > dirpath , dptr_path ( dptr_num ) ) ;
1996-05-04 11:50:46 +04:00
/* Get the wildcard mask from the dptr */
if ( ( p = dptr_wcard ( dptr_num ) ) = = NULL ) {
DEBUG ( 2 , ( " dptr_num %d has no wildcard \n " , dptr_num ) ) ;
return ( ERROR ( ERRDOS , ERRnofiles ) ) ;
}
1998-05-12 04:55:32 +04:00
pstrcpy ( mask , p ) ;
1998-08-14 21:38:29 +04:00
pstrcpy ( directory , conn - > dirpath ) ;
1996-05-04 11:50:46 +04:00
/* Get the attr mask from the dptr */
dirtype = dptr_attr ( dptr_num ) ;
1998-10-05 16:36:23 +04:00
DEBUG ( 3 , ( " dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d) \n " ,
1996-05-04 11:50:46 +04:00
dptr_num , mask , dirtype ,
1998-10-05 16:36:23 +04:00
( long ) conn - > dirptr ,
1998-08-14 21:38:29 +04:00
TellDir ( conn - > dirptr ) ) ) ;
1996-05-04 11:50:46 +04:00
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call . */
1998-08-14 21:38:29 +04:00
DEBUG ( 8 , ( " dirpath=<%s> dontdescend=<%s> \n " , conn - > dirpath , lp_dontdescend ( SNUM ( conn ) ) ) ) ;
if ( in_list ( conn - > dirpath , lp_dontdescend ( SNUM ( conn ) ) , case_sensitive ) )
1996-05-04 11:50:46 +04:00
dont_descend = True ;
p = pdata ;
space_remaining = max_data_bytes ;
out_of_space = False ;
1998-02-26 22:53:55 +03:00
/*
* Seek to the correct position . We no longer use the resume key but
* depend on the last file name instead .
*/
if ( requires_resume_key & & * resume_name & & ! continue_bit )
{
/*
* Fix for NT redirector problem triggered by resume key indexes
* changing between directory scans . We now return a resume key of 0
* and instead look for the filename to continue from ( also given
* to us by NT / 95 / smbfs / smbclient ) . If no other scans have been done between the
* findfirst / findnext ( as is usual ) then the directory pointer
* should already be at the correct place . Check this by scanning
* backwards looking for an exact ( ie . case sensitive ) filename match .
* If we get to the beginning of the directory and haven ' t found it then scan
* forwards again looking for a match . JRA .
*/
int current_pos , start_pos ;
1998-08-15 05:19:26 +04:00
char * dname = NULL ;
1998-08-14 21:38:29 +04:00
void * dirptr = conn - > dirptr ;
1998-02-26 22:53:55 +03:00
start_pos = TellDir ( dirptr ) ;
for ( current_pos = start_pos ; current_pos > = 0 ; current_pos - - )
{
1998-03-03 23:19:14 +03:00
DEBUG ( 7 , ( " call_trans2findnext: seeking to pos %d \n " , current_pos ) ) ;
1998-02-26 22:53:55 +03:00
SeekDir ( dirptr , current_pos ) ;
dname = ReadDirName ( dirptr ) ;
1998-08-11 00:12:53 +04:00
/*
* Remember , name_map_mangle is called by
* get_lanman2_dir_entry ( ) , so the resume name
* could be mangled . Ensure we do the same
* here .
*/
1998-08-15 05:19:26 +04:00
if ( dname ! = NULL )
1999-12-13 16:27:58 +03:00
name_map_mangle ( dname , False , True , SNUM ( conn ) ) ;
1998-08-11 00:12:53 +04:00
1998-02-26 22:53:55 +03:00
if ( dname & & strcsequal ( resume_name , dname ) )
{
SeekDir ( dirptr , current_pos + 1 ) ;
1998-03-03 23:19:14 +03:00
DEBUG ( 7 , ( " call_trans2findnext: got match at pos %d \n " , current_pos + 1 ) ) ;
1998-02-26 22:53:55 +03:00
break ;
}
}
/*
* Scan forward from start if not found going backwards .
*/
if ( current_pos < 0 )
{
1998-03-03 23:19:14 +03:00
DEBUG ( 7 , ( " call_trans2findnext: notfound: seeking to pos %d \n " , start_pos ) ) ;
1998-02-26 22:53:55 +03:00
SeekDir ( dirptr , start_pos ) ;
for ( current_pos = start_pos ; ( dname = ReadDirName ( dirptr ) ) ! = NULL ; SeekDir ( dirptr , + + current_pos ) )
{
1998-08-11 00:12:53 +04:00
/*
* Remember , name_map_mangle is called by
* get_lanman2_dir_entry ( ) , so the resume name
* could be mangled . Ensure we do the same
* here .
*/
1998-08-15 05:19:26 +04:00
if ( dname ! = NULL )
1999-12-13 16:27:58 +03:00
name_map_mangle ( dname , False , True , SNUM ( conn ) ) ;
1998-08-11 00:12:53 +04:00
1998-08-15 05:19:26 +04:00
if ( dname & & strcsequal ( resume_name , dname ) )
1998-02-26 22:53:55 +03:00
{
SeekDir ( dirptr , current_pos + 1 ) ;
1998-03-03 23:19:14 +03:00
DEBUG ( 7 , ( " call_trans2findnext: got match at pos %d \n " , current_pos + 1 ) ) ;
1998-02-26 22:53:55 +03:00
break ;
}
} /* end for */
} /* end if current_pos */
} /* end if requires_resume_key && !continue_bit */
1996-05-04 11:50:46 +04:00
for ( i = 0 ; ( i < ( int ) maxentries ) & & ! finished & & ! out_of_space ; i + + )
1999-12-13 16:27:58 +03:00
{
BOOL got_exact_match ;
/* this is a heuristic to avoid seeking the dirptr except when
absolutely necessary . It allows for a filename of about 40 chars */
if ( space_remaining < DIRLEN_GUESS & & numentries > 0 )
1996-05-04 11:50:46 +04:00
{
1999-12-13 16:27:58 +03:00
out_of_space = True ;
finished = False ;
}
else
{
finished = ! get_lanman2_dir_entry ( conn , mask , dirtype , info_level ,
requires_resume_key , dont_descend ,
& p , pdata , space_remaining , & out_of_space , & got_exact_match ,
& last_name_off ) ;
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
if ( finished & & out_of_space )
finished = False ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
if ( ! finished & & ! out_of_space )
numentries + + ;
/*
* As an optimisation if we know we aren ' t looking
* for a wildcard name ( ie . the name matches the wildcard exactly )
* then we can finish on any ( first ) match .
* This speeds up large directory searches . JRA .
*/
if ( got_exact_match )
finished = True ;
space_remaining = max_data_bytes - PTR_DIFF ( p , pdata ) ;
}
1996-05-04 11:50:46 +04:00
/* Check if we can close the dirptr */
if ( close_after_request | | ( finished & & close_if_end ) )
1999-12-13 16:27:58 +03:00
{
DEBUG ( 5 , ( " call_trans2findnext: closing dptr_num = %d \n " , dptr_num ) ) ;
dptr_close ( & dptr_num ) ; /* This frees up the saved mask */
}
1996-05-04 11:50:46 +04:00
/* Set up the return parameter block */
SSVAL ( params , 0 , numentries ) ;
SSVAL ( params , 2 , finished ) ;
SSVAL ( params , 4 , 0 ) ; /* Never an EA error */
SSVAL ( params , 6 , last_name_off ) ;
send_trans2_replies ( outbuf , bufsize , params , 8 , pdata , PTR_DIFF ( p , pdata ) ) ;
if ( ( ! * directory ) & & dptr_path ( dptr_num ) )
1998-05-11 10:38:36 +04:00
slprintf ( directory , sizeof ( directory ) - 1 , " (%s) " , dptr_path ( dptr_num ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " %s mask=%s directory=%s dirtype=%d numentries=%d \n " ,
1998-08-01 02:39:15 +04:00
smb_fn_name ( CVAL ( inbuf , smb_com ) ) ,
1998-08-14 21:38:29 +04:00
mask , directory , dirtype , numentries ) ) ;
1996-05-04 11:50:46 +04:00
return ( - 1 ) ;
}
/****************************************************************************
reply to a TRANS2_QFSINFO ( query filesystem info )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-11 23:14:27 +04:00
1998-08-14 21:38:29 +04:00
static int call_trans2qfsinfo ( connection_struct * conn ,
char * inbuf , char * outbuf ,
int length , int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
1999-12-13 16:27:58 +03:00
int max_data_bytes = SVAL ( inbuf , smb_mdrcnt ) ;
1996-05-04 11:50:46 +04:00
char * pdata = * ppdata ;
char * params = * pparams ;
uint16 info_level = SVAL ( params , 0 ) ;
int data_len ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT st ;
1998-08-14 21:38:29 +04:00
char * vname = volume_label ( SNUM ( conn ) ) ;
int snum = SNUM ( conn ) ;
1998-09-20 19:48:10 +04:00
char * fstype = lp_fstype ( SNUM ( conn ) ) ;
1998-09-23 05:25:33 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " call_trans2qfsinfo: level = %d \n " , info_level ) ) ;
1996-05-04 11:50:46 +04:00
2000-02-03 08:17:25 +03:00
if ( conn - > vfs_ops . stat ( " . " , & st ) ! = 0 ) {
1996-05-04 11:50:46 +04:00
DEBUG ( 2 , ( " call_trans2qfsinfo: stat of . failed (%s) \n " , strerror ( errno ) ) ) ;
return ( ERROR ( ERRSRV , ERRinvdevice ) ) ;
}
1999-12-13 16:27:58 +03:00
pdata = * ppdata = Realloc ( * ppdata , max_data_bytes + 1024 ) ;
memset ( ( char * ) pdata , ' \0 ' , max_data_bytes + 1024 ) ;
1996-05-04 11:50:46 +04:00
switch ( info_level )
1998-09-03 22:40:31 +04:00
{
1996-05-04 11:50:46 +04:00
case 1 :
1998-09-03 22:40:31 +04:00
{
1998-09-18 03:06:57 +04:00
SMB_BIG_UINT dfree , dsize , bsize ;
1998-09-03 22:40:31 +04:00
data_len = 18 ;
2000-02-03 08:17:25 +03:00
conn - > vfs_ops . disk_free ( " . " , False , & bsize , & dfree , & dsize ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( pdata , l1_idFileSystem , st . st_dev ) ;
SIVAL ( pdata , l1_cSectorUnit , bsize / 512 ) ;
SIVAL ( pdata , l1_cUnit , dsize ) ;
SIVAL ( pdata , l1_cUnitAvail , dfree ) ;
SSVAL ( pdata , l1_cbSector , 512 ) ;
1998-09-18 03:06:57 +04:00
DEBUG ( 5 , ( " call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d \n " ,
( unsigned int ) bsize , ( unsigned int ) st . st_dev , ( ( unsigned int ) bsize ) / 512 , ( unsigned int ) dsize ,
( unsigned int ) dfree , 512 ) ) ;
1998-09-03 22:40:31 +04:00
break ;
1996-05-04 11:50:46 +04:00
}
case 2 :
{
/* Return volume name */
int volname_len = MIN ( strlen ( vname ) , 11 ) ;
data_len = l2_vol_szVolLabel + volname_len + 1 ;
1998-02-11 14:07:14 +03:00
/*
* Add volume serial number - hash of a combination of
* the called hostname and the service name .
*/
1998-02-20 22:48:01 +03:00
SIVAL ( pdata , 0 , str_checksum ( lp_servicename ( snum ) ) ^ ( str_checksum ( local_machine ) < < 16 ) ) ;
1996-05-04 11:50:46 +04:00
SCVAL ( pdata , l2_vol_cch , volname_len ) ;
StrnCpy ( pdata + l2_vol_szVolLabel , vname , volname_len ) ;
1998-08-14 21:38:29 +04:00
DEBUG ( 5 , ( " call_trans2qfsinfo : time = %x, namelen = %d, name = %s \n " ,
( unsigned ) st . st_ctime , volname_len ,
1996-05-04 11:50:46 +04:00
pdata + l2_vol_szVolLabel ) ) ;
break ;
}
case SMB_QUERY_FS_ATTRIBUTE_INFO :
1999-12-13 16:27:58 +03:00
{
int fstype_len ;
SIVAL ( pdata , 0 , FILE_CASE_PRESERVED_NAMES | FILE_CASE_SENSITIVE_SEARCH |
2000-02-18 06:54:26 +03:00
FILE_DEVICE_IS_MOUNTED |
( lp_nt_acl_support ( ) ? FILE_PERSISTENT_ACLS : 0 ) ) ; /* FS ATTRIBUTES */
1998-07-17 05:38:08 +04:00
#if 0 /* Old code. JRA. */
1996-05-04 11:50:46 +04:00
SIVAL ( pdata , 0 , 0x4006 ) ; /* FS ATTRIBUTES == long filenames supported? */
1998-07-17 05:38:08 +04:00
# endif /* Old code. */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
SIVAL ( pdata , 4 , 128 ) ; /* Max filename component length */
2000-03-27 16:38:45 +04:00
fstype_len = dos_PutUniCode ( pdata + 12 , unix_to_dos ( fstype , False ) , sizeof ( pstring ) , False ) ;
1999-12-13 16:27:58 +03:00
SIVAL ( pdata , 8 , fstype_len ) ;
data_len = 12 + fstype_len ;
1998-09-18 03:06:57 +04:00
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_UNICODE_STRINGS ) ;
1996-05-04 11:50:46 +04:00
break ;
1999-12-13 16:27:58 +03:00
}
1996-05-04 11:50:46 +04:00
case SMB_QUERY_FS_LABEL_INFO :
data_len = 4 + strlen ( vname ) ;
SIVAL ( pdata , 0 , strlen ( vname ) ) ;
1998-05-12 04:55:32 +04:00
pstrcpy ( pdata + 4 , vname ) ;
1996-05-04 11:50:46 +04:00
break ;
case SMB_QUERY_FS_VOLUME_INFO :
1998-09-18 03:06:57 +04:00
1998-02-11 14:07:14 +03:00
/*
* Add volume serial number - hash of a combination of
* the called hostname and the service name .
*/
1998-09-23 05:25:33 +04:00
SIVAL ( pdata , 8 , str_checksum ( lp_servicename ( snum ) ) ^
( str_checksum ( local_machine ) < < 16 ) ) ;
/* NT4 always serves this up as unicode but expects it to be
* delivered as ascii ! ( tridge & & JRA )
*/
2000-03-28 06:38:59 +04:00
if ( ( get_remote_arch ( ) ! = RA_WIN2K ) & & ( global_client_caps & CAP_NT_SMBS ) ) {
1998-09-23 05:25:33 +04:00
data_len = 18 + strlen ( vname ) ;
SIVAL ( pdata , 12 , strlen ( vname ) ) ;
pstrcpy ( pdata + 18 , vname ) ;
} else {
data_len = 18 + 2 * strlen ( vname ) ;
SIVAL ( pdata , 12 , strlen ( vname ) * 2 ) ;
2000-03-27 16:38:45 +04:00
dos_PutUniCode ( pdata + 18 , unix_to_dos ( vname , False ) , sizeof ( pstring ) , False ) ;
2000-03-28 06:38:59 +04:00
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_UNICODE_STRINGS ) ;
1998-09-23 05:25:33 +04:00
}
DEBUG ( 5 , ( " call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s \n " ,
1999-12-13 16:27:58 +03:00
( int ) strlen ( vname ) , vname ) ) ;
1997-01-09 21:02:17 +03:00
break ;
1996-05-04 11:50:46 +04:00
case SMB_QUERY_FS_SIZE_INFO :
1998-09-03 22:40:31 +04:00
{
1998-09-18 03:06:57 +04:00
SMB_BIG_UINT dfree , dsize , bsize ;
1998-09-03 22:40:31 +04:00
data_len = 24 ;
2000-02-03 08:17:25 +03:00
conn - > vfs_ops . disk_free ( " . " , False , & bsize , & dfree , & dsize ) ;
1999-12-13 16:27:58 +03:00
SBIG_UINT ( pdata , 0 , dsize ) ;
SBIG_UINT ( pdata , 8 , dfree ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( pdata , 16 , bsize / 512 ) ;
SIVAL ( pdata , 20 , 512 ) ;
1996-05-04 11:50:46 +04:00
break ;
1998-09-03 22:40:31 +04:00
}
1996-05-04 11:50:46 +04:00
case SMB_QUERY_FS_DEVICE_INFO :
data_len = 8 ;
SIVAL ( pdata , 0 , 0 ) ; /* dev type */
SIVAL ( pdata , 4 , 0 ) ; /* characteristics */
break ;
1998-10-16 04:54:16 +04:00
case SMB_MAC_QUERY_FS_INFO :
1998-10-16 21:40:58 +04:00
/*
* Thursby MAC extension . . . ONLY on NTFS filesystems
* once we do streams then we don ' t need this
*/
if ( strequal ( lp_fstype ( SNUM ( conn ) ) , " NTFS " ) ) {
data_len = 88 ;
SIVAL ( pdata , 84 , 0x100 ) ; /* Don't support mac... */
break ;
}
/* drop through */
1996-05-04 11:50:46 +04:00
default :
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
1998-09-03 22:40:31 +04:00
}
1996-05-04 11:50:46 +04:00
send_trans2_replies ( outbuf , bufsize , params , 0 , pdata , data_len ) ;
1998-08-01 02:39:15 +04:00
DEBUG ( 4 , ( " %s info_level = %d \n " ,
smb_fn_name ( CVAL ( inbuf , smb_com ) ) , info_level ) ) ;
1996-05-04 11:50:46 +04:00
return - 1 ;
}
/****************************************************************************
reply to a TRANS2_SETFSINFO ( set filesystem info )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_trans2setfsinfo ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
/* Just say yes we did it - there is nothing that
can be set here so it doesn ' t matter . */
int outsize ;
DEBUG ( 3 , ( " call_trans2setfsinfo \n " ) ) ;
1998-08-14 21:38:29 +04:00
if ( ! CAN_WRITE ( conn ) )
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
outsize = set_message ( outbuf , 10 , 0 , True ) ;
return outsize ;
}
/****************************************************************************
1998-07-17 05:38:08 +04:00
Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO ( query file info by
file name or file id ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-07-17 05:38:08 +04:00
1998-08-14 21:38:29 +04:00
static int call_trans2qfilepathinfo ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize ,
1996-05-04 11:50:46 +04:00
char * * pparams , char * * ppdata ,
int total_data )
{
1999-12-13 16:27:58 +03:00
int max_data_bytes = SVAL ( inbuf , smb_mdrcnt ) ;
1996-05-04 11:50:46 +04:00
char * params = * pparams ;
char * pdata = * ppdata ;
uint16 tran_call = SVAL ( inbuf , smb_setup0 ) ;
uint16 info_level ;
int mode = 0 ;
1998-09-03 22:40:31 +04:00
SMB_OFF_T size = 0 ;
1996-05-04 11:50:46 +04:00
unsigned int data_size ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT sbuf ;
1996-05-04 11:50:46 +04:00
pstring fname1 ;
char * fname ;
char * p ;
1998-09-03 22:40:31 +04:00
int l ;
1998-10-20 07:17:43 +04:00
SMB_OFF_T pos = 0 ;
1997-08-21 00:32:23 +04:00
BOOL bad_path = False ;
1998-10-26 21:44:01 +03:00
BOOL delete_pending = False ;
1996-05-04 11:50:46 +04:00
if ( tran_call = = TRANSACT2_QFILEINFO ) {
1998-08-17 07:52:05 +04:00
files_struct * fsp = file_fsp ( params , 0 ) ;
1996-05-04 11:50:46 +04:00
info_level = SVAL ( params , 2 ) ;
1999-12-13 16:27:58 +03:00
DEBUG ( 3 , ( " call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d \n " , info_level ) ) ;
if ( fsp & & fsp - > open & & ( fsp - > is_directory | | fsp - > stat_open ) ) {
1998-10-20 07:17:43 +04:00
/*
* This is actually a QFILEINFO on a directory
* handle ( returned from an NT SMB ) . NT5 .0 seems
* to do this call . JRA .
*/
fname = fsp - > fsp_name ;
1999-12-13 16:27:58 +03:00
unix_convert ( fname , conn , 0 , & bad_path , & sbuf ) ;
2000-02-03 08:17:25 +03:00
if ( ! check_name ( fname , conn ) | |
( ! VALID_STAT ( sbuf ) & & conn - > vfs_ops . stat ( dos_to_unix ( fname , False ) , & sbuf ) ) ) {
1998-10-20 07:17:43 +04:00
DEBUG ( 3 , ( " fileinfo of %s failed (%s) \n " , fname , strerror ( errno ) ) ) ;
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
return ( UNIXERROR ( ERRDOS , ERRbadpath ) ) ;
}
1999-12-13 16:27:58 +03:00
delete_pending = fsp - > directory_delete_on_close ;
1998-10-20 07:17:43 +04:00
} else {
/*
* Original code - this is an open file .
*/
CHECK_FSP ( fsp , conn ) ;
CHECK_ERROR ( fsp ) ;
1996-05-04 11:50:46 +04:00
1998-10-20 07:17:43 +04:00
fname = fsp - > fsp_name ;
2000-02-03 08:17:25 +03:00
if ( fsp - > conn - > vfs_ops . fstat ( fsp - > fd_ptr - > fd , & sbuf ) ! = 0 ) {
1998-10-20 07:17:43 +04:00
DEBUG ( 3 , ( " fstat of fnum %d failed (%s) \n " , fsp - > fnum , strerror ( errno ) ) ) ;
return ( UNIXERROR ( ERRDOS , ERRbadfid ) ) ;
}
2000-02-03 08:17:25 +03:00
if ( ( pos = fsp - > conn - > vfs_ops . lseek ( fsp - > fd_ptr - > fd , 0 , SEEK_CUR ) ) = = - 1 )
1998-10-20 07:17:43 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1998-10-26 21:44:01 +03:00
delete_pending = fsp - > fd_ptr - > delete_on_close ;
1996-05-04 11:50:46 +04:00
}
} else {
/* qpathinfo */
info_level = SVAL ( params , 0 ) ;
1999-12-13 16:27:58 +03:00
DEBUG ( 3 , ( " call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d \n " , info_level ) ) ;
1996-05-04 11:50:46 +04:00
fname = & fname1 [ 0 ] ;
1997-09-26 22:55:29 +04:00
pstrcpy ( fname , & params [ 6 ] ) ;
2000-03-09 01:14:30 +03:00
RESOLVE_DFSPATH ( fname , conn , inbuf , outbuf ) ;
1999-12-13 16:27:58 +03:00
unix_convert ( fname , conn , 0 , & bad_path , & sbuf ) ;
2000-02-03 08:17:25 +03:00
if ( ! check_name ( fname , conn ) | |
( ! VALID_STAT ( sbuf ) & & conn - > vfs_ops . stat ( dos_to_unix ( fname , False ) , & sbuf ) ) ) {
1996-05-04 11:50:46 +04:00
DEBUG ( 3 , ( " fileinfo of %s failed (%s) \n " , fname , strerror ( errno ) ) ) ;
1997-08-21 00:32:23 +04:00
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1996-05-04 11:50:46 +04:00
return ( UNIXERROR ( ERRDOS , ERRbadpath ) ) ;
}
}
DEBUG ( 3 , ( " call_trans2qfilepathinfo %s level=%d call=%d total_data=%d \n " ,
fname , info_level , tran_call , total_data ) ) ;
p = strrchr ( fname , ' / ' ) ;
if ( ! p )
p = fname ;
else
p + + ;
l = strlen ( p ) ;
1998-08-14 21:38:29 +04:00
mode = dos_mode ( conn , fname , & sbuf ) ;
1996-05-04 11:50:46 +04:00
size = sbuf . st_size ;
if ( mode & aDIR ) size = 0 ;
1998-08-21 09:58:57 +04:00
/* from now on we only want the part after the / */
fname = p ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
params = * pparams = Realloc ( * pparams , 2 ) ;
memset ( ( char * ) params , ' \0 ' , 2 ) ;
data_size = max_data_bytes + 1024 ;
1996-05-04 11:50:46 +04:00
pdata = * ppdata = Realloc ( * ppdata , data_size ) ;
if ( total_data > 0 & & IVAL ( pdata , 0 ) = = total_data ) {
/* uggh, EAs for OS2 */
DEBUG ( 4 , ( " Rejecting EA request with total_data=%d \n " , total_data ) ) ;
return ( ERROR ( ERRDOS , ERROR_EAS_NOT_SUPPORTED ) ) ;
}
1999-12-13 16:27:58 +03:00
memset ( ( char * ) pdata , ' \0 ' , data_size ) ;
1996-05-04 11:50:46 +04:00
switch ( info_level )
{
1997-07-12 18:41:26 +04:00
case SMB_INFO_STANDARD :
case SMB_INFO_QUERY_EA_SIZE :
1996-05-04 11:50:46 +04:00
data_size = ( info_level = = 1 ? 22 : 26 ) ;
1998-08-14 21:38:29 +04:00
put_dos_date2 ( pdata , l1_fdateCreation , get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
1998-02-13 10:11:58 +03:00
put_dos_date2 ( pdata , l1_fdateLastAccess , sbuf . st_atime ) ;
put_dos_date2 ( pdata , l1_fdateLastWrite , sbuf . st_mtime ) ; /* write time */
1998-09-03 22:40:31 +04:00
SIVAL ( pdata , l1_cbFile , ( uint32 ) size ) ;
1998-11-16 02:07:54 +03:00
SIVAL ( pdata , l1_cbFileAlloc , SMB_ROUNDUP ( size , 1024 ) ) ;
1996-05-04 11:50:46 +04:00
SSVAL ( pdata , l1_attrFile , mode ) ;
SIVAL ( pdata , l1_attrFile + 2 , 4 ) ; /* this is what OS2 does */
break ;
1997-07-12 18:41:26 +04:00
case SMB_INFO_QUERY_EAS_FROM_LIST :
1996-05-04 11:50:46 +04:00
data_size = 24 ;
1998-08-14 21:38:29 +04:00
put_dos_date2 ( pdata , 0 , get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
1998-02-13 10:11:58 +03:00
put_dos_date2 ( pdata , 4 , sbuf . st_atime ) ;
1996-05-04 11:50:46 +04:00
put_dos_date2 ( pdata , 8 , sbuf . st_mtime ) ;
1998-09-03 22:40:31 +04:00
SIVAL ( pdata , 12 , ( uint32 ) size ) ;
1998-11-16 02:07:54 +03:00
SIVAL ( pdata , 16 , SMB_ROUNDUP ( size , 1024 ) ) ;
1996-05-04 11:50:46 +04:00
SIVAL ( pdata , 20 , mode ) ;
break ;
1997-07-12 18:41:26 +04:00
case SMB_INFO_QUERY_ALL_EAS :
1996-05-04 11:50:46 +04:00
data_size = 4 ;
SIVAL ( pdata , 0 , data_size ) ;
break ;
case 6 :
return ( ERROR ( ERRDOS , ERRbadfunc ) ) ; /* os/2 needs this */
case SMB_QUERY_FILE_BASIC_INFO :
1997-07-14 23:45:34 +04:00
data_size = 36 ; /* w95 returns 40 bytes not 36 - why ?. */
1998-08-14 21:38:29 +04:00
put_long_date ( pdata , get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
1998-02-13 10:11:58 +03:00
put_long_date ( pdata + 8 , sbuf . st_atime ) ;
1997-07-12 18:41:26 +04:00
put_long_date ( pdata + 16 , sbuf . st_mtime ) ; /* write time */
1997-07-14 23:45:34 +04:00
put_long_date ( pdata + 24 , sbuf . st_mtime ) ; /* change time */
1996-05-04 11:50:46 +04:00
SIVAL ( pdata , 32 , mode ) ;
1997-07-12 18:41:26 +04:00
DEBUG ( 5 , ( " SMB_QFBI - " ) ) ;
1998-01-24 11:49:21 +03:00
{
1998-08-14 21:38:29 +04:00
time_t create_time = get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ;
1998-01-24 11:49:21 +03:00
DEBUG ( 5 , ( " create: %s " , ctime ( & create_time ) ) ) ;
}
1998-02-13 10:11:58 +03:00
DEBUG ( 5 , ( " access: %s " , ctime ( & sbuf . st_atime ) ) ) ;
1997-07-12 18:41:26 +04:00
DEBUG ( 5 , ( " write: %s " , ctime ( & sbuf . st_mtime ) ) ) ;
1997-07-14 23:45:34 +04:00
DEBUG ( 5 , ( " change: %s " , ctime ( & sbuf . st_mtime ) ) ) ;
1997-07-12 18:41:26 +04:00
DEBUG ( 5 , ( " mode: %x \n " , mode ) ) ;
1996-05-04 11:50:46 +04:00
break ;
case SMB_QUERY_FILE_STANDARD_INFO :
data_size = 22 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( pdata , 0 , size ) ;
SOFF_T ( pdata , 8 , size ) ;
1996-05-04 11:50:46 +04:00
SIVAL ( pdata , 16 , sbuf . st_nlink ) ;
CVAL ( pdata , 20 ) = 0 ;
CVAL ( pdata , 21 ) = ( mode & aDIR ) ? 1 : 0 ;
break ;
case SMB_QUERY_FILE_EA_INFO :
data_size = 4 ;
break ;
1997-10-10 05:32:26 +04:00
/* Get the 8.3 name - used if NT SMB was negotiated. */
1996-05-04 11:50:46 +04:00
case SMB_QUERY_FILE_ALT_NAME_INFO :
1997-10-10 05:32:26 +04:00
{
pstring short_name ;
1998-07-17 05:38:08 +04:00
pstrcpy ( short_name , p ) ;
1997-10-10 05:32:26 +04:00
/* Mangle if not already 8.3 */
if ( ! is_8_3 ( short_name , True ) )
{
1999-12-13 16:27:58 +03:00
if ( ! name_map_mangle ( short_name , True , True , SNUM ( conn ) ) )
1997-10-10 05:32:26 +04:00
* short_name = ' \0 ' ;
}
1998-07-17 05:38:08 +04:00
strupper ( short_name ) ;
1999-12-13 16:27:58 +03:00
l = strlen ( short_name ) ;
2000-03-27 16:38:45 +04:00
dos_PutUniCode ( pdata + 4 , unix_to_dos ( short_name , False ) , sizeof ( pstring ) , False ) ;
1999-12-13 16:27:58 +03:00
data_size = 4 + ( 2 * l ) ;
SIVAL ( pdata , 0 , 2 * l ) ;
1997-10-10 05:32:26 +04:00
}
break ;
case SMB_QUERY_FILE_NAME_INFO :
1999-12-13 16:27:58 +03:00
/*
* The first part of this code is essential
* to get security descriptors to work on mapped
* drives . Don ' t ask how I discovered this unless
* you like hearing about me suffering . . . . : - ) . JRA .
*/
if ( strequal ( " . " , fname ) & & ( global_client_caps & CAP_UNICODE ) ) {
l = l * 2 ;
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_UNICODE_STRINGS ) ;
2000-03-27 16:38:45 +04:00
dos_PutUniCode ( pdata + 4 , unix_to_dos ( " \\ " , False ) , sizeof ( pstring ) , False ) ;
1999-12-13 16:27:58 +03:00
} else {
pstrcpy ( pdata + 4 , fname ) ;
}
1996-05-04 11:50:46 +04:00
data_size = 4 + l ;
SIVAL ( pdata , 0 , l ) ;
break ;
1997-10-10 05:32:26 +04:00
1996-05-04 11:50:46 +04:00
case SMB_QUERY_FILE_ALLOCATION_INFO :
case SMB_QUERY_FILE_END_OF_FILEINFO :
data_size = 8 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( pdata , 0 , size ) ;
1996-05-04 11:50:46 +04:00
break ;
case SMB_QUERY_FILE_ALL_INFO :
1998-08-14 21:38:29 +04:00
put_long_date ( pdata , get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
1998-02-13 10:11:58 +03:00
put_long_date ( pdata + 8 , sbuf . st_atime ) ;
1997-07-12 18:41:26 +04:00
put_long_date ( pdata + 16 , sbuf . st_mtime ) ; /* write time */
1997-07-14 23:45:34 +04:00
put_long_date ( pdata + 24 , sbuf . st_mtime ) ; /* change time */
1996-05-04 11:50:46 +04:00
SIVAL ( pdata , 32 , mode ) ;
pdata + = 40 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( pdata , 0 , size ) ;
SOFF_T ( pdata , 8 , size ) ;
1996-05-04 11:50:46 +04:00
SIVAL ( pdata , 16 , sbuf . st_nlink ) ;
1998-10-26 21:44:01 +03:00
CVAL ( pdata , 20 ) = delete_pending ;
1996-05-04 11:50:46 +04:00
CVAL ( pdata , 21 ) = ( mode & aDIR ) ? 1 : 0 ;
pdata + = 24 ;
1998-10-24 12:08:05 +04:00
SINO_T ( pdata , 0 , ( SMB_INO_T ) sbuf . st_ino ) ;
1996-05-04 11:50:46 +04:00
pdata + = 8 ; /* index number */
pdata + = 4 ; /* EA info */
if ( mode & aRONLY )
1998-09-11 23:14:27 +04:00
SIVAL ( pdata , 0 , 0xA9 ) ;
1996-05-04 11:50:46 +04:00
else
1998-09-11 23:14:27 +04:00
SIVAL ( pdata , 0 , 0xd01BF ) ;
1996-05-04 11:50:46 +04:00
pdata + = 4 ;
1998-10-26 21:44:01 +03:00
SOFF_T ( pdata , 0 , pos ) ; /* current offset */
1996-05-04 11:50:46 +04:00
pdata + = 8 ;
SIVAL ( pdata , 0 , mode ) ; /* is this the right sort of mode info? */
pdata + = 4 ;
pdata + = 4 ; /* alignment */
SIVAL ( pdata , 0 , l ) ;
1997-09-26 22:55:29 +04:00
pstrcpy ( pdata + 4 , fname ) ;
1996-05-04 11:50:46 +04:00
pdata + = 4 + l ;
data_size = PTR_DIFF ( pdata , ( * ppdata ) ) ;
break ;
1998-08-21 18:31:43 +04:00
#if 0
/* NT4 server just returns "invalid query" to this - if we try to answer
it then NTws gets a BSOD ! ( tridge ) */
1996-05-04 11:50:46 +04:00
case SMB_QUERY_FILE_STREAM_INFO :
data_size = 24 + l ;
SIVAL ( pdata , 0 , pos ) ;
SIVAL ( pdata , 4 , size ) ;
SIVAL ( pdata , 12 , size ) ;
SIVAL ( pdata , 20 , l ) ;
1997-09-26 22:55:29 +04:00
pstrcpy ( pdata + 24 , fname ) ;
1996-05-04 11:50:46 +04:00
break ;
1998-08-21 18:31:43 +04:00
# endif
1998-08-21 09:58:57 +04:00
1996-05-04 11:50:46 +04:00
default :
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
}
send_trans2_replies ( outbuf , bufsize , params , 2 , * ppdata , data_size ) ;
return ( - 1 ) ;
}
/****************************************************************************
reply to a TRANS2_SETFILEINFO ( set file info by fileid )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_trans2setfilepathinfo ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize , char * * pparams ,
1996-05-04 11:50:46 +04:00
char * * ppdata , int total_data )
{
char * params = * pparams ;
char * pdata = * ppdata ;
uint16 tran_call = SVAL ( inbuf , smb_setup0 ) ;
uint16 info_level ;
int mode = 0 ;
1998-09-03 22:40:31 +04:00
SMB_OFF_T size = 0 ;
1996-05-04 11:50:46 +04:00
struct utimbuf tvs ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT st ;
1996-05-04 11:50:46 +04:00
pstring fname1 ;
char * fname ;
int fd = - 1 ;
1997-08-21 00:32:23 +04:00
BOOL bad_path = False ;
1998-11-18 02:44:52 +03:00
files_struct * fsp = NULL ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( ! CAN_WRITE ( conn ) )
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
if ( tran_call = = TRANSACT2_SETFILEINFO ) {
1998-11-18 02:44:52 +03:00
fsp = file_fsp ( params , 0 ) ;
1998-11-20 01:37:33 +03:00
info_level = SVAL ( params , 2 ) ;
1998-11-18 02:44:52 +03:00
1999-12-13 16:27:58 +03:00
if ( fsp & & fsp - > open & & ( fsp - > is_directory | | fsp - > stat_open ) ) {
1998-10-21 20:58:34 +04:00
/*
* This is actually a SETFILEINFO on a directory
* handle ( returned from an NT SMB ) . NT5 .0 seems
* to do this call . JRA .
*/
fname = fsp - > fsp_name ;
1999-12-13 16:27:58 +03:00
unix_convert ( fname , conn , 0 , & bad_path , & st ) ;
2000-02-03 08:17:25 +03:00
if ( ! check_name ( fname , conn ) | |
( ! VALID_STAT ( st ) & & conn - > vfs_ops . stat ( dos_to_unix ( fname , False ) , & st ) ) ) {
1998-10-21 20:58:34 +04:00
DEBUG ( 3 , ( " fileinfo of %s failed (%s) \n " , fname , strerror ( errno ) ) ) ;
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
return ( UNIXERROR ( ERRDOS , ERRbadpath ) ) ;
}
} else {
/*
* Original code - this is an open file .
*/
CHECK_FSP ( fsp , conn ) ;
CHECK_ERROR ( fsp ) ;
1996-05-04 11:50:46 +04:00
1998-10-21 20:58:34 +04:00
fname = fsp - > fsp_name ;
fd = fsp - > fd_ptr - > fd ;
1996-05-04 11:50:46 +04:00
2000-02-03 08:17:25 +03:00
if ( fsp - > conn - > vfs_ops . fstat ( fd , & st ) ! = 0 ) {
1998-10-21 20:58:34 +04:00
DEBUG ( 3 , ( " fstat of fnum %d failed (%s) \n " , fsp - > fnum , strerror ( errno ) ) ) ;
return ( UNIXERROR ( ERRDOS , ERRbadfid ) ) ;
}
1996-05-04 11:50:46 +04:00
}
} else {
/* set path info */
info_level = SVAL ( params , 0 ) ;
fname = fname1 ;
1997-09-26 22:55:29 +04:00
pstrcpy ( fname , & params [ 6 ] ) ;
1999-12-13 16:27:58 +03:00
unix_convert ( fname , conn , 0 , & bad_path , & st ) ;
1998-08-14 21:38:29 +04:00
if ( ! check_name ( fname , conn ) )
1997-08-21 00:32:23 +04:00
{
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
return ( UNIXERROR ( ERRDOS , ERRbadpath ) ) ;
}
2000-02-03 08:17:25 +03:00
if ( ! VALID_STAT ( st ) & & conn - > vfs_ops . stat ( dos_to_unix ( fname , False ) , & st ) ! = 0 ) {
1996-05-04 11:50:46 +04:00
DEBUG ( 3 , ( " stat of %s failed (%s) \n " , fname , strerror ( errno ) ) ) ;
1997-08-21 00:32:23 +04:00
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
return ( UNIXERROR ( ERRDOS , ERRbadpath ) ) ;
1996-05-04 11:50:46 +04:00
}
}
DEBUG ( 3 , ( " call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d \n " ,
tran_call , fname , info_level , total_data ) ) ;
/* Realloc the parameter and data sizes */
1999-12-13 16:27:58 +03:00
params = * pparams = Realloc ( * pparams , 2 ) ;
1996-05-04 11:50:46 +04:00
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
1999-12-13 16:27:58 +03:00
SSVAL ( params , 0 , 0 ) ;
1996-05-04 11:50:46 +04:00
size = st . st_size ;
tvs . modtime = st . st_mtime ;
tvs . actime = st . st_atime ;
1998-08-14 21:38:29 +04:00
mode = dos_mode ( conn , fname , & st ) ;
1996-05-04 11:50:46 +04:00
if ( total_data > 0 & & IVAL ( pdata , 0 ) = = total_data ) {
/* uggh, EAs for OS2 */
DEBUG ( 4 , ( " Rejecting EA request with total_data=%d \n " , total_data ) ) ;
1997-08-26 05:28:27 +04:00
return ( ERROR ( ERRDOS , ERROR_EAS_NOT_SUPPORTED ) ) ;
1996-05-04 11:50:46 +04:00
}
switch ( info_level )
1997-07-12 18:41:26 +04:00
{
case SMB_INFO_STANDARD :
case SMB_INFO_QUERY_EA_SIZE :
1996-05-04 11:50:46 +04:00
{
1997-07-12 18:41:26 +04:00
/* access time */
1996-05-04 11:50:46 +04:00
tvs . actime = make_unix_date2 ( pdata + l1_fdateLastAccess ) ;
1997-07-12 18:41:26 +04:00
/* write time */
1996-05-04 11:50:46 +04:00
tvs . modtime = make_unix_date2 ( pdata + l1_fdateLastWrite ) ;
1997-07-12 18:41:26 +04:00
1996-05-04 11:50:46 +04:00
mode = SVAL ( pdata , l1_attrFile ) ;
size = IVAL ( pdata , l1_cbFile ) ;
break ;
1997-07-12 18:41:26 +04:00
}
1996-05-04 11:50:46 +04:00
1997-07-12 18:41:26 +04:00
/* XXXX um, i don't think this is right.
it ' s also not in the cifs6 . txt spec .
*/
case SMB_INFO_QUERY_EAS_FROM_LIST :
1996-05-04 11:50:46 +04:00
tvs . actime = make_unix_date2 ( pdata + 8 ) ;
tvs . modtime = make_unix_date2 ( pdata + 12 ) ;
size = IVAL ( pdata , 16 ) ;
mode = IVAL ( pdata , 24 ) ;
break ;
1997-07-12 18:41:26 +04:00
/* XXXX nor this. not in cifs6.txt, either. */
case SMB_INFO_QUERY_ALL_EAS :
1996-05-04 11:50:46 +04:00
tvs . actime = make_unix_date2 ( pdata + 8 ) ;
tvs . modtime = make_unix_date2 ( pdata + 12 ) ;
size = IVAL ( pdata , 16 ) ;
mode = IVAL ( pdata , 24 ) ;
break ;
case SMB_SET_FILE_BASIC_INFO :
1997-07-12 18:41:26 +04:00
{
1999-12-21 00:46:41 +03:00
/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
time_t write_time ;
time_t changed_time ;
1997-07-14 23:45:34 +04:00
/* Ignore create time at offset pdata. */
1997-07-12 18:41:26 +04:00
/* access time */
tvs . actime = interpret_long_date ( pdata + 8 ) ;
1999-12-21 00:46:41 +03:00
write_time = interpret_long_date ( pdata + 16 ) ;
changed_time = interpret_long_date ( pdata + 24 ) ;
1999-12-21 22:14:17 +03:00
tvs . modtime = MIN ( write_time , changed_time ) ;
1999-12-21 00:46:41 +03:00
/* Prefer a defined time to an undefined one. */
if ( tvs . modtime = = ( time_t ) 0 | | tvs . modtime = = ( time_t ) - 1 )
tvs . modtime = ( write_time = = ( time_t ) 0 | | write_time = = ( time_t ) - 1
? changed_time
: write_time ) ;
1997-07-12 18:41:26 +04:00
1997-09-12 00:17:32 +04:00
#if 0 /* Needs more testing... */
/* Test from Luke to prevent Win95 from
setting incorrect values here .
*/
if ( tvs . actime < tvs . modtime )
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
# endif /* Needs more testing... */
1997-07-12 18:41:26 +04:00
/* attributes */
mode = IVAL ( pdata , 32 ) ;
1996-05-04 11:50:46 +04:00
break ;
1997-07-12 18:41:26 +04:00
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
/*
* NT seems to use this call with a size of zero
* to mean truncate the file . JRA .
*/
case SMB_SET_FILE_ALLOCATION_INFO :
{
SMB_OFF_T newsize = IVAL ( pdata , 0 ) ;
# ifdef LARGE_SMB_OFF_T
newsize | = ( ( ( SMB_OFF_T ) IVAL ( pdata , 4 ) ) < < 32 ) ;
# else /* LARGE_SMB_OFF_T */
if ( IVAL ( pdata , 4 ) ! = 0 ) /* more than 32 bits? */
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
# endif /* LARGE_SMB_OFF_T */
DEBUG ( 10 , ( " call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f \n " , fname , ( double ) newsize ) ) ;
if ( newsize = = 0 )
size = 0 ;
break ;
}
1996-05-04 11:50:46 +04:00
case SMB_SET_FILE_END_OF_FILE_INFO :
1997-07-12 18:41:26 +04:00
{
1998-09-11 23:14:27 +04:00
size = IVAL ( pdata , 0 ) ;
# ifdef LARGE_SMB_OFF_T
size | = ( ( ( SMB_OFF_T ) IVAL ( pdata , 4 ) ) < < 32 ) ;
# else /* LARGE_SMB_OFF_T */
1996-05-04 11:50:46 +04:00
if ( IVAL ( pdata , 4 ) ! = 0 ) /* more than 32 bits? */
1997-07-12 18:41:26 +04:00
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
1998-09-11 23:14:27 +04:00
# endif /* LARGE_SMB_OFF_T */
1999-12-13 16:27:58 +03:00
DEBUG ( 10 , ( " call_trans2setfilepathinfo: Set end of file info for file %s to %.0f \n " , fname , ( double ) size ) ) ;
1996-05-04 11:50:46 +04:00
break ;
1997-07-12 18:41:26 +04:00
}
1996-05-04 11:50:46 +04:00
1998-09-11 23:14:27 +04:00
case SMB_SET_FILE_DISPOSITION_INFO : /* Set delete on close for open file. */
{
1998-11-24 02:55:33 +03:00
if ( ( tran_call = = TRANSACT2_SETFILEINFO ) & & ( fsp ! = NULL ) )
1998-10-23 21:25:14 +04:00
{
1998-10-23 07:34:50 +04:00
BOOL delete_on_close = ( CVAL ( pdata , 0 ) ? True : False ) ;
1998-09-11 23:14:27 +04:00
if ( fsp - > is_directory )
1999-12-13 16:27:58 +03:00
{
fsp - > directory_delete_on_close = delete_on_close ;
DEBUG ( 10 , ( " call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s \n " ,
delete_on_close ? " Added " : " Removed " , fsp - > fnum , fsp - > fsp_name ) ) ;
1998-10-23 07:34:50 +04:00
1999-12-13 16:27:58 +03:00
}
else if ( fsp - > stat_open )
{
DEBUG ( 10 , ( " call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s \n " ,
delete_on_close ? " Added " : " Removed " , fsp - > fnum , fsp - > fsp_name ) ) ;
}
else
1998-10-23 07:34:50 +04:00
{
/*
1999-12-13 16:27:58 +03:00
* We can only set the delete on close flag if
* the share mode contained ALLOW_SHARE_DELETE
1998-10-23 07:34:50 +04:00
*/
1999-12-13 16:27:58 +03:00
if ( lp_share_modes ( SNUM ( conn ) ) )
1998-10-23 07:34:50 +04:00
{
1999-12-13 16:27:58 +03:00
if ( ! GET_ALLOW_SHARE_DELETE ( fsp - > share_mode ) )
1998-10-23 07:52:28 +04:00
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
1998-10-23 21:25:14 +04:00
/*
1999-12-13 16:27:58 +03:00
* If the flag has been set then
* modify the share mode entry for all files we have open
* on this device and inode to tell other smbds we have
* changed the delete on close flag .
1998-10-23 21:25:14 +04:00
*/
1999-12-13 16:27:58 +03:00
if ( delete_on_close & & ! GET_DELETE_ON_CLOSE_FLAG ( fsp - > share_mode ) )
1998-10-23 21:25:14 +04:00
{
1999-12-13 16:27:58 +03:00
int i ;
files_struct * iterate_fsp ;
SMB_DEV_T dev = fsp - > fd_ptr - > dev ;
SMB_INO_T inode = fsp - > fd_ptr - > inode ;
int num_share_modes ;
share_mode_entry * current_shares = NULL ;
1999-12-21 12:25:59 +03:00
if ( lock_share_entry ( fsp - > conn , dev , inode ) = = False )
1999-12-13 16:27:58 +03:00
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
/*
* Before we allow this we need to ensure that all current opens
* on the file have the GET_ALLOW_SHARE_DELETE flag set . If they
* do not then we deny this ( as we are essentially deleting the
* file at this point .
*/
1999-12-21 12:25:59 +03:00
num_share_modes = get_share_modes ( conn , dev , inode , & current_shares ) ;
1999-12-13 16:27:58 +03:00
for ( i = 0 ; i < num_share_modes ; i + + )
1998-10-23 21:25:14 +04:00
{
1999-12-13 16:27:58 +03:00
if ( ! GET_ALLOW_SHARE_DELETE ( current_shares [ i ] . share_mode ) )
{
DEBUG ( 5 , ( " call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
1998-10-23 21:25:14 +04:00
file % s as a share exists that was not opened with FILE_DELETE access . \ n " ,
1999-12-13 16:27:58 +03:00
fsp - > fnum , fsp - > fsp_name ) ) ;
/*
* Release the lock .
*/
1998-10-23 21:25:14 +04:00
1999-12-21 12:25:59 +03:00
unlock_share_entry ( fsp - > conn , dev , inode ) ;
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
/*
* current_shares was malloced by get_share_modes - free it here .
*/
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
free ( ( char * ) current_shares ) ;
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
/*
* Even though share violation would be more appropriate here ,
* return ERRnoaccess as that ' s what NT does .
*/
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-10-23 21:25:14 +04:00
}
1999-12-13 16:27:58 +03:00
/*
* current_shares was malloced by get_share_modes - free it here .
*/
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
free ( ( char * ) current_shares ) ;
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
DEBUG ( 10 , ( " call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s \n " ,
delete_on_close ? " Adding " : " Removing " , fsp - > fnum , fsp - > fsp_name ) ) ;
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
/*
* Go through all files we have open on the same device and
* inode ( hanging off the same hash bucket ) and set the DELETE_ON_CLOSE_FLAG .
* Other smbd ' s that have this file open will have to fend for themselves . We
* take care of this ( rare ) case in close_file ( ) . See the comment there .
*/
1998-10-23 07:52:28 +04:00
1999-12-13 16:27:58 +03:00
for ( iterate_fsp = file_find_di_first ( dev , inode ) ; iterate_fsp ;
iterate_fsp = file_find_di_next ( iterate_fsp ) )
{
int new_share_mode = ( delete_on_close ?
( iterate_fsp - > share_mode | DELETE_ON_CLOSE_FLAG ) :
( iterate_fsp - > share_mode & ~ DELETE_ON_CLOSE_FLAG ) ) ;
1998-10-23 07:52:28 +04:00
1999-12-13 16:27:58 +03:00
DEBUG ( 10 , ( " call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
1998-10-23 07:44:57 +04:00
dev = % x , inode = % .0f from % x to % x \ n " ,
1999-12-13 16:27:58 +03:00
iterate_fsp - > fnum , iterate_fsp - > fsp_name , ( unsigned int ) dev ,
( double ) inode , iterate_fsp - > share_mode , new_share_mode ) ) ;
1998-10-23 07:44:57 +04:00
1999-12-21 12:25:59 +03:00
if ( modify_share_mode ( iterate_fsp , new_share_mode , iterate_fsp - > oplock_type ) = = False )
1999-12-13 16:27:58 +03:00
DEBUG ( 0 , ( " call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1998-10-23 07:44:57 +04:00
dev = % x , inode = % .0f \ n " , iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1999-12-13 16:27:58 +03:00
}
1998-10-23 07:34:50 +04:00
1999-12-13 16:27:58 +03:00
/*
* Set the delete on close flag in the reference
* counted struct . Delete when the last reference
* goes away .
*/
fsp - > fd_ptr - > delete_on_close = delete_on_close ;
1998-11-18 22:06:51 +03:00
1999-12-21 12:25:59 +03:00
unlock_share_entry ( fsp - > conn , dev , inode ) ;
1998-10-23 21:25:14 +04:00
1999-12-13 16:27:58 +03:00
DEBUG ( 10 , ( " call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s \n " ,
delete_on_close ? " Added " : " Removed " , fsp - > fnum , fsp - > fsp_name ) ) ;
1998-10-23 07:34:50 +04:00
1999-12-13 16:27:58 +03:00
} /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
} /* end if lp_share_modes() */
} /* end if is_directory. */
1998-09-11 23:14:27 +04:00
} else
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
break ;
}
1996-05-04 11:50:46 +04:00
default :
1997-07-12 18:41:26 +04:00
{
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
}
1997-07-12 18:41:26 +04:00
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
/* get some defaults (no modifications) if any info is zero or -1. */
if ( tvs . actime = = ( time_t ) 0 | | tvs . actime = = ( time_t ) - 1 )
tvs . actime = st . st_atime ;
if ( tvs . modtime = = ( time_t ) 0 | | tvs . modtime = = ( time_t ) - 1 )
tvs . modtime = st . st_mtime ;
1997-07-14 23:45:34 +04:00
DEBUG ( 6 , ( " actime: %s " , ctime ( & tvs . actime ) ) ) ;
DEBUG ( 6 , ( " modtime: %s " , ctime ( & tvs . modtime ) ) ) ;
1998-09-03 22:40:31 +04:00
DEBUG ( 6 , ( " size: %.0f " , ( double ) size ) ) ;
1997-07-14 23:45:34 +04:00
DEBUG ( 6 , ( " mode: %x \n " , mode ) ) ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
if ( ! ( ( info_level = = SMB_SET_FILE_END_OF_FILE_INFO ) | |
( info_level = = SMB_SET_FILE_ALLOCATION_INFO ) ) ) {
/*
* Only do this test if we are not explicitly
* changing the size of a file .
*/
if ( ! size )
size = st . st_size ;
}
1996-05-04 11:50:46 +04:00
1997-07-12 18:41:26 +04:00
/* Try and set the times, size and mode of this file -
if they are different from the current values
*/
1999-12-13 16:27:58 +03:00
if ( st . st_mtime ! = tvs . modtime | | st . st_atime ! = tvs . actime ) {
if ( fsp ! = NULL ) {
1998-11-18 02:44:52 +03:00
/*
* This was a setfileinfo on an open file .
* NT does this a lot . It ' s actually pointless
* setting the time here , as it will be overwritten
* on the next write , so we save the request
* away and will set it on file code . JRA .
*/
1999-12-13 16:27:58 +03:00
if ( tvs . modtime ! = ( time_t ) 0 & & tvs . modtime ! = ( time_t ) - 1 ) {
DEBUG ( 10 , ( " call_trans2setfilepathinfo: setting pending modtime to %s \n " ,
ctime ( & tvs . modtime ) ) ) ;
fsp - > pending_modtime = tvs . modtime ;
}
} else {
DEBUG ( 10 , ( " call_trans2setfilepathinfo: setting utimes to modified values. \n " ) ) ;
if ( file_utime ( conn , fname , & tvs ) ! = 0 )
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1997-07-12 18:41:26 +04:00
}
1996-05-04 11:50:46 +04:00
}
1997-07-12 18:41:26 +04:00
/* check the mode isn't different, before changing it */
1999-12-13 16:27:58 +03:00
if ( ( mode ! = 0 ) & & ( mode ! = dos_mode ( conn , fname , & st ) ) ) {
DEBUG ( 10 , ( " call_trans2setfilepathinfo: file %s : setting dos mode %x \n " ,
fname , mode ) ) ;
if ( file_chmod ( conn , fname , mode , NULL ) ) {
DEBUG ( 2 , ( " chmod of %s failed (%s) \n " , fname , strerror ( errno ) ) ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1996-05-04 11:50:46 +04:00
}
1997-07-12 18:41:26 +04:00
1999-12-13 16:27:58 +03:00
if ( size ! = st . st_size ) {
DEBUG ( 10 , ( " call_trans2setfilepathinfo: file %s : setting new size to %.0f \n " ,
fname , ( double ) size ) ) ;
if ( fd = = - 1 ) {
2000-02-03 08:17:25 +03:00
fd = conn - > vfs_ops . open ( dos_to_unix ( fname , False ) , O_RDWR , 0 ) ;
1996-05-04 11:50:46 +04:00
if ( fd = = - 1 )
1998-10-04 13:42:51 +04:00
return ( UNIXERROR ( ERRDOS , ERRbadpath ) ) ;
2000-02-03 08:17:25 +03:00
set_filelen ( fd , size ) ; /* tpot vfs */
conn - > vfs_ops . close ( fd ) ;
1999-12-13 16:27:58 +03:00
} else {
2000-02-03 08:17:25 +03:00
set_filelen ( fd , size ) ; /* tpot vfs */
1996-05-04 11:50:46 +04:00
}
1999-12-13 16:27:58 +03:00
if ( fsp )
set_filelen_write_cache ( fsp , size ) ;
1996-05-04 11:50:46 +04:00
}
SSVAL ( params , 0 , 0 ) ;
send_trans2_replies ( outbuf , bufsize , params , 2 , * ppdata , 0 ) ;
return ( - 1 ) ;
}
/****************************************************************************
reply to a TRANS2_MKDIR ( make directory with extended attributes ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_trans2mkdir ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
char * params = * pparams ;
pstring directory ;
int ret = - 1 ;
1997-08-21 00:32:23 +04:00
BOOL bad_path = False ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( ! CAN_WRITE ( conn ) )
1996-05-04 11:50:46 +04:00
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
1997-09-26 22:55:29 +04:00
pstrcpy ( directory , & params [ 4 ] ) ;
1996-05-04 11:50:46 +04:00
DEBUG ( 3 , ( " call_trans2mkdir : name = %s \n " , directory ) ) ;
1999-12-13 16:27:58 +03:00
unix_convert ( directory , conn , 0 , & bad_path , NULL ) ;
1998-08-14 21:38:29 +04:00
if ( check_name ( directory , conn ) )
2000-02-03 08:17:25 +03:00
ret = conn - > vfs_ops . mkdir ( dos_to_unix ( directory , False ) ,
unix_mode ( conn , aDIR , directory ) ) ;
1996-05-04 11:50:46 +04:00
if ( ret < 0 )
{
DEBUG ( 5 , ( " call_trans2mkdir error (%s) \n " , strerror ( errno ) ) ) ;
1997-08-21 00:32:23 +04:00
if ( ( errno = = ENOENT ) & & bad_path )
{
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1996-05-04 11:50:46 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
/* Realloc the parameter and data sizes */
params = * pparams = Realloc ( * pparams , 2 ) ;
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
SSVAL ( params , 0 , 0 ) ;
send_trans2_replies ( outbuf , bufsize , params , 2 , * ppdata , 0 ) ;
return ( - 1 ) ;
}
/****************************************************************************
reply to a TRANS2_FINDNOTIFYFIRST ( start monitoring a directory for changes )
We don ' t actually do this - we just send a null response .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_trans2findnotifyfirst ( connection_struct * conn ,
char * inbuf , char * outbuf ,
int length , int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
static uint16 fnf_handle = 257 ;
char * params = * pparams ;
uint16 info_level = SVAL ( params , 4 ) ;
DEBUG ( 3 , ( " call_trans2findnotifyfirst - info_level %d \n " , info_level ) ) ;
switch ( info_level )
{
case 1 :
case 2 :
break ;
default :
return ( ERROR ( ERRDOS , ERRunknownlevel ) ) ;
}
/* Realloc the parameter and data sizes */
params = * pparams = Realloc ( * pparams , 6 ) ;
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
SSVAL ( params , 0 , fnf_handle ) ;
SSVAL ( params , 2 , 0 ) ; /* No changes */
SSVAL ( params , 4 , 0 ) ; /* No EA errors */
fnf_handle + + ;
if ( fnf_handle = = 0 )
fnf_handle = 257 ;
send_trans2_replies ( outbuf , bufsize , params , 6 , * ppdata , 0 ) ;
return ( - 1 ) ;
}
/****************************************************************************
reply to a TRANS2_FINDNOTIFYNEXT ( continue monitoring a directory for
changes ) . Currently this does nothing .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_trans2findnotifynext ( connection_struct * conn ,
char * inbuf , char * outbuf ,
int length , int bufsize ,
char * * pparams , char * * ppdata )
1996-05-04 11:50:46 +04:00
{
char * params = * pparams ;
DEBUG ( 3 , ( " call_trans2findnotifynext \n " ) ) ;
/* Realloc the parameter and data sizes */
params = * pparams = Realloc ( * pparams , 4 ) ;
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
SSVAL ( params , 0 , 0 ) ; /* No changes */
SSVAL ( params , 2 , 0 ) ; /* No EA errors */
send_trans2_replies ( outbuf , bufsize , params , 4 , * ppdata , 0 ) ;
return ( - 1 ) ;
}
2000-03-09 01:14:30 +03:00
/****************************************************************************
reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele < kalele @ veritas . com >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int call_trans2getdfsreferral ( connection_struct * conn , char * inbuf ,
char * outbuf , int length , int bufsize ,
char * * pparams , char * * ppdata )
{
char * params = * pparams ;
enum remote_arch_types ra_type = get_remote_arch ( ) ;
BOOL NT_arch = ( ( ra_type = = RA_WINNT ) | | ( ra_type = = RA_WIN2K ) ) ;
pstring pathname ;
int reply_size = 0 ;
int max_referral_level = SVAL ( params , 0 ) ;
2000-03-13 20:38:13 +03:00
2000-03-09 01:14:30 +03:00
DEBUG ( 10 , ( " call_trans2getdfsreferral \n " ) ) ;
2000-03-11 01:53:36 +03:00
2000-03-09 01:14:30 +03:00
if ( ! lp_host_msdfs ( ) )
return ( ERROR ( ERRDOS , ERRbadfunc ) ) ;
/* if pathname is in UNICODE, convert to DOS */
/* NT always sends in UNICODE, may not set UNICODE flag */
if ( NT_arch | | ( SVAL ( inbuf , smb_flg2 ) & FLAGS2_UNICODE_STRINGS ) )
{
unistr_to_dos ( pathname , & params [ 2 ] ) ;
DEBUG ( 10 , ( " UNICODE referral for %s \n " , pathname ) ) ;
}
else
pstrcpy ( pathname , & params [ 2 ] ) ;
if ( ( reply_size = setup_dfs_referral ( pathname , max_referral_level , ppdata ) ) < 0 )
return ( ERROR ( ERRDOS , ERRbadfile ) ) ;
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_UNICODE_STRINGS |
FLAGS2_DFS_PATHNAMES ) ;
send_trans2_replies ( outbuf , bufsize , 0 , 0 , * ppdata , reply_size ) ;
2000-03-11 01:53:36 +03:00
return ( - 1 ) ;
2000-03-09 01:14:30 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
reply to a SMBfindclose ( stop trans2 directory search )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_findclose ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
int outsize = 0 ;
1999-12-13 16:27:58 +03:00
int dptr_num = SVALS ( inbuf , smb_vwv0 ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " reply_findclose, dptr_num = %d \n " , dptr_num ) ) ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
dptr_close ( & dptr_num ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
outsize = set_message ( outbuf , 0 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " SMBfindclose dptr_num = %d \n " , dptr_num ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
reply to a SMBfindnclose ( stop FINDNOTIFYFIRST directory search )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_findnclose ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
int outsize = 0 ;
int dptr_num = - 1 ;
dptr_num = SVAL ( inbuf , smb_vwv0 ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " reply_findnclose, dptr_num = %d \n " , dptr_num ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
/* We never give out valid handles for a
findnotifyfirst - so any dptr_num is ok here .
Just ignore it . */
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
outsize = set_message ( outbuf , 0 , 0 , True ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " SMB_findnclose dptr_num = %d \n " , dptr_num ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
reply to a SMBtranss2 - just ignore it !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_transs2 ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
DEBUG ( 4 , ( " Ignoring transs2 of length %d \n " , length ) ) ;
return ( - 1 ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
reply to a SMBtrans2
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_trans2 ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1996-05-04 11:50:46 +04:00
{
1998-08-14 21:38:29 +04:00
int outsize = 0 ;
unsigned int total_params = SVAL ( inbuf , smb_tpscnt ) ;
unsigned int total_data = SVAL ( inbuf , smb_tdscnt ) ;
1996-05-04 11:50:46 +04:00
#if 0
1998-08-14 21:38:29 +04:00
unsigned int max_param_reply = SVAL ( inbuf , smb_mprcnt ) ;
unsigned int max_data_reply = SVAL ( inbuf , smb_mdrcnt ) ;
unsigned int max_setup_fields = SVAL ( inbuf , smb_msrcnt ) ;
BOOL close_tid = BITSETW ( inbuf + smb_flags , 0 ) ;
BOOL no_final_response = BITSETW ( inbuf + smb_flags , 1 ) ;
int32 timeout = IVALS ( inbuf , smb_timeout ) ;
1996-05-04 11:50:46 +04:00
# endif
1998-08-14 21:38:29 +04:00
unsigned int suwcnt = SVAL ( inbuf , smb_suwcnt ) ;
unsigned int tran_call = SVAL ( inbuf , smb_setup0 ) ;
char * params = NULL , * data = NULL ;
int num_params , num_params_sofar , num_data , num_data_sofar ;
1998-04-01 00:55:14 +04:00
1998-08-14 21:38:29 +04:00
if ( global_oplock_break & & ( tran_call = = TRANSACT2_OPEN ) ) {
/* Queue this open message as we are the process of an
* oplock break . */
1998-04-01 00:55:14 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 2 , ( " reply_trans2: queueing message trans2open due to being " ) ) ;
DEBUGADD ( 2 , ( " in oplock break state. \n " ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
push_oplock_pending_smb_message ( inbuf , length ) ;
return - 1 ;
}
outsize = set_message ( outbuf , 0 , 0 , True ) ;
/* All trans2 messages we handle have smb_sucnt == 1 - ensure this
is so as a sanity check */
if ( suwcnt ! = 1 ) {
DEBUG ( 2 , ( " Invalid smb_sucnt in trans2 call \n " ) ) ;
return ( ERROR ( ERRSRV , ERRerror ) ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
/* Allocate the space for the maximum needed parameters and data */
if ( total_params > 0 )
params = ( char * ) malloc ( total_params ) ;
if ( total_data > 0 )
data = ( char * ) malloc ( total_data ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( ( total_params & & ! params ) | | ( total_data & & ! data ) ) {
DEBUG ( 2 , ( " Out of memory in reply_trans2 \n " ) ) ;
1998-09-29 03:55:09 +04:00
if ( params )
free ( params ) ;
if ( data )
free ( data ) ;
1998-08-14 21:38:29 +04:00
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
}
1997-11-19 02:30:49 +03:00
1998-08-14 21:38:29 +04:00
/* Copy the param and data bytes sent with this request into
the params buffer */
num_params = num_params_sofar = SVAL ( inbuf , smb_pscnt ) ;
num_data = num_data_sofar = SVAL ( inbuf , smb_dscnt ) ;
if ( num_params > total_params | | num_data > total_data )
exit_server ( " invalid params in reply_trans2 " ) ;
if ( params )
memcpy ( params , smb_base ( inbuf ) + SVAL ( inbuf , smb_psoff ) , num_params ) ;
if ( data )
memcpy ( data , smb_base ( inbuf ) + SVAL ( inbuf , smb_dsoff ) , num_data ) ;
if ( num_data_sofar < total_data | | num_params_sofar < total_params ) {
/* We need to send an interim response then receive the rest
of the parameter / data bytes */
outsize = set_message ( outbuf , 0 , 0 , True ) ;
send_smb ( Client , outbuf ) ;
while ( num_data_sofar < total_data | |
num_params_sofar < total_params ) {
BOOL ret ;
1998-09-23 05:48:45 +04:00
ret = receive_next_smb ( inbuf , bufsize , SMB_SECONDARY_WAIT ) ;
1998-08-14 21:38:29 +04:00
if ( ( ret & &
( CVAL ( inbuf , smb_com ) ! = SMBtranss2 ) ) | | ! ret ) {
outsize = set_message ( outbuf , 0 , 0 , True ) ;
if ( ret )
DEBUG ( 0 , ( " reply_trans2: Invalid secondary trans2 packet \n " ) ) ;
else
DEBUG ( 0 , ( " reply_trans2: %s in getting secondary trans2 response. \n " ,
( smb_read_error = = READ_ERROR ) ? " error " : " timeout " ) ) ;
if ( params )
free ( params ) ;
if ( data )
free ( data ) ;
return ( ERROR ( ERRSRV , ERRerror ) ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
/* Revise total_params and total_data in case
they have changed downwards */
total_params = SVAL ( inbuf , smb_tpscnt ) ;
total_data = SVAL ( inbuf , smb_tdscnt ) ;
num_params_sofar + = ( num_params = SVAL ( inbuf , smb_spscnt ) ) ;
num_data_sofar + = ( num_data = SVAL ( inbuf , smb_sdscnt ) ) ;
if ( num_params_sofar > total_params | | num_data_sofar > total_data )
exit_server ( " data overflow in trans2 " ) ;
memcpy ( & params [ SVAL ( inbuf , smb_spsdisp ) ] ,
smb_base ( inbuf ) + SVAL ( inbuf , smb_spsoff ) , num_params ) ;
memcpy ( & data [ SVAL ( inbuf , smb_sdsdisp ) ] ,
smb_base ( inbuf ) + SVAL ( inbuf , smb_sdsoff ) , num_data ) ;
}
}
if ( Protocol > = PROTOCOL_NT1 ) {
uint16 flg2 = SVAL ( outbuf , smb_flg2 ) ;
SSVAL ( outbuf , smb_flg2 , flg2 | 0x40 ) ; /* IS_LONG_NAME */
1996-05-04 11:50:46 +04:00
}
1998-08-14 21:38:29 +04:00
/* Now we must call the relevant TRANS2 function */
1999-12-13 16:27:58 +03:00
switch ( tran_call ) {
case TRANSACT2_OPEN :
outsize = call_trans2open ( conn ,
1998-08-14 21:38:29 +04:00
inbuf , outbuf , bufsize ,
& params , & data ) ;
1999-12-13 16:27:58 +03:00
break ;
case TRANSACT2_FINDFIRST :
outsize = call_trans2findfirst ( conn , inbuf , outbuf ,
bufsize , & params , & data ) ;
break ;
case TRANSACT2_FINDNEXT :
outsize = call_trans2findnext ( conn , inbuf , outbuf ,
length , bufsize ,
& params , & data ) ;
break ;
case TRANSACT2_QFSINFO :
outsize = call_trans2qfsinfo ( conn , inbuf , outbuf ,
length , bufsize , & params ,
& data ) ;
break ;
case TRANSACT2_SETFSINFO :
outsize = call_trans2setfsinfo ( conn , inbuf , outbuf ,
length , bufsize ,
& params , & data ) ;
break ;
case TRANSACT2_QPATHINFO :
case TRANSACT2_QFILEINFO :
outsize = call_trans2qfilepathinfo ( conn , inbuf , outbuf ,
length , bufsize ,
& params , & data , total_data ) ;
break ;
case TRANSACT2_SETPATHINFO :
case TRANSACT2_SETFILEINFO :
outsize = call_trans2setfilepathinfo ( conn , inbuf , outbuf ,
length , bufsize ,
& params , & data ,
total_data ) ;
break ;
case TRANSACT2_FINDNOTIFYFIRST :
outsize = call_trans2findnotifyfirst ( conn , inbuf , outbuf ,
length , bufsize ,
& params , & data ) ;
break ;
case TRANSACT2_FINDNOTIFYNEXT :
outsize = call_trans2findnotifynext ( conn , inbuf , outbuf ,
length , bufsize ,
& params , & data ) ;
break ;
case TRANSACT2_MKDIR :
outsize = call_trans2mkdir ( conn , inbuf , outbuf , length ,
bufsize , & params , & data ) ;
break ;
2000-03-09 01:14:30 +03:00
case TRANSACT2_GET_DFS_REFERRAL :
outsize = call_trans2getdfsreferral ( conn , inbuf , outbuf , length ,
bufsize , & params , & data ) ;
break ;
1999-12-13 16:27:58 +03:00
default :
/* Error in request */
DEBUG ( 2 , ( " Unknown request %d in trans2 call \n " , tran_call ) ) ;
if ( params )
free ( params ) ;
if ( data )
free ( data ) ;
return ( ERROR ( ERRSRV , ERRerror ) ) ;
1998-08-14 21:38:29 +04:00
}
/* As we do not know how many data packets will need to be
returned here the various call_trans2xxxx calls
must send their own . Thus a call_trans2xxx routine only
returns a value other than - 1 when it wants to send
an error packet .
*/
if ( params )
free ( params ) ;
if ( data )
free ( data ) ;
return outsize ; /* If a correct response was needed the
call_trans2xxx calls have already sent
it . If outsize ! = - 1 then it is returning */
1996-05-04 11:50:46 +04:00
}