2005-01-12 10:03:29 +03:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Andrew Tridgell 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-01-12 10:03:29 +03:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-01-12 10:03:29 +03:00
*/
/*
a composite API for loading a whole file into memory
*/
# include "includes.h"
# include "libcli/raw/libcliraw.h"
# include "libcli/composite/composite.h"
2005-09-26 15:47:55 +04:00
# include "libcli/smb_composite/smb_composite.h"
2005-01-12 10:03:29 +03:00
/* the stages of this call */
enum loadfile_stage { LOADFILE_OPEN , LOADFILE_READ , LOADFILE_CLOSE } ;
static void loadfile_handler ( struct smbcli_request * req ) ;
2005-01-17 00:58:28 +03:00
struct loadfile_state {
2005-01-22 05:51:39 +03:00
enum loadfile_stage stage ;
2005-01-17 00:58:28 +03:00
struct smb_composite_loadfile * io ;
2005-01-17 01:22:13 +03:00
struct smbcli_request * req ;
2005-01-17 00:58:28 +03:00
union smb_open * io_open ;
union smb_read * io_read ;
} ;
2005-01-12 10:03:29 +03:00
/*
setup for the close
*/
2005-01-31 11:30:44 +03:00
static NTSTATUS setup_close ( struct composite_context * c ,
2005-01-12 10:03:29 +03:00
struct smbcli_tree * tree , uint16_t fnum )
{
2005-09-26 15:47:55 +04:00
struct loadfile_state * state = talloc_get_type ( c - > private_data , struct loadfile_state ) ;
2005-01-17 00:58:28 +03:00
union smb_close * io_close ;
2005-01-12 10:03:29 +03:00
/* nothing to read, setup the close */
io_close = talloc ( c , union smb_close ) ;
NT_STATUS_HAVE_NO_MEMORY ( io_close ) ;
io_close - > close . level = RAW_CLOSE_CLOSE ;
2006-03-13 01:48:25 +03:00
io_close - > close . in . file . fnum = fnum ;
2005-01-12 10:03:29 +03:00
io_close - > close . in . write_time = 0 ;
2005-01-17 01:22:13 +03:00
state - > req = smb_raw_close_send ( tree , io_close ) ;
NT_STATUS_HAVE_NO_MEMORY ( state - > req ) ;
2005-01-12 10:03:29 +03:00
/* call the handler again when the close is done */
2005-01-17 01:22:13 +03:00
state - > req - > async . fn = loadfile_handler ;
2009-02-02 12:17:00 +03:00
state - > req - > async . private_data = c ;
2005-01-22 05:51:39 +03:00
state - > stage = LOADFILE_CLOSE ;
2005-01-12 10:03:29 +03:00
return NT_STATUS_OK ;
}
/*
called when the open is done - pull the results and setup for the
first readx , or close if the file is zero size
*/
2005-01-31 11:30:44 +03:00
static NTSTATUS loadfile_open ( struct composite_context * c ,
2005-01-12 10:03:29 +03:00
struct smb_composite_loadfile * io )
{
2005-09-26 15:47:55 +04:00
struct loadfile_state * state = talloc_get_type ( c - > private_data , struct loadfile_state ) ;
2005-01-17 01:22:13 +03:00
struct smbcli_tree * tree = state - > req - > tree ;
2005-01-12 10:03:29 +03:00
NTSTATUS status ;
2005-01-17 01:22:13 +03:00
status = smb_raw_open_recv ( state - > req , c , state - > io_open ) ;
2005-01-12 10:03:29 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
/* don't allow stupidly large loads */
2005-01-17 00:58:28 +03:00
if ( state - > io_open - > ntcreatex . out . size > 100 * 1000 * 1000 ) {
2005-01-12 10:03:29 +03:00
return NT_STATUS_INSUFFICIENT_RESOURCES ;
}
/* allocate space for the file data */
2005-01-17 00:58:28 +03:00
io - > out . size = state - > io_open - > ntcreatex . out . size ;
2005-01-12 10:03:29 +03:00
io - > out . data = talloc_array ( c , uint8_t , io - > out . size ) ;
NT_STATUS_HAVE_NO_MEMORY ( io - > out . data ) ;
if ( io - > out . size = = 0 ) {
2006-03-13 01:48:25 +03:00
return setup_close ( c , tree , state - > io_open - > ntcreatex . out . file . fnum ) ;
2005-01-12 10:03:29 +03:00
}
/* setup for the read */
2005-01-17 00:58:28 +03:00
state - > io_read = talloc ( c , union smb_read ) ;
NT_STATUS_HAVE_NO_MEMORY ( state - > io_read ) ;
2005-01-12 10:03:29 +03:00
2005-01-17 00:58:28 +03:00
state - > io_read - > readx . level = RAW_READ_READX ;
2006-03-13 01:48:25 +03:00
state - > io_read - > readx . in . file . fnum = state - > io_open - > ntcreatex . out . file . fnum ;
2005-01-17 00:58:28 +03:00
state - > io_read - > readx . in . offset = 0 ;
state - > io_read - > readx . in . mincnt = MIN ( 32768 , io - > out . size ) ;
state - > io_read - > readx . in . maxcnt = state - > io_read - > readx . in . mincnt ;
state - > io_read - > readx . in . remaining = 0 ;
2007-10-07 02:28:14 +04:00
state - > io_read - > readx . in . read_for_execute = false ;
2005-01-17 00:58:28 +03:00
state - > io_read - > readx . out . data = io - > out . data ;
2005-01-17 01:22:13 +03:00
state - > req = smb_raw_read_send ( tree , state - > io_read ) ;
NT_STATUS_HAVE_NO_MEMORY ( state - > req ) ;
2005-01-12 10:03:29 +03:00
/* call the handler again when the first read is done */
2005-01-17 01:22:13 +03:00
state - > req - > async . fn = loadfile_handler ;
2009-02-02 12:17:00 +03:00
state - > req - > async . private_data = c ;
2005-01-22 05:51:39 +03:00
state - > stage = LOADFILE_READ ;
2005-01-15 13:29:43 +03:00
2005-01-17 00:58:28 +03:00
talloc_free ( state - > io_open ) ;
2005-01-12 10:03:29 +03:00
return NT_STATUS_OK ;
}
/*
called when a read is done - pull the results and setup for the
next read , or close if the file is all done
*/
2005-01-31 11:30:44 +03:00
static NTSTATUS loadfile_read ( struct composite_context * c ,
2005-01-12 10:03:29 +03:00
struct smb_composite_loadfile * io )
{
2005-09-26 15:47:55 +04:00
struct loadfile_state * state = talloc_get_type ( c - > private_data , struct loadfile_state ) ;
2005-01-17 01:22:13 +03:00
struct smbcli_tree * tree = state - > req - > tree ;
2005-01-12 10:03:29 +03:00
NTSTATUS status ;
2005-01-17 01:22:13 +03:00
status = smb_raw_read_recv ( state - > req , state - > io_read ) ;
2005-01-12 10:03:29 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
/* we might be done */
2005-01-17 00:58:28 +03:00
if ( state - > io_read - > readx . in . offset +
state - > io_read - > readx . out . nread = = io - > out . size ) {
2006-03-13 01:48:25 +03:00
return setup_close ( c , tree , state - > io_read - > readx . in . file . fnum ) ;
2005-01-12 10:03:29 +03:00
}
/* setup for the next read */
2005-01-17 00:58:28 +03:00
state - > io_read - > readx . in . offset + = state - > io_read - > readx . out . nread ;
state - > io_read - > readx . in . mincnt = MIN ( 32768 , io - > out . size - state - > io_read - > readx . in . offset ) ;
state - > io_read - > readx . out . data = io - > out . data + state - > io_read - > readx . in . offset ;
2005-01-12 10:03:29 +03:00
2005-01-17 01:22:13 +03:00
state - > req = smb_raw_read_send ( tree , state - > io_read ) ;
NT_STATUS_HAVE_NO_MEMORY ( state - > req ) ;
2005-01-12 10:03:29 +03:00
/* call the handler again when the read is done */
2005-01-17 01:22:13 +03:00
state - > req - > async . fn = loadfile_handler ;
2009-02-02 12:17:00 +03:00
state - > req - > async . private_data = c ;
2005-01-12 10:03:29 +03:00
return NT_STATUS_OK ;
}
/*
called when the close is done , check the status and cleanup
*/
2005-01-31 11:30:44 +03:00
static NTSTATUS loadfile_close ( struct composite_context * c ,
2005-01-12 10:03:29 +03:00
struct smb_composite_loadfile * io )
{
2005-09-26 15:47:55 +04:00
struct loadfile_state * state = talloc_get_type ( c - > private_data , struct loadfile_state ) ;
2005-01-12 10:03:29 +03:00
NTSTATUS status ;
2005-01-17 01:22:13 +03:00
status = smbcli_request_simple_recv ( state - > req ) ;
2005-01-12 10:03:29 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2005-09-26 15:47:55 +04:00
c - > state = COMPOSITE_STATE_DONE ;
2005-01-12 10:03:29 +03:00
return NT_STATUS_OK ;
}
/*
handler for completion of a sub - request in loadfile
*/
static void loadfile_handler ( struct smbcli_request * req )
{
2009-02-02 12:17:00 +03:00
struct composite_context * c = ( struct composite_context * ) req - > async . private_data ;
2005-09-26 15:47:55 +04:00
struct loadfile_state * state = talloc_get_type ( c - > private_data , struct loadfile_state ) ;
2005-01-12 10:03:29 +03:00
/* when this handler is called, the stage indicates what
call has just finished */
2005-01-22 05:51:39 +03:00
switch ( state - > stage ) {
2005-01-12 10:03:29 +03:00
case LOADFILE_OPEN :
2005-01-23 11:16:16 +03:00
c - > status = loadfile_open ( c , state - > io ) ;
2005-01-12 10:03:29 +03:00
break ;
case LOADFILE_READ :
2005-01-23 11:16:16 +03:00
c - > status = loadfile_read ( c , state - > io ) ;
2005-01-12 10:03:29 +03:00
break ;
case LOADFILE_CLOSE :
2005-01-23 11:16:16 +03:00
c - > status = loadfile_close ( c , state - > io ) ;
2005-01-12 10:03:29 +03:00
break ;
}
2005-01-23 11:16:16 +03:00
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2005-09-26 15:47:55 +04:00
c - > state = COMPOSITE_STATE_ERROR ;
2005-01-23 11:16:16 +03:00
}
2005-09-26 15:47:55 +04:00
if ( c - > state > = COMPOSITE_STATE_DONE & &
2005-01-23 11:16:16 +03:00
c - > async . fn ) {
c - > async . fn ( c ) ;
2005-01-12 10:03:29 +03:00
}
}
/*
composite loadfile call - does an openx followed by a number of readx calls ,
followed by a close
*/
2005-01-31 11:30:44 +03:00
struct composite_context * smb_composite_loadfile_send ( struct smbcli_tree * tree ,
2005-01-12 10:03:29 +03:00
struct smb_composite_loadfile * io )
{
2005-01-31 11:30:44 +03:00
struct composite_context * c ;
2005-01-17 00:58:28 +03:00
struct loadfile_state * state ;
2005-01-12 10:03:29 +03:00
2005-01-31 11:30:44 +03:00
c = talloc_zero ( tree , struct composite_context ) ;
2005-01-12 10:03:29 +03:00
if ( c = = NULL ) goto failed ;
2005-01-17 00:58:28 +03:00
state = talloc ( c , struct loadfile_state ) ;
if ( state = = NULL ) goto failed ;
state - > io = io ;
2005-09-26 15:47:55 +04:00
c - > private_data = state ;
c - > state = COMPOSITE_STATE_IN_PROGRESS ;
2011-11-22 12:36:30 +04:00
c - > event_ctx = tree - > session - > transport - > ev ;
2005-01-12 10:03:29 +03:00
/* setup for the open */
2005-01-17 00:58:28 +03:00
state - > io_open = talloc_zero ( c , union smb_open ) ;
if ( state - > io_open = = NULL ) goto failed ;
2005-01-12 10:03:29 +03:00
2005-01-17 00:58:28 +03:00
state - > io_open - > ntcreatex . level = RAW_OPEN_NTCREATEX ;
state - > io_open - > ntcreatex . in . flags = NTCREATEX_FLAGS_EXTENDED ;
state - > io_open - > ntcreatex . in . access_mask = SEC_FILE_READ_DATA ;
state - > io_open - > ntcreatex . in . file_attr = FILE_ATTRIBUTE_NORMAL ;
state - > io_open - > ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE ;
state - > io_open - > ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
state - > io_open - > ntcreatex . in . impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS ;
state - > io_open - > ntcreatex . in . fname = io - > in . fname ;
2005-01-12 10:03:29 +03:00
/* send the open on its way */
2005-01-17 01:22:13 +03:00
state - > req = smb_raw_open_send ( tree , state - > io_open ) ;
if ( state - > req = = NULL ) goto failed ;
2005-01-12 10:03:29 +03:00
/* setup the callback handler */
2005-01-17 01:22:13 +03:00
state - > req - > async . fn = loadfile_handler ;
2009-02-02 12:17:00 +03:00
state - > req - > async . private_data = c ;
2005-01-22 05:51:39 +03:00
state - > stage = LOADFILE_OPEN ;
2005-01-12 10:03:29 +03:00
return c ;
failed :
talloc_free ( c ) ;
return NULL ;
}
/*
composite loadfile call - recv side
*/
2005-01-31 11:30:44 +03:00
NTSTATUS smb_composite_loadfile_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx )
2005-01-12 10:03:29 +03:00
{
NTSTATUS status ;
2005-01-31 11:30:44 +03:00
status = composite_wait ( c ) ;
2005-01-12 10:03:29 +03:00
2005-01-12 14:43:18 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
2005-09-26 15:47:55 +04:00
struct loadfile_state * state = talloc_get_type ( c - > private_data , struct loadfile_state ) ;
2005-01-17 00:58:28 +03:00
talloc_steal ( mem_ctx , state - > io - > out . data ) ;
2005-01-12 10:03:29 +03:00
}
talloc_free ( c ) ;
return status ;
}
/*
composite loadfile call - sync interface
*/
NTSTATUS smb_composite_loadfile ( struct smbcli_tree * tree ,
TALLOC_CTX * mem_ctx ,
struct smb_composite_loadfile * io )
{
2005-01-31 11:30:44 +03:00
struct composite_context * c = smb_composite_loadfile_send ( tree , io ) ;
2005-01-12 10:03:29 +03:00
return smb_composite_loadfile_recv ( c , mem_ctx ) ;
}
2005-01-23 03:51:20 +03:00