diff options
-rw-r--r-- | source3/libsmb/clireadwrite.c | 185 | ||||
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 4 |
2 files changed, 63 insertions, 126 deletions
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index f5ddc77c8f..54d3fd18e3 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -26,7 +26,8 @@ /**************************************************************************** issue a single SMBread and don't wait for a reply ****************************************************************************/ -static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset, + +static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, size_t size, int i) { memset(cli->outbuf,'\0',smb_size); @@ -45,148 +46,89 @@ static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset, SSVAL(cli->outbuf,smb_vwv6,size); SSVAL(cli->outbuf,smb_mid,cli->mid + i); - cli_send_smb(cli); + return cli_send_smb(cli); } /**************************************************************************** - issue a single SMBread and wait for a reply. This function only called - in the rpc pipe code to read dce/rpc reply fragments. + Read size bytes at offset offset using SMBreadX. ****************************************************************************/ -size_t cli_read_one(struct cli_state *cli, int fnum, char *buf, off_t offset, - size_t size) + +ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) { uint32 ecode; uint8 eclass; char *p; int size2; + int readsize; + ssize_t total = 0; if (size == 0) return 0; - /* Issue a read and receive a reply */ - - cli_issue_read(cli, fnum, offset, size, 0); + /* + * Set readsize to the maximum size we can handle in one readX, + * rounded down to a multiple of 1024. + */ - if (!cli_receive_smb(cli)) - return -1; + readsize = (cli->max_xmit - (smb_size+32)) & ~1023; + if (readsize > size ) + readsize = size; - size2 = SVAL(cli->inbuf, smb_vwv5); + while (total < size) { - /* Check for error. Because the client library doesn't support - STATUS32, we need to check for and ignore the more data error - for pipe support. */ + /* Issue a read and receive a reply */ - if (cli_error(cli, &eclass, &ecode, NULL) && - (eclass != ERRDOS && ecode != ERRmoredata)) { - return -1; - } - - if (size2 > size) { - DEBUG(5,("server returned more than we wanted!\n")); - return -1; - } - - /* Copy data into buffer */ - - p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); - memcpy(buf, p, size2); - - return size2; -} - -/**************************************************************************** - read from a file -****************************************************************************/ -size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) -{ - char *p; - int total = -1; -/* - * There is a problem in this code when mpx is more than one. - * for some reason files can get corrupted when being read. - * Until we understand this fully I am serializing reads (one - * read/one reply) for now. JRA. - */ -#if 0 - int mpx = MAX(cli->max_mux-1, 1); -#else - int mpx = 1; -#endif - int block; - int mid; - int blocks; - /* issued is the number of readX requests we have sent so far */ - int issued=0; - /* received is the number of readX replies we have received */ - int received=0; - - /* maybe its a very silly request? */ - if (size == 0) return 0; - - /* set block to the maximum size we can handle in one readX, - rounded down to a multiple of 1024 */ - block = (cli->max_xmit - (smb_size+32)) & ~1023; - - /* work out how many readX calls we will need in total */ - blocks = (size + (block-1)) / block; + if (!cli_issue_read(cli, fnum, offset, readsize, 0)) + return -1; - while (received < blocks) { - int size2; + if (!cli_receive_smb(cli)) + return -1; - while (issued - received < mpx && issued < blocks) { - int size1 = MIN(block, size-issued*block); - cli_issue_read(cli, fnum, offset+issued*block, size1, issued); - issued++; - } + /* + * Check for error. Because the client library doesn't support + * STATUS32, we need to check for and ignore the more data error + * for pipe support. + */ - if (!cli_receive_smb(cli)) { - return total; + if (cli_error(cli, &eclass, &ecode, NULL) && + (eclass != ERRDOS && ecode != ERRmoredata)) { + return -1; } - received++; - mid = SVAL(cli->inbuf, smb_mid) - cli->mid; size2 = SVAL(cli->inbuf, smb_vwv5); - if (CVAL(cli->inbuf,smb_rcls) != 0) { - blocks = MIN(blocks, mid-1); - continue; - } - - if (size2 <= 0) { - blocks = MIN(blocks, mid-1); - /* this distinguishes EOF from an error */ - total = MAX(total, 0); - continue; - } - - if (size2 > block) { - DEBUG(0,("server returned more than we wanted!\n")); + if (size2 > readsize) { + DEBUG(5,("server returned more than we wanted!\n")); return -1; - } - if (mid >= issued) { - DEBUG(0,("invalid mid from server!\n")); + } else if (size2 < 0) { + DEBUG(5,("read return < 0!\n")); return -1; } + + /* Copy data into buffer */ + p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); + memcpy(buf + total, p, size2); - memcpy(buf+mid*block, p, size2); + total += size2; + offset += size2; - total = MAX(total, mid*block + size2); - } + /* + * If the server returned less than we asked for we're at EOF. + */ - while (received < issued) { - cli_receive_smb(cli); - received++; + if (size2 < readsize) + break; } - + return total; } - /**************************************************************************** issue a single SMBwrite and don't wait for a reply ****************************************************************************/ -static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf, + +static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf, size_t size, int i) { char *p; @@ -223,7 +165,7 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 SSVAL(cli->outbuf,smb_mid,cli->mid + i); show_msg(cli->outbuf); - cli_send_smb(cli); + return cli_send_smb(cli); } /**************************************************************************** @@ -233,6 +175,7 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 0x0004 use raw named pipe protocol 0x0008 start of message mode named pipe protocol ****************************************************************************/ + ssize_t cli_write(struct cli_state *cli, int fnum, uint16 write_mode, char *buf, off_t offset, size_t size) @@ -246,45 +189,39 @@ ssize_t cli_write(struct cli_state *cli, while (received < blocks) { - while ((issued - received < mpx) && (issued < blocks)) - { + while ((issued - received < mpx) && (issued < blocks)) { int bsent = issued * block; int size1 = MIN(block, size - bsent); - cli_issue_write(cli, fnum, offset + bsent, + if (!cli_issue_write(cli, fnum, offset + bsent, write_mode, buf + bsent, - size1, issued); + size1, issued)) + return -1; issued++; } if (!cli_receive_smb(cli)) - { return bwritten; - } received++; if (CVAL(cli->inbuf,smb_rcls) != 0) - { break; - } bwritten += SVAL(cli->inbuf, smb_vwv2); } while (received < issued && cli_receive_smb(cli)) - { received++; - } return bwritten; } - /**************************************************************************** write to a file using a SMBwrite and not bypassing 0 byte writes ****************************************************************************/ + ssize_t cli_smbwrite(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size1) { @@ -315,17 +252,18 @@ ssize_t cli_smbwrite(struct cli_state *cli, cli_setup_bcc(cli, p); - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { + if (!cli_send_smb(cli)) + return -1; + + if (!cli_receive_smb(cli)) return -1; - } - if (CVAL(cli->inbuf,smb_rcls) != 0) { + if (CVAL(cli->inbuf,smb_rcls) != 0) return -1; - } size = SVAL(cli->inbuf,smb_vwv0); - if (size == 0) break; + if (size == 0) + break; size1 -= size; total += size; @@ -333,4 +271,3 @@ ssize_t cli_smbwrite(struct cli_state *cli, return total; } - diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index c3ebf28809..4bbbac17ed 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -76,7 +76,7 @@ static BOOL rpc_read(struct cli_state *cli, prs_struct *rdata, uint32 data_to_re if (size > (size_t)data_to_read) size = (size_t)data_to_read; - num_read = (int)cli_read_one(cli, cli->nt_pipe_fnum, pdata, (off_t)stream_offset, size); + num_read = (int)cli_read(cli, cli->nt_pipe_fnum, pdata, (off_t)stream_offset, size); DEBUG(5,("rpc_read: num_read = %d, read offset: %d, to read: %d\n", num_read, stream_offset, data_to_read)); @@ -467,7 +467,7 @@ static BOOL rpc_api_pipe(struct cli_state *cli, uint16 cmd, prs_struct *data, pr prs_init(&hps, 0, cli->mem_ctx, UNMARSHALL); prs_give_memory(&hps, hdr_data, sizeof(hdr_data), False); - num_read = cli_read_one(cli, cli->nt_pipe_fnum, hdr_data, 0, RPC_HEADER_LEN+RPC_HDR_RESP_LEN); + num_read = cli_read(cli, cli->nt_pipe_fnum, hdr_data, 0, RPC_HEADER_LEN+RPC_HDR_RESP_LEN); if (cli_error(cli, &eclass, &ecode, NULL) && (eclass != ERRDOS && ecode != ERRmoredata)) { DEBUG(0,("rpc_api_pipe: cli_read error : %d/%d\n", |