diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/client/client.c | 400 | ||||
-rw-r--r-- | source3/client/smbspool.c | 6 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 2 | ||||
-rw-r--r-- | source3/libsmb/clidfs.c | 154 | ||||
-rw-r--r-- | source3/libsmb/clientgen.c | 4 | ||||
-rw-r--r-- | source3/libsmb/cliprint.c | 105 |
7 files changed, 538 insertions, 135 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 466958b5ab..eb39dbf88b 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -245,7 +245,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \ libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \ libsmb/clistr.o lib/util_seaccess.o \ - libsmb/cliquota.o libsmb/clifsinfo.o \ + libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \ libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \ libsmb/clioplock.o $(ERRORMAP_OBJ) libsmb/clirap2.o \ $(DOSERR_OBJ) \ diff --git a/source3/client/client.c b/source3/client/client.c index a080444998..311b372666 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -28,7 +28,6 @@ #define REGISTER 0 #endif -struct cli_state *cli; extern BOOL in_client; static int port = 0; pstring cur_dir = "\\"; @@ -97,10 +96,169 @@ static unsigned int put_total_time_ms = 0; /* totals globals */ static double dir_total; -#define USENMB +struct client_connection { + struct client_connection *prev, *next; + struct cli_state *cli; +}; + +struct cli_state *cli; +struct client_connection *connections; + +/******************************************************************** + Return a connection to a server. +********************************************************************/ + +static struct cli_state *do_connect(const char *server, const char *share) +{ + struct cli_state *c; + struct nmb_name called, calling; + const char *server_n; + struct in_addr ip; + pstring servicename; + char *sharename; + + /* make a copy so we don't modify the global string 'service' */ + pstrcpy(servicename, share); + sharename = servicename; + if (*sharename == '\\') { + server = sharename+2; + sharename = strchr_m(server,'\\'); + if (!sharename) return NULL; + *sharename = 0; + sharename++; + } + + server_n = server; + + zero_ip(&ip); + + make_nmb_name(&calling, global_myname(), 0x0); + make_nmb_name(&called , server, name_type); + + again: + zero_ip(&ip); + if (have_ip) ip = dest_ip; + + /* have to open a new connection */ + if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) || + !cli_connect(c, server_n, &ip)) { + d_printf("Connection to %s failed\n", server_n); + return NULL; + } + + c->protocol = max_protocol; + c->use_kerberos = use_kerberos; + cli_setup_signing_state(c, cmdline_auth_info.signing_state); + + + if (!cli_session_request(c, &calling, &called)) { + char *p; + d_printf("session request to %s failed (%s)\n", + called.name, cli_errstr(c)); + cli_shutdown(c); + if ((p=strchr_m(called.name, '.'))) { + *p = 0; + goto again; + } + if (strcmp(called.name, "*SMBSERVER")) { + make_nmb_name(&called , "*SMBSERVER", 0x20); + goto again; + } + return NULL; + } + + DEBUG(4,(" session request ok\n")); + + if (!cli_negprot(c)) { + d_printf("protocol negotiation failed\n"); + cli_shutdown(c); + return NULL; + } + + if (!got_pass) { + char *pass = getpass("Password: "); + if (pass) { + pstrcpy(password, pass); + got_pass = 1; + } + } + + if (!cli_session_setup(c, username, + password, strlen(password), + password, strlen(password), + lp_workgroup())) { + /* if a password was not supplied then try again with a null username */ + if (password[0] || !username[0] || use_kerberos || + !cli_session_setup(c, "", "", 0, "", 0, lp_workgroup())) { + d_printf("session setup failed: %s\n", cli_errstr(c)); + if (NT_STATUS_V(cli_nt_error(c)) == + NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)) + d_printf("did you forget to run kinit?\n"); + cli_shutdown(c); + return NULL; + } + d_printf("Anonymous login successful\n"); + } + + if (*c->server_domain) { + DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n", + c->server_domain,c->server_os,c->server_type)); + } else if (*c->server_os || *c->server_type){ + DEBUG(1,("OS=[%s] Server=[%s]\n", + c->server_os,c->server_type)); + } + DEBUG(4,(" session setup ok\n")); + + if (!cli_send_tconX(c, sharename, "?????", + password, strlen(password)+1)) { + d_printf("tree connect failed: %s\n", cli_errstr(c)); + cli_shutdown(c); + return NULL; + } + + DEBUG(4,(" tconx ok\n")); -/* some forward declarations */ -static struct cli_state *do_connect(const char *server, const char *share); + return c; +} + +/******************************************************************** + Add a new connection to the list +********************************************************************/ + +static struct cli_state* add_new_connection( const char *server, const char *share ) +{ + struct client_connection *node; + + node = SMB_XMALLOC_P( struct client_connection ); + + node->cli = do_connect( server, share ); + + if ( !node->cli ) { + SAFE_FREE( node ); + return NULL; + } + + DLIST_ADD( connections, node ); + + return node->cli; + +} + +/******************************************************************** + Return a connection to a server. +********************************************************************/ + +static struct cli_state* find_connection ( const char *server, const char *share ) +{ + struct client_connection *p; + + for ( p=connections; p; p=p->next ) { + if ( strequal(server, p->cli->desthost) && strequal(share,p->cli->share) ) + return p->cli; + } + + return NULL; +} /**************************************************************************** Write to a local file with CR/LF->LF translation if appropriate. Return the @@ -2424,6 +2582,8 @@ static void server_fn(const char *name, uint32 m, static BOOL list_servers(const char *wk_grp) { + fstring state; + if (!cli->server_domain) return False; @@ -2431,16 +2591,18 @@ static BOOL list_servers(const char *wk_grp) d_printf("\n\tServer Comment\n"); d_printf("\t--------- -------\n"); }; + fstrcpy( state, "Server" ); cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn, - "Server"); + state); if (!grepable) { d_printf("\n\tWorkgroup Master\n"); d_printf("\t--------- -------\n"); }; + fstrcpy( state, "Workgroup" ); cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM, - server_fn, "Workgroup"); + server_fn, state); return True; } @@ -2499,6 +2661,101 @@ static int cmd_logon(void) return 0; } + +/**************************************************************************** + Add a connection to a new //server/share path +****************************************************************************/ + +static int cmd_add_connect(void) +{ + pstring path; + struct cli_state *new_cli; + + if ( !next_token_nr(NULL, path, NULL, sizeof(path)) ) { + d_printf("connect <uncpath>\n"); + return 0; + } + + string_replace(path, '/','\\'); + + new_cli = add_new_connection( "", path ); + + /* if successful, set this as the current connection */ + + if ( new_cli ) + cli = new_cli; + + return 0; +} + +/**************************************************************************** + list active connections +****************************************************************************/ + +static int cmd_list_connect(void) +{ + struct client_connection *p; + int i; + + for ( p=connections,i=0; p; p=p->next,i++ ) { + d_printf("%d:\tserver=%s, share=%s\n", + i, p->cli->desthost, p->cli->share ); + } + + return 0; +} + +/**************************************************************************** + set the current active_connection +****************************************************************************/ + +static int cmd_set_connect(void) +{ + pstring path; + char *server, *share; + struct cli_state *c; + + if ( !next_token_nr(NULL, path, NULL, sizeof(path)) ) { + d_printf("setconnect <uncpath>\n"); + return 0; + } + + if ( strlen(path) < 5 ) { + d_printf("Invalid UNC path [%s]\n", path ); + return 1; + } + + + string_replace(path, '/','\\'); + + share = strrchr_m( path, '\\' ); + if ( !share ) { + d_printf("Invalid UNC path [%s]\n", path ); + return 1; + }; + + *share = '\0'; + share++; + + if ( path[0] != '\\' || path[1]!='\\' ) { + d_printf("Invalid UNC path [%s]\n", path ); + return 1; + } + + server = path+2; + + c = find_connection( server, share ); + if ( !c ) { + d_printf("Cannot find existing connection for //%s/%s\n", + server, share); + return 1; + } + + cli = c; + + return 0; +} + /* Some constants for completing filename arguments */ #define COMPL_NONE 0 /* No completions */ @@ -2570,6 +2827,9 @@ static struct {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}}, {"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}}, {"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}}, + {"addconnect",cmd_add_connect,"add a connection to a new //server/share",{COMPL_NONE,COMPL_NONE}}, + {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}}, + {"setconnect",cmd_set_connect,"set the current active connection",{COMPL_NONE,COMPL_NONE}}, /* Yes, this must be here, see crh's comment above. */ {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}}, @@ -2644,7 +2904,7 @@ static int process_command_string(char *cmd) /* establish the connection if not already */ if (!cli) { - cli = do_connect(desthost, service); + cli = add_new_connection(desthost, service); if (!cli) return 0; } @@ -2952,123 +3212,6 @@ static int process_stdin(void) return rc; } -/***************************************************** - Return a connection to a server. -*******************************************************/ - -static struct cli_state *do_connect(const char *server, const char *share) -{ - struct cli_state *c; - struct nmb_name called, calling; - const char *server_n; - struct in_addr ip; - pstring servicename; - char *sharename; - - /* make a copy so we don't modify the global string 'service' */ - pstrcpy(servicename, share); - sharename = servicename; - if (*sharename == '\\') { - server = sharename+2; - sharename = strchr_m(server,'\\'); - if (!sharename) return NULL; - *sharename = 0; - sharename++; - } - - server_n = server; - - zero_ip(&ip); - - make_nmb_name(&calling, global_myname(), 0x0); - make_nmb_name(&called , server, name_type); - - again: - zero_ip(&ip); - if (have_ip) ip = dest_ip; - - /* have to open a new connection */ - if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) || - !cli_connect(c, server_n, &ip)) { - d_printf("Connection to %s failed\n", server_n); - return NULL; - } - - c->protocol = max_protocol; - c->use_kerberos = use_kerberos; - cli_setup_signing_state(c, cmdline_auth_info.signing_state); - - - if (!cli_session_request(c, &calling, &called)) { - char *p; - d_printf("session request to %s failed (%s)\n", - called.name, cli_errstr(c)); - cli_shutdown(c); - if ((p=strchr_m(called.name, '.'))) { - *p = 0; - goto again; - } - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); - goto again; - } - return NULL; - } - - DEBUG(4,(" session request ok\n")); - - if (!cli_negprot(c)) { - d_printf("protocol negotiation failed\n"); - cli_shutdown(c); - return NULL; - } - - if (!got_pass) { - char *pass = getpass("Password: "); - if (pass) { - pstrcpy(password, pass); - got_pass = 1; - } - } - - if (!cli_session_setup(c, username, - password, strlen(password), - password, strlen(password), - lp_workgroup())) { - /* if a password was not supplied then try again with a null username */ - if (password[0] || !username[0] || use_kerberos || - !cli_session_setup(c, "", "", 0, "", 0, lp_workgroup())) { - d_printf("session setup failed: %s\n", cli_errstr(c)); - if (NT_STATUS_V(cli_nt_error(c)) == - NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)) - d_printf("did you forget to run kinit?\n"); - cli_shutdown(c); - return NULL; - } - d_printf("Anonymous login successful\n"); - } - - if (*c->server_domain) { - DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n", - c->server_domain,c->server_os,c->server_type)); - } else if (*c->server_os || *c->server_type){ - DEBUG(1,("OS=[%s] Server=[%s]\n", - c->server_os,c->server_type)); - } - DEBUG(4,(" session setup ok\n")); - - if (!cli_send_tconX(c, sharename, "?????", - password, strlen(password)+1)) { - d_printf("tree connect failed: %s\n", cli_errstr(c)); - cli_shutdown(c); - return NULL; - } - - DEBUG(4,(" tconx ok\n")); - - return c; -} - /**************************************************************************** Process commands from the client. ****************************************************************************/ @@ -3077,7 +3220,7 @@ static int process(char *base_directory) { int rc = 0; - cli = do_connect(desthost, service); + cli = add_new_connection(desthost, service); if (!cli) { return 1; } @@ -3100,7 +3243,7 @@ static int process(char *base_directory) static int do_host_query(char *query_host) { - cli = do_connect(query_host, "IPC$"); + cli = add_new_connection(query_host, "IPC$"); if (!cli) return 1; @@ -3113,7 +3256,7 @@ static int do_host_query(char *query_host) cli_shutdown(cli); port = 139; - cli = do_connect(query_host, "IPC$"); + cli = add_new_connection(query_host, "IPC$"); } if (cli == NULL) { @@ -3128,7 +3271,6 @@ static int do_host_query(char *query_host) return(0); } - /**************************************************************************** Handle a tar operation. ****************************************************************************/ @@ -3139,7 +3281,7 @@ static int do_tar_op(char *base_directory) /* do we already have a connection? */ if (!cli) { - cli = do_connect(desthost, service); + cli = add_new_connection(desthost, service); if (!cli) return 1; } diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c index f838c5de5b..5df6bfe407 100644 --- a/source3/client/smbspool.c +++ b/source3/client/smbspool.c @@ -339,7 +339,7 @@ smb_print(struct cli_state *cli, /* I - SMB connection */ if ((fnum = cli_open(cli, title, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE)) == -1) { - fprintf(stderr, "ERROR: %s opening remote file %s\n", + fprintf(stderr, "ERROR: %s opening remote spool %s\n", cli_errstr(cli), title); return (1); } @@ -357,7 +357,7 @@ smb_print(struct cli_state *cli, /* I - SMB connection */ { if (cli_write(cli, fnum, 0, buffer, tbytes, nbytes) != nbytes) { - fprintf(stderr, "ERROR: Error writing file: %s\n", cli_errstr(cli)); + fprintf(stderr, "ERROR: Error writing spool: %s\n", cli_errstr(cli)); break; } @@ -366,7 +366,7 @@ smb_print(struct cli_state *cli, /* I - SMB connection */ if (!cli_close(cli, fnum)) { - fprintf(stderr, "ERROR: %s closing remote file %s\n", + fprintf(stderr, "ERROR: %s closing remote spool %s\n", cli_errstr(cli), title); return (1); } diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index bffe9dfe8a..fa98d55f25 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -151,7 +151,7 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli) if (cli->use_level_II_oplocks) capabilities |= CAP_LEVEL_II_OPLOCKS; - capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX)); + capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS)); return capabilities; } diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c new file mode 100644 index 0000000000..bb82fbfabb --- /dev/null +++ b/source3/libsmb/clidfs.c @@ -0,0 +1,154 @@ +/* + Unix SMB/CIFS implementation. + client connect/disconnect routines + Copyright (C) Gerald (Jerry) Carter + + 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 02139, USA. +*/ + +#define NO_SYSLOG + +#include "includes.h" + +/******************************************************************** + check for dfs referral +********************************************************************/ + +BOOL check_for_dfs_referral( struct cli_state *cli ) +{ + uint32 flgs2 = SVAL(cli->inbuf,smb_flg2); + + /* only deal with DS when we negotiated NT_STATUS codes and UNICODE */ + + if ( !( (flgs2&FLAGS2_32_BIT_ERROR_CODES) && (flgs2&FLAGS2_UNICODE_STRINGS) ) ) + return False; + + if ( NT_STATUS_EQUAL( NT_STATUS_PATH_NOT_COVERED, NT_STATUS(IVAL(cli->inbuf,smb_rcls)) ) ) + return True; + + return False; +} + +/******************************************************************** + split a dfs path into the server and share name components +********************************************************************/ + +void split_dfs_path( const char *nodepath, fstring server, fstring share ) +{ + char *p; + pstring path; + + pstrcpy( path, nodepath ); + + if ( path[0] != '\\' ) + return; + + p = strrchr_m( path, '\\' ); + + if ( !p ) + return; + + *p = '\0'; + p++; + + fstrcpy( share, p ); + fstrcpy( server, &path[1] ); +} + +/******************************************************************** + get the dfs referral link +********************************************************************/ + +BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path, + struct referral **refs, size_t *num_refs) +{ + unsigned int data_len = 0; + unsigned int param_len = 0; + uint16 setup = TRANSACT2_GET_DFS_REFERRAL; + char param[sizeof(pstring)+2]; + pstring data; + char *rparam=NULL, *rdata=NULL; + char *p; + size_t pathlen = 2*(strlen(path)+1); + uint16 num_referrals; + struct referral *referrals; + + memset(param, 0, sizeof(param)); + SSVAL(param, 0, 0x03); /* max referral level */ + p = ¶m[2]; + + p += clistr_push(cli, p, path, MIN(pathlen, sizeof(param)-2), STR_TERMINATE); + param_len = PTR_DIFF(p, param); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + (char *)&data, data_len, cli->max_xmit /* data, length, max */ + )) { + return False; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + return False; + } + + num_referrals = SVAL( rdata, 2 ); + + if ( num_referrals != 0 ) { + uint16 ref_version; + uint16 ref_size; + int i; + uint16 node_offset; + + + referrals = SMB_XMALLOC_ARRAY( struct referral, num_referrals ); + + /* start at the referrals array */ + + p = rdata+8; + for ( i=0; i<num_referrals; i++ ) { + ref_version = SVAL( p, 0 ); + ref_size = SVAL( p, 2 ); + node_offset = SVAL( p, 16 ); + + if ( ref_version != 3 ) { + p += ref_size; + continue; + } + + referrals[0].proximity = SVAL( p, 8 ); + referrals[0].ttl = SVAL( p, 10 ); + + clistr_pull( cli, referrals[0].alternate_path, p+node_offset, + sizeof(referrals[0].alternate_path), -1, STR_TERMINATE|STR_UNICODE ); + + p += ref_size; + } + + } + + *num_refs = num_referrals; + *refs = referrals; + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + + return True; +} + diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 39fe91172d..369fba3521 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -185,6 +185,8 @@ void cli_setup_packet(struct cli_state *cli) flags2 = FLAGS2_LONG_PATH_COMPONENTS; if (cli->capabilities & CAP_UNICODE) flags2 |= FLAGS2_UNICODE_STRINGS; + if (cli->capabilities & CAP_DFS) + flags2 |= FLAGS2_DFS_PATHNAMES; if (cli->capabilities & CAP_STATUS32) flags2 |= FLAGS2_32_BIT_ERROR_CODES; if (cli->use_spnego) @@ -283,7 +285,7 @@ struct cli_state *cli_initialise(struct cli_state *cli) cli->use_spnego = lp_client_use_spnego(); - cli->capabilities = CAP_UNICODE | CAP_STATUS32; + cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS; /* Set the CLI_FORCE_DOSERR environment variable to test client routines using DOS errors instead of STATUS32 diff --git a/source3/libsmb/cliprint.c b/source3/libsmb/cliprint.c index 2fb0e59aca..732241a758 100644 --- a/source3/libsmb/cliprint.c +++ b/source3/libsmb/cliprint.c @@ -156,3 +156,108 @@ int cli_printjob_del(struct cli_state *cli, int job) } +/**************************************************************************** + Open a spool file +****************************************************************************/ + +int cli_spl_open(struct cli_state *cli, const char *fname, int flags, int share_mode) +{ + char *p; + unsigned openfn=0; + unsigned accessmode=0; + + if (flags & O_CREAT) + openfn |= (1<<4); + if (!(flags & O_EXCL)) { + if (flags & O_TRUNC) + openfn |= (1<<1); + else + openfn |= (1<<0); + } + + accessmode = (share_mode<<4); + + if ((flags & O_ACCMODE) == O_RDWR) { + accessmode |= 2; + } else if ((flags & O_ACCMODE) == O_WRONLY) { + accessmode |= 1; + } + +#if defined(O_SYNC) + if ((flags & O_SYNC) == O_SYNC) { + accessmode |= (1<<14); + } +#endif /* O_SYNC */ + + if (share_mode == DENY_FCB) { + accessmode = 0xFF; + } + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,15,0,True); + + SCVAL(cli->outbuf,smb_com,SMBsplopen); + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,0xFF); + SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */ + SSVAL(cli->outbuf,smb_vwv3,accessmode); + SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN); + SSVAL(cli->outbuf,smb_vwv5,0); + SSVAL(cli->outbuf,smb_vwv8,openfn); + + if (cli->use_oplocks) { + /* if using oplocks then ask for a batch oplock via + core and extended methods */ + SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)| + FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK); + SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6); + } + + p = smb_buf(cli->outbuf); + p += clistr_push(cli, p, fname, -1, STR_TERMINATE); + + cli_setup_bcc(cli, p); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return -1; + } + + if (cli_is_error(cli)) { + return -1; + } + + return SVAL(cli->inbuf,smb_vwv2); +} + +/**************************************************************************** + Close a file. +****************************************************************************/ + +BOOL cli_spl_close(struct cli_state *cli, int fnum) +{ + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,3,0,True); + + SCVAL(cli->outbuf,smb_com,SMBsplclose); + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,fnum); + SIVALS(cli->outbuf,smb_vwv1,-1); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return False; + } + + return !cli_is_error(cli); +} + + |