From 858e63cab3b6a23692678d6eb03f9e48c3c08603 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 25 Apr 2000 14:04:06 +0000 Subject: split clientgen.c into several parts the next step is splitting out the auth code, to make adding lukes NTLMSSP support easier (This used to be commit 10c5470835b43116ed48b3137c3b9cc867a20989) --- source3/libsmb/clireadwrite.c | 273 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 source3/libsmb/clireadwrite.c (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c new file mode 100644 index 0000000000..8012c02a8f --- /dev/null +++ b/source3/libsmb/clireadwrite.c @@ -0,0 +1,273 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + client file read/write routines + Copyright (C) Andrew Tridgell 1994-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define NO_SYSLOG + +#include "includes.h" + +/**************************************************************************** +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, + size_t size, int i) +{ + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,10,0,True); + + CVAL(cli->outbuf,smb_com) = SMBreadX; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + CVAL(cli->outbuf,smb_vwv0) = 0xFF; + SSVAL(cli->outbuf,smb_vwv2,fnum); + SIVAL(cli->outbuf,smb_vwv3,offset); + SSVAL(cli->outbuf,smb_vwv5,size); + SSVAL(cli->outbuf,smb_vwv6,size); + SSVAL(cli->outbuf,smb_mid,cli->mid + i); + + cli_send_smb(cli); +} + +/**************************************************************************** + 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; + int issued=0; + int received=0; +/* + * 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 = (cli->max_xmit - (smb_size+32)) & ~1023; + int mid; + int blocks = (size + (block-1)) / block; + + if (size == 0) return 0; + + while (received < blocks) { + int size2; + + while (issued - received < mpx && issued < blocks) { + int size1 = MIN(block, size-issued*block); + cli_issue_read(cli, fnum, offset+issued*block, size1, issued); + issued++; + } + + if (!cli_receive_smb(cli)) { + return total; + } + + 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")); + return -1; + } + if (mid >= issued) { + DEBUG(0,("invalid mid from server!\n")); + return -1; + } + p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); + + memcpy(buf+mid*block, p, size2); + + total = MAX(total, mid*block + size2); + } + + while (received < issued) { + cli_receive_smb(cli); + received++; + } + + 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, + size_t size, int i) +{ + char *p; + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,12,size,True); + + CVAL(cli->outbuf,smb_com) = SMBwriteX; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + CVAL(cli->outbuf,smb_vwv0) = 0xFF; + SSVAL(cli->outbuf,smb_vwv2,fnum); + + SIVAL(cli->outbuf,smb_vwv3,offset); + SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0); + SSVAL(cli->outbuf,smb_vwv7,mode); + + SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0); + SSVAL(cli->outbuf,smb_vwv10,size); + SSVAL(cli->outbuf,smb_vwv11, + smb_buf(cli->outbuf) - smb_base(cli->outbuf)); + + p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11); + memcpy(p, buf, size); + + SSVAL(cli->outbuf,smb_mid,cli->mid + i); + + show_msg(cli->outbuf); + cli_send_smb(cli); +} + +/**************************************************************************** + write to a file + write_mode: 0x0001 disallow write cacheing + 0x0002 return bytes remaining + 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) +{ + int bwritten = 0; + int issued = 0; + int received = 0; + int mpx = MAX(cli->max_mux-1, 1); + int block = (cli->max_xmit - (smb_size+32)) & ~1023; + int blocks = (size + (block-1)) / block; + + while (received < blocks) { + + while ((issued - received < mpx) && (issued < blocks)) + { + int bsent = issued * block; + int size1 = MIN(block, size - bsent); + + cli_issue_write(cli, fnum, offset + bsent, + write_mode, + buf + bsent, + size1, issued); + 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) +{ + char *p; + ssize_t total = 0; + + do { + size_t size = MIN(size1, cli->max_xmit - 48); + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,5, 3 + size,True); + + CVAL(cli->outbuf,smb_com) = SMBwrite; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,fnum); + SSVAL(cli->outbuf,smb_vwv1,size); + SIVAL(cli->outbuf,smb_vwv2,offset); + SSVAL(cli->outbuf,smb_vwv4,0); + + p = smb_buf(cli->outbuf); + *p++ = 1; + SSVAL(p, 0, size); + memcpy(p+2, buf, size); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return -1; + } + + if (CVAL(cli->inbuf,smb_rcls) != 0) { + return -1; + } + + size = SVAL(cli->inbuf,smb_vwv0); + if (size == 0) break; + + size1 -= size; + total += size; + } while (size1); + + return total; +} + -- cgit From 7f36df301e28dc8ca0e5bfadc109d6e907d9ba2b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Aug 2000 18:32:34 +0000 Subject: Tidyup removing many of the 0xC0000000 | NT_STATUS_XXX stuff (only need NT_STATUS_XXX). Removed IS_BITS_xxx macros as they were just reproducing "C" syntax in a more obscure way. Jeremy. (This used to be commit c55bcec817f47d6162466b193d533c877194124a) --- source3/libsmb/clireadwrite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 8012c02a8f..86a51da835 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -148,10 +148,10 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 SSVAL(cli->outbuf,smb_vwv2,fnum); SIVAL(cli->outbuf,smb_vwv3,offset); - SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0); + SIVAL(cli->outbuf,smb_vwv5,(mode & 0x0008) ? 0xFFFFFFFF : 0); SSVAL(cli->outbuf,smb_vwv7,mode); - SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0); + SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0); SSVAL(cli->outbuf,smb_vwv10,size); SSVAL(cli->outbuf,smb_vwv11, smb_buf(cli->outbuf) - smb_base(cli->outbuf)); -- cgit From 5264e9a2a737d6498be0f346bcbc3b583609abf5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Jun 2001 08:17:16 +0000 Subject: Set correct reply word in large writeX (greater than 64k) replies. Also added smbtorture test for this. Jeremy. (This used to be commit 6d65556ae8bea45a203defaded8436cbb56965e1) --- source3/libsmb/clireadwrite.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 86a51da835..6c52d2b776 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -138,7 +138,10 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,12,size,True); + if (size > 0xFFFF) + set_message(cli->outbuf,14,size,True); + else + set_message(cli->outbuf,12,size,True); CVAL(cli->outbuf,smb_com) = SMBwriteX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -152,6 +155,7 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 SSVAL(cli->outbuf,smb_vwv7,mode); SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0); + SSVAL(cli->outbuf,smb_vwv9,((size>>16)&1)); SSVAL(cli->outbuf,smb_vwv10,size); SSVAL(cli->outbuf,smb_vwv11, smb_buf(cli->outbuf) - smb_base(cli->outbuf)); -- cgit From 91b8a8d1d21b810b6aca44ce647837669efd6dcf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jun 2001 09:10:42 +0000 Subject: next_token() was supposed to be a reentrant replacement for strtok(), but the code suffered from bitrot and is not now reentrant. That means we can get bizarre behaviour i've fixed this by making next_token() reentrant and creating a next_token_nr() that is a small non-reentrant wrapper for those lumps of code (mostly smbclient) that have come to rely on the non-reentrant behaviour (This used to be commit 674ee2f1d12b0afc164a9e9072758fd1c5e54df7) --- source3/libsmb/clireadwrite.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 6c52d2b776..9ee63270df 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -139,9 +139,9 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 memset(cli->inbuf,'\0',smb_size); if (size > 0xFFFF) - set_message(cli->outbuf,14,size,True); + set_message(cli->outbuf,14,0,True); else - set_message(cli->outbuf,12,size,True); + set_message(cli->outbuf,12,0,True); CVAL(cli->outbuf,smb_com) = SMBwriteX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -162,6 +162,7 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11); memcpy(p, buf, size); + cli_setup_bcc(cli, p+size); SSVAL(cli->outbuf,smb_mid,cli->mid + i); @@ -240,7 +241,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,5, 3 + size,True); + set_message(cli->outbuf,5, 0,True); CVAL(cli->outbuf,smb_com) = SMBwrite; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -253,8 +254,10 @@ ssize_t cli_smbwrite(struct cli_state *cli, p = smb_buf(cli->outbuf); *p++ = 1; - SSVAL(p, 0, size); - memcpy(p+2, buf, size); + SSVAL(p, 0, size); p += 2; + memcpy(p, buf, size); p += size; + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { -- cgit From 6fdffd9b6c6150793d86114f18c2239a53625e73 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Jun 2001 00:42:53 +0000 Subject: added some comments to make the cli read code clearer (This used to be commit bbfbe03cc6166c23c42a704b5acaa19cbdbc39ce) --- source3/libsmb/clireadwrite.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 9ee63270df..70266a2d9a 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -55,8 +55,6 @@ size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t { char *p; int total = -1; - int issued=0; - int received=0; /* * There is a problem in this code when mpx is more than one. * for some reason files can get corrupted when being read. @@ -68,12 +66,24 @@ size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t #else int mpx = 1; #endif - int block = (cli->max_xmit - (smb_size+32)) & ~1023; + int block; int mid; - int blocks = (size + (block-1)) / block; + 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; + while (received < blocks) { int size2; -- cgit From ff5a18ad3e5a9a4dac6947e3551126c8ea9077dd Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 22 Jun 2001 01:09:40 +0000 Subject: Merged cli_read_one() function for reading DCE/RPC reply fragments. (This used to be commit 9e074bc2bf2df34048b67457623bb8219fb1e4d6) --- source3/libsmb/clireadwrite.c | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 70266a2d9a..f5ddc77c8f 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -48,6 +48,52 @@ static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset, 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. +****************************************************************************/ +size_t cli_read_one(struct cli_state *cli, int fnum, char *buf, off_t offset, + size_t size) +{ + uint32 ecode; + uint8 eclass; + char *p; + int size2; + + if (size == 0) + return 0; + + /* Issue a read and receive a reply */ + + cli_issue_read(cli, fnum, offset, size, 0); + + if (!cli_receive_smb(cli)) + return -1; + + size2 = SVAL(cli->inbuf, smb_vwv5); + + /* 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_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 ****************************************************************************/ -- cgit From 5fb9a869b7e56ca567eae43d85079c37f246daec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 29 Jun 2001 00:22:22 +0000 Subject: Use a logical cli_read(), removed the cli_read_one() hack. Jeremy. (This used to be commit 2999eab5abe86bf08e693800c01ad544f04e4d6c) --- source3/libsmb/clireadwrite.c | 185 ++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 124 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') 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; } - -- cgit From 4592d107fc01c8cb46f99843529d145d268b35da Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 1 Jul 2001 13:18:35 +0000 Subject: cli_read() was reading too many bytes. (This used to be commit ba79d2a030b9ae087f0cc4248baa6cf6bee112fb) --- source3/libsmb/clireadwrite.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 54d3fd18e3..458532cb2e 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -71,10 +71,9 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ */ readsize = (cli->max_xmit - (smb_size+32)) & ~1023; - if (readsize > size ) - readsize = size; while (total < size) { + readsize = MIN(readsize, size-total); /* Issue a read and receive a reply */ -- cgit From 2ccfea3de7b2b7dc0be2438c3adb3f7be82a2dfc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 10 Aug 2001 06:00:33 +0000 Subject: A rewrite of the error handling in the libsmb client code. I've separated out the error handling into a bunch of separate functions rather than all being handled in one big function. Fetch error codes from the last received packet: void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *num); uint32 cli_nt_error(struct cli_state *); Convert errors to UNIX errno values: int cli_errno_from_dos(uint8 eclass, uint32 num); int cli_errno_from_nt(uint32 status); int cli_errno(struct cli_state *cli); Detect different kinds of errors: BOOL cli_is_dos_error(struct cli_state *cli); BOOL cli_is_nt_error(struct cli_state *cli); BOOL cli_is_error(struct cli_state *cli); This also means we now support CAP_STATUS32 as we can decode and understand NT errors instead of just DOS errors. Yay! Ported a whole bunch of files in libsmb to use this new API instead of the just the DOS error. (This used to be commit 6dbdb0d813f3c7ab20b38baa1223b0b479aadec9) --- source3/libsmb/clireadwrite.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 458532cb2e..f6ee78c567 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -55,8 +55,6 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, 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; @@ -83,15 +81,21 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ if (!cli_receive_smb(cli)) return -1; - /* - * 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. - */ + /* Check for error. Make sure to check for DOS and NT + errors. */ - if (cli_error(cli, &eclass, &ecode, NULL) && - (eclass != ERRDOS && ecode != ERRmoredata)) { - return -1; + if (cli_is_error(cli)) { + uint32 status = 0; + uint8 eclass = 0; + + if (cli_is_nt_error(cli)) + status = cli_nt_error(cli); + else + cli_dos_error(cli, &eclass, &status); + + if ((eclass == ERRDOS && status == ERRmoredata) || + status == STATUS_MORE_ENTRIES) + return -1; } size2 = SVAL(cli->inbuf, smb_vwv5); -- cgit From 364d0e56e94718ad49bca4d6dcc95dee8e4e85e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 24 Aug 2001 20:20:08 +0000 Subject: Re-added readbraw call to test with smbtorture. This code not yet tested... Jeremy. (This used to be commit fe85a19b4b9db5910ad8259890f94c9496e1aebf) --- source3/libsmb/clireadwrite.c | 89 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index f6ee78c567..6566acf4ef 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -24,7 +24,7 @@ #include "includes.h" /**************************************************************************** -issue a single SMBread and don't wait for a reply +Issue a single SMBread and don't wait for a reply. ****************************************************************************/ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, @@ -49,6 +49,31 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, return cli_send_smb(cli); } +/**************************************************************************** +Issue a single SMBreadraw and don't wait for a reply. +****************************************************************************/ + +static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, + size_t size, int i) +{ + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,10,0,True); + + CVAL(cli->outbuf,smb_com) = SMBreadbraw; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,fnum); + SIVAL(cli->outbuf,smb_vwv1,offset); + SSVAL(cli->outbuf,smb_vwv2,size); + SSVAL(cli->outbuf,smb_vwv3,size); + SSVAL(cli->outbuf,smb_mid,cli->mid + i); + + return cli_send_smb(cli); +} + /**************************************************************************** Read size bytes at offset offset using SMBreadX. ****************************************************************************/ @@ -127,6 +152,68 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return total; } +/**************************************************************************** + Tester for the readraw call. +****************************************************************************/ + +ssize_t cli_readraw(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) +{ + char *p; + int size2; + size_t readsize; + ssize_t total = 0; + + if (size == 0) + return 0; + + /* + * Set readsize to the maximum size we can handle in one readraw. + */ + + readsize = 0xFFFF; + + while (total < size) { + readsize = MIN(readsize, size-total); + + /* Issue a read and receive a reply */ + + if (!cli_issue_readraw(cli, fnum, offset, readsize, 0)) + return -1; + + if (!client_receive_smb(cli->fd, cli->inbuf, cli->timeout)) + return -1; + + size2 = smb_len(cli->inbuf); + + if (size2 > readsize) { + DEBUG(5,("server returned more than we wanted!\n")); + return -1; + } else if (size2 < 0) { + DEBUG(5,("read return < 0!\n")); + return -1; + } + + /* Copy data into buffer */ + + if (size2) { + p = cli->inbuf + 4; + memcpy(buf + total, p, size2); + } + + total += size2; + offset += size2; + + /* + * If the server returned less than we asked for we're at EOF. + */ + + if (size2 < readsize) + break; + } + + return total; +} + /**************************************************************************** issue a single SMBwrite and don't wait for a reply ****************************************************************************/ -- cgit From ee5f7237decfe446f4fdb08422beb2e6cb43af7f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 17:52:23 +0000 Subject: started converting NTSTATUS to be a structure on systems with gcc in order to make it type incompatible with BOOL so we catch errors sooner. This has already found a number of bugs (This used to be commit 1b778bc7d22efff3f90dc450eb12baa1241cf68f) --- source3/libsmb/clireadwrite.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 6566acf4ef..abbb8cd110 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -110,16 +110,17 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ errors. */ if (cli_is_error(cli)) { - uint32 status = 0; + NTSTATUS status = NT_STATUS_OK; uint8 eclass = 0; + uint32 ecode = 0; if (cli_is_nt_error(cli)) status = cli_nt_error(cli); else - cli_dos_error(cli, &eclass, &status); + cli_dos_error(cli, &eclass, &ecode); - if ((eclass == ERRDOS && status == ERRmoredata) || - status == STATUS_MORE_ENTRIES) + if ((eclass == ERRDOS && ecode == ERRmoredata) || + NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES)) return -1; } -- cgit From d53d5beeb29c0024556aae2f66f1d5bfe63960e5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Sep 2001 11:32:59 +0000 Subject: use cli_is_error() instead of looking in smb_rcls, otherwise NT status codes don't work correctly (This used to be commit 55d5828e608671f070a9e96938be0d16d50aeb26) --- source3/libsmb/clireadwrite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index abbb8cd110..f141a208bf 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -297,7 +297,7 @@ ssize_t cli_write(struct cli_state *cli, received++; - if (CVAL(cli->inbuf,smb_rcls) != 0) + if (cli_is_error(cli)) break; bwritten += SVAL(cli->inbuf, smb_vwv2); @@ -349,7 +349,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, if (!cli_receive_smb(cli)) return -1; - if (CVAL(cli->inbuf,smb_rcls) != 0) + if (cli_is_error(cli)) return -1; size = SVAL(cli->inbuf,smb_vwv0); -- cgit From d6823366b881612234ab0655adb11c594f864c4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jan 2002 19:10:25 +0000 Subject: Same fix as went into 2.2 (I'm waiting for jerry to finish some code). Jeremy. (This used to be commit 01ff6ce4963e1daff019f2b936cef218e1c93f67) --- source3/libsmb/clireadwrite.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index f141a208bf..93333bff95 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -35,11 +35,11 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, set_message(cli->outbuf,10,0,True); - CVAL(cli->outbuf,smb_com) = SMBreadX; + SCVAL(cli->outbuf,smb_com,SMBreadX); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - CVAL(cli->outbuf,smb_vwv0) = 0xFF; + SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,fnum); SIVAL(cli->outbuf,smb_vwv3,offset); SSVAL(cli->outbuf,smb_vwv5,size); @@ -61,7 +61,7 @@ static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, set_message(cli->outbuf,10,0,True); - CVAL(cli->outbuf,smb_com) = SMBreadbraw; + SCVAL(cli->outbuf,smb_com,SMBreadbraw); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); @@ -232,11 +232,11 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 else set_message(cli->outbuf,12,0,True); - CVAL(cli->outbuf,smb_com) = SMBwriteX; + SCVAL(cli->outbuf,smb_com,SMBwriteX); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - CVAL(cli->outbuf,smb_vwv0) = 0xFF; + SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,fnum); SIVAL(cli->outbuf,smb_vwv3,offset); @@ -327,7 +327,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, set_message(cli->outbuf,5, 0,True); - CVAL(cli->outbuf,smb_com) = SMBwrite; + SCVAL(cli->outbuf,smb_com,SMBwrite); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/libsmb/clireadwrite.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 93333bff95..627bab88a5 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. client file read/write routines Copyright (C) Andrew Tridgell 1994-1998 -- cgit From 5e09ffdc7cfbbf06720af55101512ca88fac7ea2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Mar 2002 01:43:06 +0000 Subject: Test against W2K that we're doing large read/writes correctly (we are). At least with 14 word writes. Jeremy. (This used to be commit 24ef6258a16e6b4673f1088d64b79bddcd268df5) --- source3/libsmb/clireadwrite.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 627bab88a5..402de726e8 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -223,6 +223,14 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 { char *p; + if (size > cli->bufsize) { + cli->outbuf = realloc(cli->outbuf, size + 1024); + cli->inbuf = realloc(cli->inbuf, size + 1024); + if (cli->outbuf == NULL || cli->inbuf == NULL) + return False; + cli->bufsize = size + 1024; + } + memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); @@ -300,6 +308,7 @@ ssize_t cli_write(struct cli_state *cli, break; bwritten += SVAL(cli->inbuf, smb_vwv2); + bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))>>16); } while (received < issued && cli_receive_smb(cli)) -- cgit From a1249aca906e9624edada1b4e9c654b568897dce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Mar 2002 01:47:31 +0000 Subject: Correctly increment offset in cli_smbwrite. Jeremy. (This used to be commit 5b04b5f1df3ee509e7314064966be09e2202b0ef) --- source3/libsmb/clireadwrite.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 402de726e8..0a9569fc69 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -366,6 +366,8 @@ ssize_t cli_smbwrite(struct cli_state *cli, size1 -= size; total += size; + offset += size; + } while (size1); return total; -- cgit From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/libsmb/clireadwrite.c | 64 +++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 0a9569fc69..756a6cce2f 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -48,31 +48,6 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, return cli_send_smb(cli); } -/**************************************************************************** -Issue a single SMBreadraw and don't wait for a reply. -****************************************************************************/ - -static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, - size_t size, int i) -{ - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); - - set_message(cli->outbuf,10,0,True); - - SCVAL(cli->outbuf,smb_com,SMBreadbraw); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); - - SSVAL(cli->outbuf,smb_vwv0,fnum); - SIVAL(cli->outbuf,smb_vwv1,offset); - SSVAL(cli->outbuf,smb_vwv2,size); - SSVAL(cli->outbuf,smb_vwv3,size); - SSVAL(cli->outbuf,smb_mid,cli->mid + i); - - return cli_send_smb(cli); -} - /**************************************************************************** Read size bytes at offset offset using SMBreadX. ****************************************************************************/ @@ -152,6 +127,43 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return total; } +#if 0 /* relies on client_recieve_smb(), now a static in libsmb/clientgen.c */ + +/* This call is INCOMPATIBLE with SMB signing. If you remove the #if 0 + you must fix ensure you don't attempt to sign the packets - data + *will* be currupted */ + +/**************************************************************************** +Issue a single SMBreadraw and don't wait for a reply. +****************************************************************************/ + +static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, + size_t size, int i) +{ + + if (!cli->sign_info.use_smb_signing) { + DEBUG(0, ("Cannot use readraw and SMB Signing\n")); + return False; + } + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,10,0,True); + + SCVAL(cli->outbuf,smb_com,SMBreadbraw); + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,fnum); + SIVAL(cli->outbuf,smb_vwv1,offset); + SSVAL(cli->outbuf,smb_vwv2,size); + SSVAL(cli->outbuf,smb_vwv3,size); + SSVAL(cli->outbuf,smb_mid,cli->mid + i); + + return cli_send_smb(cli); +} + /**************************************************************************** Tester for the readraw call. ****************************************************************************/ @@ -213,7 +225,7 @@ ssize_t cli_readraw(struct cli_state *cli, int fnum, char *buf, off_t offset, si return total; } - +#endif /**************************************************************************** issue a single SMBwrite and don't wait for a reply ****************************************************************************/ -- cgit From a834a73e341059be154426390304a42e4a011f72 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 25 Sep 2002 15:19:00 +0000 Subject: sync'ing up for 3.0alpha20 release (This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139) --- source3/libsmb/clireadwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 756a6cce2f..875df11dca 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -127,7 +127,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return total; } -#if 0 /* relies on client_recieve_smb(), now a static in libsmb/clientgen.c */ +#if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */ /* This call is INCOMPATIBLE with SMB signing. If you remove the #if 0 you must fix ensure you don't attempt to sign the packets - data -- cgit From 296c93923c643fbbf1720af2f647f29aea708bd5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Nov 2002 19:11:46 +0000 Subject: Test was reversed for ERRmoredata in cli_read. Jeremy. (This used to be commit fff7f3cbe248982bcd70abb1da6624186bab42d2) --- source3/libsmb/clireadwrite.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 875df11dca..38e8aac42a 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -84,6 +84,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ errors. */ if (cli_is_error(cli)) { + BOOL recoverable_error = False; NTSTATUS status = NT_STATUS_OK; uint8 eclass = 0; uint32 ecode = 0; @@ -93,8 +94,17 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ else cli_dos_error(cli, &eclass, &ecode); + /* + * ERRDOS ERRmoredata or STATUS_MORE_ENRTIES is a + * recoverable error, plus we have valid data in the + * packet so don't error out here. + */ + if ((eclass == ERRDOS && ecode == ERRmoredata) || NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES)) + recoverable_error = True; + + if (!recoverable_error) return -1; } -- cgit From 41969738a4d5244b73864dd882d214ff8824365b Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 19 Dec 2002 20:26:44 +0000 Subject: merge from 2.2 fix for smbclient large files (This used to be commit 17f685fdbf5d36f82e3da0a09457f5e248b3f109) --- source3/libsmb/clireadwrite.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 38e8aac42a..7780c93cc4 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -29,10 +29,15 @@ Issue a single SMBread and don't wait for a reply. static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, size_t size, int i) { + BOOL bigoffset = False; + memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,10,0,True); + if ((SMB_BIG_UINT)offset >> 32) + bigoffset = True; + + set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); SCVAL(cli->outbuf,smb_com,SMBreadX); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -45,6 +50,9 @@ static BOOL 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); + if (bigoffset) + SIVAL(cli->outbuf,smb_vwv10,(offset>>32) & 0xffffffff); + return cli_send_smb(cli); } -- cgit From 266c1ece1242e9e7b32eede8d5e1d1c81a6eb619 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Dec 2002 06:12:13 +0000 Subject: Merge Richard's write > 4Gb fix. Jeremy. (This used to be commit 5431bae8944496f44d8cc6d2c4de86e9feb60f32) --- source3/libsmb/clireadwrite.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 7780c93cc4..187a40cade 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -252,6 +252,7 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 size_t size, int i) { char *p; + BOOL bigoffset = False; if (size > cli->bufsize) { cli->outbuf = realloc(cli->outbuf, size + 1024); @@ -264,7 +265,10 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - if (size > 0xFFFF) + if ((SMB_BIG_UINT)offset >> 32) + bigoffset = True; + + if (bigoffset) set_message(cli->outbuf,14,0,True); else set_message(cli->outbuf,12,0,True); @@ -277,14 +281,20 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 SSVAL(cli->outbuf,smb_vwv2,fnum); SIVAL(cli->outbuf,smb_vwv3,offset); - SIVAL(cli->outbuf,smb_vwv5,(mode & 0x0008) ? 0xFFFFFFFF : 0); + SIVAL(cli->outbuf,smb_vwv5,0); SSVAL(cli->outbuf,smb_vwv7,mode); + /* + * THe following is still wrong ... + */ SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0); SSVAL(cli->outbuf,smb_vwv9,((size>>16)&1)); SSVAL(cli->outbuf,smb_vwv10,size); SSVAL(cli->outbuf,smb_vwv11, smb_buf(cli->outbuf) - smb_base(cli->outbuf)); + + if (bigoffset) + SIVAL(cli->outbuf,smb_vwv12,(offset>>32) & 0xffffffff); p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11); memcpy(p, buf, size); -- cgit From 634c54310c92c48dd4eceec602e230a021bdcfc5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Jan 2003 08:28:12 +0000 Subject: Merge from HEAD - make Samba compile with -Wwrite-strings without additional warnings. (Adds a lot of const). Andrew Bartlett (This used to be commit 3a7458f9472432ef12c43008414925fd1ce8ea0c) --- source3/libsmb/clireadwrite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 187a40cade..fb013734ac 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -248,7 +248,8 @@ ssize_t cli_readraw(struct cli_state *cli, int fnum, char *buf, off_t offset, si issue a single SMBwrite and don't wait for a reply ****************************************************************************/ -static BOOL 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, const char *buf, size_t size, int i) { char *p; @@ -316,7 +317,7 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 ssize_t cli_write(struct cli_state *cli, int fnum, uint16 write_mode, - char *buf, off_t offset, size_t size) + const char *buf, off_t offset, size_t size) { int bwritten = 0; int issued = 0; -- cgit From 99cdb462083381c88689a4e698ca48b6ed4cf5ac Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 15 Jan 2003 18:57:41 +0000 Subject: *lots of small merges form HEAD *sync up configure.in *don't build torture tools in make all *make sure to remove torture tools as part of make clean (This used to be commit 0fb724b3216eeeb97e61ff12755ca3a31bcad6ef) --- source3/libsmb/clireadwrite.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index fb013734ac..0715aa7f1a 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -285,10 +285,13 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, SIVAL(cli->outbuf,smb_vwv5,0); SSVAL(cli->outbuf,smb_vwv7,mode); + SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0); /* - * THe following is still wrong ... + * According to CIFS-TR-1p00, this following field should only + * be set if CAP_LARGE_WRITEX is set. We should check this + * locally. However, this check might already have been + * done by our callers. */ - SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0); SSVAL(cli->outbuf,smb_vwv9,((size>>16)&1)); SSVAL(cli->outbuf,smb_vwv10,size); SSVAL(cli->outbuf,smb_vwv11, -- cgit From 38b3ee6467230955ec94c820f3740eab89534d8c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Aug 2003 17:08:35 +0000 Subject: RPC fix from Ronan Waide . Tested with rpcecho. Jeremy. (This used to be commit 68590b9e2266cf76b46a68cca0acaa47733811fe) --- source3/libsmb/clireadwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 0715aa7f1a..8eac7d07d8 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -326,7 +326,7 @@ ssize_t cli_write(struct cli_state *cli, int issued = 0; int received = 0; int mpx = MAX(cli->max_mux-1, 1); - int block = (cli->max_xmit - (smb_size+32)) & ~1023; + int block = cli->max_xmit - (smb_size+32); int blocks = (size + (block-1)) / block; while (received < blocks) { -- cgit From 41b37207139b3cbfa293a84ab92113db8007afed Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Sep 2004 00:49:41 +0000 Subject: r2371: Fix for talking to OS/2 clients (max_mux ignored) by Guenter Kukkukk . Bugid #1590. Jeremy. (This used to be commit 330025d1a669de927a3879a9c3a9fc20e1be464f) --- source3/libsmb/clireadwrite.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 8eac7d07d8..60ac89aeb2 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -325,10 +325,16 @@ ssize_t cli_write(struct cli_state *cli, int bwritten = 0; int issued = 0; int received = 0; - int mpx = MAX(cli->max_mux-1, 1); + int mpx = 1; int block = cli->max_xmit - (smb_size+32); int blocks = (size + (block-1)) / block; + if(cli->max_mux == 0) { + mpx = 1; + } else { + mpx = cli->max_mux-1; + } + while (received < blocks) { while ((issued - received < mpx) && (issued < blocks)) { -- cgit From 40a89ce884de9de9cd013864e03a73b9c44ebde7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 17 Sep 2004 00:53:17 +0000 Subject: r2373: Fix typo. Jeremy. (This used to be commit b1033fc77c97f0d9b5613a0b9f7d45dcf58e6b56) --- source3/libsmb/clireadwrite.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 60ac89aeb2..3f14e53094 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -329,10 +329,10 @@ ssize_t cli_write(struct cli_state *cli, int block = cli->max_xmit - (smb_size+32); int blocks = (size + (block-1)) / block; - if(cli->max_mux == 0) { - mpx = 1; - } else { + if(cli->max_mux > 1) { mpx = cli->max_mux-1; + } else { + mpx = 1; } while (received < blocks) { -- cgit From 26c106e0838db54aafddf1e0f7e4781510dbc582 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Thu, 14 Oct 2004 03:19:57 +0000 Subject: r2959: If we want to support writes >= 65536 with cli_write, then it had better return a size_t, not an ssize_t, and we had better left shift the upper part of the write count, not right shift it. (This used to be commit 3eb33fbc64415600d62ff7b1f2edd67d2dac05b4) --- source3/libsmb/clireadwrite.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 3f14e53094..d1a23d36c8 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -318,9 +318,9 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, 0x0008 start of message mode named pipe protocol ****************************************************************************/ -ssize_t cli_write(struct cli_state *cli, - int fnum, uint16 write_mode, - const char *buf, off_t offset, size_t size) +size_t cli_write(struct cli_state *cli, + int fnum, uint16 write_mode, + const char *buf, off_t offset, size_t size) { int bwritten = 0; int issued = 0; @@ -358,7 +358,7 @@ ssize_t cli_write(struct cli_state *cli, break; bwritten += SVAL(cli->inbuf, smb_vwv2); - bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))>>16); + bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))<<16); } while (received < issued && cli_receive_smb(cli)) -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/libsmb/clireadwrite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index d1a23d36c8..3223098820 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -256,8 +256,8 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, BOOL bigoffset = False; if (size > cli->bufsize) { - cli->outbuf = realloc(cli->outbuf, size + 1024); - cli->inbuf = realloc(cli->inbuf, size + 1024); + cli->outbuf = SMB_REALLOC(cli->outbuf, size + 1024); + cli->inbuf = SMB_REALLOC(cli->inbuf, size + 1024); if (cli->outbuf == NULL || cli->inbuf == NULL) return False; cli->bufsize = size + 1024; -- cgit From 5b713a206bf9c05faad750512886f4bbeebb21f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Dec 2004 00:25:11 +0000 Subject: r4186: Fix client & server to allow 127k READX calls. Jeremy. (This used to be commit 831cb21a874601e4536c2cf76c5351e1d0defcb5) --- source3/libsmb/clireadwrite.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 3223098820..64f16e94ca 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -48,6 +48,7 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, SIVAL(cli->outbuf,smb_vwv3,offset); SSVAL(cli->outbuf,smb_vwv5,size); SSVAL(cli->outbuf,smb_vwv6,size); + SSVAL(cli->outbuf,smb_vwv7,((size >> 16) & 1)); SSVAL(cli->outbuf,smb_mid,cli->mid + i); if (bigoffset) @@ -75,7 +76,11 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ * rounded down to a multiple of 1024. */ - readsize = (cli->max_xmit - (smb_size+32)) & ~1023; + if (cli->capabilities & CAP_LARGE_READX) { + readsize = CLI_MAX_LARGE_READX_SIZE; + } else { + readsize = (cli->max_xmit - (smb_size+32)) & ~1023; + } while (total < size) { readsize = MIN(readsize, size-total); @@ -117,6 +122,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ } size2 = SVAL(cli->inbuf, smb_vwv5); + size2 |= (SVAL(cli->inbuf, smb_vwv7) & 1); if (size2 > readsize) { DEBUG(5,("server returned more than we wanted!\n")); -- cgit From 4730a56263b0547faabbfadb845e8b92bd0b9441 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Dec 2004 00:33:53 +0000 Subject: r4188: Ensure we add in the upper length in the right place ! Jeremy. (This used to be commit 9d4e57f06c4f75f42036e91401b0d0392647752b) --- source3/libsmb/clireadwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 64f16e94ca..1785905ff2 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -122,7 +122,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ } size2 = SVAL(cli->inbuf, smb_vwv5); - size2 |= (SVAL(cli->inbuf, smb_vwv7) & 1); + size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7) & 1)) << 16); if (size2 > readsize) { DEBUG(5,("server returned more than we wanted!\n")); -- cgit From 9e3453459c9166e71f483d67c04be2e49da6c561 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Dec 2004 01:25:24 +0000 Subject: r4212: Ensure we only look at the bottom bit of large_readx. Set the 14 word version of write if size > 0xffff as well as 64-bit offset. Jeremy. (This used to be commit 94779ccb39560bf5eecab77d70f1fa04bfcf1456) --- source3/libsmb/clireadwrite.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 1785905ff2..9e52ed3594 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -259,7 +259,7 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, size_t size, int i) { char *p; - BOOL bigoffset = False; + BOOL large_writex = False; if (size > cli->bufsize) { cli->outbuf = SMB_REALLOC(cli->outbuf, size + 1024); @@ -272,10 +272,11 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - if ((SMB_BIG_UINT)offset >> 32) - bigoffset = True; + if (((SMB_BIG_UINT)offset >> 32) || (size > 0xFFFF)) { + large_writex = True; + } - if (bigoffset) + if (large_writex) set_message(cli->outbuf,14,0,True); else set_message(cli->outbuf,12,0,True); @@ -303,7 +304,7 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, SSVAL(cli->outbuf,smb_vwv11, smb_buf(cli->outbuf) - smb_base(cli->outbuf)); - if (bigoffset) + if (large_writex) SIVAL(cli->outbuf,smb_vwv12,(offset>>32) & 0xffffffff); p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11); -- cgit From ab398643a4e44211696ef5ce72b62ab7ecee7bc9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 19 Jul 2005 02:37:04 +0000 Subject: r8572: Remove crufty #define NO_SYSLOG as it's not used at all anymore. (This used to be commit 985dbb47d925e79c1195ca219f7ab5d6648b22b8) --- source3/libsmb/clireadwrite.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 9e52ed3594..1220907629 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -18,8 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define NO_SYSLOG - #include "includes.h" /**************************************************************************** -- cgit From 54abd2aa66069e6baf7769c496f46d9dba18db39 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 30 Sep 2005 17:13:37 +0000 Subject: r10656: BIG merge from trunk. Features not copied over * \PIPE\unixinfo * winbindd's {group,alias}membership new functions * winbindd's lookupsids() functionality * swat (trunk changes to be reverted as per discussion with Deryck) (This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3) --- source3/libsmb/clireadwrite.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 1220907629..55e36b646b 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -323,13 +323,13 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, 0x0008 start of message mode named pipe protocol ****************************************************************************/ -size_t cli_write(struct cli_state *cli, +ssize_t cli_write(struct cli_state *cli, int fnum, uint16 write_mode, const char *buf, off_t offset, size_t size) { - int bwritten = 0; - int issued = 0; - int received = 0; + ssize_t bwritten = 0; + unsigned int issued = 0; + unsigned int received = 0; int mpx = 1; int block = cli->max_xmit - (smb_size+32); int blocks = (size + (block-1)) / block; @@ -343,8 +343,8 @@ size_t cli_write(struct cli_state *cli, while (received < blocks) { while ((issued - received < mpx) && (issued < blocks)) { - int bsent = issued * block; - int size1 = MIN(block, size - bsent); + ssize_t bsent = issued * block; + ssize_t size1 = MIN(block, size - bsent); if (!cli_issue_write(cli, fnum, offset + bsent, write_mode, -- cgit From 7756059d38e5702b4ba51f71cefb2a4656244cf7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Jan 2006 20:15:08 +0000 Subject: r13119: Fix for #1779 from William Jojo Jeremy. (This used to be commit 103cac7dd314117b15e27fd263a64beeb36ed6e6) --- source3/libsmb/clireadwrite.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 55e36b646b..a080bd3c64 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -49,8 +49,9 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, SSVAL(cli->outbuf,smb_vwv7,((size >> 16) & 1)); SSVAL(cli->outbuf,smb_mid,cli->mid + i); - if (bigoffset) - SIVAL(cli->outbuf,smb_vwv10,(offset>>32) & 0xffffffff); + if (bigoffset) { + SIVAL(cli->outbuf,smb_vwv10,(((SMB_BIG_UINT)offset)>>32) & 0xffffffff); + } return cli_send_smb(cli); } @@ -302,8 +303,9 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, SSVAL(cli->outbuf,smb_vwv11, smb_buf(cli->outbuf) - smb_base(cli->outbuf)); - if (large_writex) - SIVAL(cli->outbuf,smb_vwv12,(offset>>32) & 0xffffffff); + if (large_writex) { + SIVAL(cli->outbuf,smb_vwv12,(((SMB_BIG_UINT)offset)>>32) & 0xffffffff); + } p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11); memcpy(p, buf, size); -- cgit From 894358a8f3e338b339b6c37233edef794b312087 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Mar 2006 06:31:04 +0000 Subject: r13915: Fixed a very interesting class of realloc() bugs found by Coverity. realloc can return NULL in one of two cases - (1) the realloc failed, (2) realloc succeeded but the new size requested was zero, in which case this is identical to a free() call. The error paths dealing with these two cases should be different, but mostly weren't. Secondly the standard idiom for dealing with realloc when you know the new size is non-zero is the following : tmp = realloc(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } However, there were *many* *many* places in Samba where we were using the old (broken) idiom of : p = realloc(p, size) if (!p) { return error; } which will leak the memory pointed to by p on realloc fail. This commit (hopefully) fixes all these cases by moving to a standard idiom of : p = SMB_REALLOC(p, size) if (!p) { return error; } Where if the realloc returns null due to the realloc failing or size == 0 we *guarentee* that the storage pointed to by p has been freed. This allows me to remove a lot of code that was dealing with the standard (more verbose) method that required a tmp pointer. This is almost always what you want. When a realloc fails you never usually want the old memory, you want to free it and get into your error processing asap. For the 11 remaining cases where we really do need to keep the old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR, which can be used as follows : tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the pointer p, even on size == 0 or realloc fail. All this is done by a hidden extra argument to Realloc(), BOOL free_old_on_error which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR macros (and their array counterparts). It remains to be seen what this will do to our Coverity bug count :-). Jeremy. (This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0) --- source3/libsmb/clireadwrite.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index a080bd3c64..650822bf8e 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -262,9 +262,14 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, if (size > cli->bufsize) { cli->outbuf = SMB_REALLOC(cli->outbuf, size + 1024); + if (!cli->outbuf) { + return False; + } cli->inbuf = SMB_REALLOC(cli->inbuf, size + 1024); - if (cli->outbuf == NULL || cli->inbuf == NULL) + if (cli->inbuf == NULL) { + SAFE_FREE(cli->outbuf); return False; + } cli->bufsize = size + 1024; } -- cgit From 7b75d2c650cc8dfe8c9d5b9e396afce1cedb0645 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Apr 2006 02:33:11 +0000 Subject: r15162: Patch for bug #3668. Windows has a bug with LARGE_READX where if you ask for exactly 64k bytes it returns 0. Jeremy. (This used to be commit dcef65acb5bc08ea4b61ef490a518b7e668ff2ee) --- source3/libsmb/clireadwrite.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 650822bf8e..883bc1260d 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -76,7 +76,11 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ */ if (cli->capabilities & CAP_LARGE_READX) { - readsize = CLI_MAX_LARGE_READX_SIZE; + if (cli->is_samba) { + readsize = CLI_SAMBA_MAX_LARGE_READX_SIZE; + } else { + readsize = CLI_WINDOWS_MAX_LARGE_READX_SIZE; + } } else { readsize = (cli->max_xmit - (smb_size+32)) & ~1023; } -- cgit From 02eea79624c85fb5ce6c3ffefe2d27e40c5ff97f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 31 Jul 2006 03:53:39 +0000 Subject: r17333: Some C++ warnings (This used to be commit be9aaffdaccae06c8c035eaf31862e34b7cfbe38) --- source3/libsmb/clireadwrite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 883bc1260d..02fa804f41 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -265,11 +265,11 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, BOOL large_writex = False; if (size > cli->bufsize) { - cli->outbuf = SMB_REALLOC(cli->outbuf, size + 1024); + cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024); if (!cli->outbuf) { return False; } - cli->inbuf = SMB_REALLOC(cli->inbuf, size + 1024); + cli->inbuf = (char *)SMB_REALLOC(cli->inbuf, size + 1024); if (cli->inbuf == NULL) { SAFE_FREE(cli->outbuf); return False; -- cgit From 0829e1ad1c3646efecf50729f493b9ee72ef0517 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 22:40:32 +0000 Subject: r22391: Looks bigger than it is. Make "inbuf" available to all callers of smb_setlen (via set_message() calls). This will allow the server to reflect back the correct encryption context. Jeremy. (This used to be commit 2d80a96120a5fe2fe726f00746d36d85044c4bdb) --- source3/libsmb/clireadwrite.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 02fa804f41..1c72cb2942 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -35,7 +35,7 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, if ((SMB_BIG_UINT)offset >> 32) bigoffset = True; - set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); + set_message(NULL,cli->outbuf,bigoffset ? 12 : 10,0,True); SCVAL(cli->outbuf,smb_com,SMBreadX); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -176,7 +176,7 @@ static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,10,0,True); + set_message(NULL,cli->outbuf,10,0,True); SCVAL(cli->outbuf,smb_com,SMBreadbraw); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -285,9 +285,9 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, } if (large_writex) - set_message(cli->outbuf,14,0,True); + set_message(NULL,cli->outbuf,14,0,True); else - set_message(cli->outbuf,12,0,True); + set_message(NULL,cli->outbuf,12,0,True); SCVAL(cli->outbuf,smb_com,SMBwriteX); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -399,7 +399,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,5, 0,True); + set_message(NULL,cli->outbuf,5, 0,True); SCVAL(cli->outbuf,smb_com,SMBwrite); SSVAL(cli->outbuf,smb_tid,cli->cnum); -- cgit From 32106b23951e01fb17f814584ebbcc8d7288cb75 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 May 2007 00:07:38 +0000 Subject: r22920: Add in the UNIX capability for 24-bit readX, as discussed with the Apple guys and Linux kernel guys. Still looking at how to do writeX as there's no recvfile(). Jeremy. (This used to be commit a53268fb2082de586e2df250d8ddfcff53379102) --- source3/libsmb/clireadwrite.c | 50 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 1c72cb2942..35d2afe2e7 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -46,7 +46,7 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, SIVAL(cli->outbuf,smb_vwv3,offset); SSVAL(cli->outbuf,smb_vwv5,size); SSVAL(cli->outbuf,smb_vwv6,size); - SSVAL(cli->outbuf,smb_vwv7,((size >> 16) & 1)); + SSVAL(cli->outbuf,smb_vwv7,(size >> 16)); SSVAL(cli->outbuf,smb_mid,cli->mid + i); if (bigoffset) { @@ -63,9 +63,11 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) { char *p; - int size2; - int readsize; + size_t size2; + size_t readsize; ssize_t total = 0; + /* We can only do direct reads if not signing. */ + BOOL direct_reads = !client_is_signing_on(cli); if (size == 0) return 0; @@ -75,7 +77,11 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ * rounded down to a multiple of 1024. */ - if (cli->capabilities & CAP_LARGE_READX) { + if (client_is_signing_on(cli) == False && + cli_encryption_on(cli) == False && + (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { + readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; + } else if (cli->capabilities & CAP_LARGE_READX) { if (cli->is_samba) { readsize = CLI_SAMBA_MAX_LARGE_READX_SIZE; } else { @@ -93,8 +99,13 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ if (!cli_issue_read(cli, fnum, offset, readsize, 0)) return -1; - if (!cli_receive_smb(cli)) - return -1; + if (direct_reads) { + if (!cli_receive_smb_readX_header(cli)) + return -1; + } else { + if (!cli_receive_smb(cli)) + return -1; + } /* Check for error. Make sure to check for DOS and NT errors. */ @@ -125,7 +136,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ } size2 = SVAL(cli->inbuf, smb_vwv5); - size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7) & 1)) << 16); + size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7))) << 16); if (size2 > readsize) { DEBUG(5,("server returned more than we wanted!\n")); @@ -135,10 +146,29 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return -1; } - /* Copy data into buffer */ + if (!direct_reads) { + /* Copy data into buffer */ + p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); + memcpy(buf + total, p, size2); + } else { + /* Ensure the remaining data matches the return size. */ + ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); - p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); - memcpy(buf + total, p, size2); + /* Ensure the size is correct. */ + if (toread != size2) { + DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } + + /* Read data directly into buffer */ + toread = cli_receive_smb_data(cli,buf+total,size2); + if (toread != size2) { + DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } + } total += size2; offset += size2; -- cgit From 4d6caa09e2b8c1c26f3dde832586d871bbbc2dda Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 May 2007 23:50:35 +0000 Subject: r23148: Fix old old bug in cli_smbwrite() (not incrementing data being sent). Patch from mnix@wanm.com.au. Jeremy. (This used to be commit 2524d85465ba5406e684199c10f59e685ab860b5) --- source3/libsmb/clireadwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 35d2afe2e7..c31d417fbd 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -443,7 +443,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, p = smb_buf(cli->outbuf); *p++ = 1; SSVAL(p, 0, size); p += 2; - memcpy(p, buf, size); p += size; + memcpy(p, buf + total, size); p += size; cli_setup_bcc(cli, p); -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/libsmb/clireadwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index c31d417fbd..3ba9be58b6 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/libsmb/clireadwrite.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 3ba9be58b6..7e479dc00a 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/libsmb/clireadwrite.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 7e479dc00a..ed80dfaf1a 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -34,7 +34,7 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, if ((SMB_BIG_UINT)offset >> 32) bigoffset = True; - set_message(NULL,cli->outbuf,bigoffset ? 12 : 10,0,True); + set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); SCVAL(cli->outbuf,smb_com,SMBreadX); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -76,9 +76,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ * rounded down to a multiple of 1024. */ - if (client_is_signing_on(cli) == False && - cli_encryption_on(cli) == False && - (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { + if (client_is_signing_on(cli) == False && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; } else if (cli->capabilities & CAP_LARGE_READX) { if (cli->is_samba) { @@ -205,7 +203,7 @@ static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(NULL,cli->outbuf,10,0,True); + set_message(cli->outbuf,10,0,True); SCVAL(cli->outbuf,smb_com,SMBreadbraw); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -314,9 +312,9 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, } if (large_writex) - set_message(NULL,cli->outbuf,14,0,True); + set_message(cli->outbuf,14,0,True); else - set_message(NULL,cli->outbuf,12,0,True); + set_message(cli->outbuf,12,0,True); SCVAL(cli->outbuf,smb_com,SMBwriteX); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -428,7 +426,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(NULL,cli->outbuf,5, 0,True); + set_message(cli->outbuf,5, 0,True); SCVAL(cli->outbuf,smb_com,SMBwrite); SSVAL(cli->outbuf,smb_tid,cli->cnum); -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/libsmb/clireadwrite.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index ed80dfaf1a..0d037e946e 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -23,10 +23,10 @@ Issue a single SMBread and don't wait for a reply. ****************************************************************************/ -static BOOL 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) { - BOOL bigoffset = False; + bool bigoffset = False; memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); @@ -66,7 +66,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ size_t readsize; ssize_t total = 0; /* We can only do direct reads if not signing. */ - BOOL direct_reads = !client_is_signing_on(cli); + bool direct_reads = !client_is_signing_on(cli); if (size == 0) return 0; @@ -108,7 +108,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ errors. */ if (cli_is_error(cli)) { - BOOL recoverable_error = False; + bool recoverable_error = False; NTSTATUS status = NT_STATUS_OK; uint8 eclass = 0; uint32 ecode = 0; @@ -191,7 +191,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ Issue a single SMBreadraw and don't wait for a reply. ****************************************************************************/ -static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, +static bool cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, size_t size, int i) { @@ -284,12 +284,12 @@ ssize_t cli_readraw(struct cli_state *cli, int fnum, char *buf, off_t offset, si issue a single SMBwrite and don't wait for a reply ****************************************************************************/ -static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, +static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, const char *buf, size_t size, int i) { char *p; - BOOL large_writex = False; + bool large_writex = False; if (size > cli->bufsize) { cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024); -- cgit From f5dcac6e8ed17a45d82ce395b01f8d5418a11331 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Oct 2007 12:54:39 -0700 Subject: Our userlevel SMBwriteX call is non-standard in that it sometimes uses a 12-word write and doesn't include a pad byte (as Windows does). Fix this so that we are identical to Windows clients. This will make recvfile processing much easier to detect (as we can just read a standard writeX header length to decide). Jeremy. (This used to be commit 3d3d1b806aef3617abaac46daf230ed32076e2ce) --- source3/libsmb/clireadwrite.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 0d037e946e..e2d5337ee4 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -291,7 +291,7 @@ static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, char *p; bool large_writex = False; - if (size > cli->bufsize) { + if (size + 1 > cli->bufsize) { cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024); if (!cli->outbuf) { return False; @@ -307,7 +307,7 @@ static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - if (((SMB_BIG_UINT)offset >> 32) || (size > 0xFFFF)) { + if (cli->capabilities & CAP_LARGE_FILES) { large_writex = True; } @@ -315,11 +315,11 @@ static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, set_message(cli->outbuf,14,0,True); else set_message(cli->outbuf,12,0,True); - + SCVAL(cli->outbuf,smb_com,SMBwriteX); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - + SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,fnum); @@ -336,19 +336,21 @@ static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, */ SSVAL(cli->outbuf,smb_vwv9,((size>>16)&1)); SSVAL(cli->outbuf,smb_vwv10,size); + /* +1 is pad byte. */ SSVAL(cli->outbuf,smb_vwv11, - smb_buf(cli->outbuf) - smb_base(cli->outbuf)); + smb_buf(cli->outbuf) - smb_base(cli->outbuf) + 1); if (large_writex) { SIVAL(cli->outbuf,smb_vwv12,(((SMB_BIG_UINT)offset)>>32) & 0xffffffff); } - - p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11); + + p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11) -1; + *p++ = '\0'; /* pad byte. */ memcpy(p, buf, size); cli_setup_bcc(cli, p+size); SSVAL(cli->outbuf,smb_mid,cli->mid + i); - + show_msg(cli->outbuf); return cli_send_smb(cli); } -- cgit From 329365684bca99bf9020b6638a1357df65c1d938 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 2 Nov 2007 12:21:34 -0700 Subject: Change the client library to write directly out of the incoming buffer in the non-signed case. Speeds up writes by over 10% or so. Complete the server recvfile implementation. Jeremy. (This used to be commit 81ca5853b2475f123faab3b550f0a7b24ae3c208) --- source3/libsmb/clireadwrite.c | 106 +++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 32 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index e2d5337ee4..0c79da9f84 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -1,18 +1,18 @@ -/* +/* Unix SMB/CIFS implementation. client file read/write routines Copyright (C) Andrew Tridgell 1994-1998 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 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, see . */ @@ -23,7 +23,7 @@ Issue a single SMBread and don't wait for a reply. ****************************************************************************/ -static bool 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) { bool bigoffset = False; @@ -31,11 +31,11 @@ static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - if ((SMB_BIG_UINT)offset >> 32) + if ((SMB_BIG_UINT)offset >> 32) bigoffset = True; set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); - + SCVAL(cli->outbuf,smb_com,SMBreadX); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); @@ -68,7 +68,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ /* We can only do direct reads if not signing. */ bool direct_reads = !client_is_signing_on(cli); - if (size == 0) + if (size == 0) return 0; /* @@ -280,18 +280,25 @@ ssize_t cli_readraw(struct cli_state *cli, int fnum, char *buf, off_t offset, si return total; } #endif + /**************************************************************************** -issue a single SMBwrite and don't wait for a reply + Issue a single SMBwrite and don't wait for a reply. ****************************************************************************/ -static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, - uint16 mode, const char *buf, - size_t size, int i) +static bool cli_issue_write(struct cli_state *cli, + int fnum, + off_t offset, + uint16 mode, + const char *buf, + size_t size, + int i) { char *p; - bool large_writex = False; + bool large_writex = false; + /* We can only do direct writes if not signing. */ + bool direct_writes = !client_is_signing_on(cli); - if (size + 1 > cli->bufsize) { + if (!direct_writes && size + 1 > cli->bufsize) { cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024); if (!cli->outbuf) { return False; @@ -311,10 +318,11 @@ static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, large_writex = True; } - if (large_writex) + if (large_writex) { set_message(cli->outbuf,14,0,True); - else + } else { set_message(cli->outbuf,12,0,True); + } SCVAL(cli->outbuf,smb_com,SMBwriteX); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -334,7 +342,7 @@ static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, * locally. However, this check might already have been * done by our callers. */ - SSVAL(cli->outbuf,smb_vwv9,((size>>16)&1)); + SSVAL(cli->outbuf,smb_vwv9,(size>>16)); SSVAL(cli->outbuf,smb_vwv10,size); /* +1 is pad byte. */ SSVAL(cli->outbuf,smb_vwv11, @@ -346,13 +354,27 @@ static bool cli_issue_write(struct cli_state *cli, int fnum, off_t offset, p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11) -1; *p++ = '\0'; /* pad byte. */ - memcpy(p, buf, size); - cli_setup_bcc(cli, p+size); + if (!direct_writes) { + memcpy(p, buf, size); + } + if (size > 0x1FFFF) { + /* This is a POSIX 14 word large write. */ + set_message_bcc(cli->outbuf, 0); /* Set bcc to zero. */ + _smb_setlen_large(cli->outbuf,smb_size + 28 + 1 /* pad */ + size - 4); + } else { + cli_setup_bcc(cli, p+size); + } SSVAL(cli->outbuf,smb_mid,cli->mid + i); show_msg(cli->outbuf); - return cli_send_smb(cli); + if (direct_writes) { + /* For direct writes we now need to write the data + * directly out of buf. */ + return cli_send_smb_direct_writeX(cli, buf, size); + } else { + return cli_send_smb(cli); + } } /**************************************************************************** @@ -371,8 +393,8 @@ ssize_t cli_write(struct cli_state *cli, unsigned int issued = 0; unsigned int received = 0; int mpx = 1; - int block = cli->max_xmit - (smb_size+32); - int blocks = (size + (block-1)) / block; + size_t writesize; + int blocks; if(cli->max_mux > 1) { mpx = cli->max_mux-1; @@ -380,11 +402,29 @@ ssize_t cli_write(struct cli_state *cli, mpx = 1; } + if (!client_is_signing_on(cli) && + (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) && + (cli->capabilities & CAP_LARGE_FILES)) { + /* Only do massive writes if we can do them direct + * with no signing. */ + writesize = CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE; + } else if (cli->capabilities & CAP_LARGE_READX) { + if (cli->is_samba) { + writesize = CLI_SAMBA_MAX_LARGE_READX_SIZE; + } else { + writesize = CLI_WINDOWS_MAX_LARGE_READX_SIZE; + } + } else { + writesize = (cli->max_xmit - (smb_size+32)) & ~1023; + } + + blocks = (size + (writesize-1)) / writesize; + while (received < blocks) { while ((issued - received < mpx) && (issued < blocks)) { - ssize_t bsent = issued * block; - ssize_t size1 = MIN(block, size - bsent); + ssize_t bsent = issued * writesize; + ssize_t size1 = MIN(writesize, size - bsent); if (!cli_issue_write(cli, fnum, offset + bsent, write_mode, @@ -394,8 +434,9 @@ ssize_t cli_write(struct cli_state *cli, issued++; } - if (!cli_receive_smb(cli)) + if (!cli_receive_smb(cli)) { return bwritten; + } received++; @@ -406,9 +447,10 @@ ssize_t cli_write(struct cli_state *cli, bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))<<16); } - while (received < issued && cli_receive_smb(cli)) + while (received < issued && cli_receive_smb(cli)) { received++; - + } + return bwritten; } @@ -424,7 +466,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, do { size_t size = MIN(size1, cli->max_xmit - 48); - + memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); @@ -433,25 +475,25 @@ ssize_t cli_smbwrite(struct cli_state *cli, SCVAL(cli->outbuf,smb_com,SMBwrite); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - + SSVAL(cli->outbuf,smb_vwv0,fnum); SSVAL(cli->outbuf,smb_vwv1,size); SIVAL(cli->outbuf,smb_vwv2,offset); SSVAL(cli->outbuf,smb_vwv4,0); - + p = smb_buf(cli->outbuf); *p++ = 1; SSVAL(p, 0, size); p += 2; memcpy(p, buf + total, size); p += size; cli_setup_bcc(cli, p); - + if (!cli_send_smb(cli)) return -1; if (!cli_receive_smb(cli)) return -1; - + if (cli_is_error(cli)) return -1; -- cgit From 7498e1b8c09abef2db0658c6bfd6d42891c9690d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Nov 2007 14:12:38 -0800 Subject: Ensure we don't use massive writes in pipe mode. Jeremy. (This used to be commit 47640fb20e42f226e7ea104076fd52547bfe1abb) --- source3/libsmb/clireadwrite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 0c79da9f84..d77875bae5 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -402,11 +402,12 @@ ssize_t cli_write(struct cli_state *cli, mpx = 1; } - if (!client_is_signing_on(cli) && + if (write_mode == 0 && + !client_is_signing_on(cli) && (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) && (cli->capabilities & CAP_LARGE_FILES)) { /* Only do massive writes if we can do them direct - * with no signing. */ + * with no signing - not on a pipe. */ writesize = CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE; } else if (cli->capabilities & CAP_LARGE_READX) { if (cli->is_samba) { -- cgit From afc93255d183eefb68e45b8ec6275f6a62cf9795 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Dec 2007 17:12:36 -0800 Subject: Add SMB encryption. Still fixing client decrypt but negotiation works. Jeremy. (This used to be commit d78045601af787731f0737b8627450018902b104) --- source3/libsmb/clireadwrite.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index d77875bae5..0b33e43563 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -34,7 +34,7 @@ static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset, if ((SMB_BIG_UINT)offset >> 32) bigoffset = True; - set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); + cli_set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); SCVAL(cli->outbuf,smb_com,SMBreadX); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -65,8 +65,8 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ size_t size2; size_t readsize; ssize_t total = 0; - /* We can only do direct reads if not signing. */ - bool direct_reads = !client_is_signing_on(cli); + /* We can only do direct reads if not signing or encrypting. */ + bool direct_reads = !client_is_signing_on(cli) && !cli_encryption_on(cli); if (size == 0) return 0; @@ -76,7 +76,9 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ * rounded down to a multiple of 1024. */ - if (client_is_signing_on(cli) == False && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { + if (client_is_signing_on(cli) == false && + cli_encryption_on(cli) == false && + (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; } else if (cli->capabilities & CAP_LARGE_READX) { if (cli->is_samba) { @@ -203,7 +205,7 @@ static bool cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,10,0,True); + cli_set_message(cli->outbuf,10,0,True); SCVAL(cli->outbuf,smb_com,SMBreadbraw); SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -295,8 +297,8 @@ static bool cli_issue_write(struct cli_state *cli, { char *p; bool large_writex = false; - /* We can only do direct writes if not signing. */ - bool direct_writes = !client_is_signing_on(cli); + /* We can only do direct writes if not signing and not encrypting. */ + bool direct_writes = !client_is_signing_on(cli) && !cli_encryption_on(cli); if (!direct_writes && size + 1 > cli->bufsize) { cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024); @@ -319,9 +321,9 @@ static bool cli_issue_write(struct cli_state *cli, } if (large_writex) { - set_message(cli->outbuf,14,0,True); + cli_set_message(cli->outbuf,14,0,True); } else { - set_message(cli->outbuf,12,0,True); + cli_set_message(cli->outbuf,12,0,True); } SCVAL(cli->outbuf,smb_com,SMBwriteX); @@ -404,16 +406,17 @@ ssize_t cli_write(struct cli_state *cli, if (write_mode == 0 && !client_is_signing_on(cli) && + !cli_encryption_on(cli) && (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) && (cli->capabilities & CAP_LARGE_FILES)) { /* Only do massive writes if we can do them direct - * with no signing - not on a pipe. */ + * with no signing or encrypting - not on a pipe. */ writesize = CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE; - } else if (cli->capabilities & CAP_LARGE_READX) { + } else if (cli->capabilities & CAP_LARGE_WRITEX) { if (cli->is_samba) { - writesize = CLI_SAMBA_MAX_LARGE_READX_SIZE; + writesize = CLI_SAMBA_MAX_LARGE_WRITEX_SIZE; } else { - writesize = CLI_WINDOWS_MAX_LARGE_READX_SIZE; + writesize = CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE; } } else { writesize = (cli->max_xmit - (smb_size+32)) & ~1023; @@ -471,7 +474,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,5, 0,True); + cli_set_message(cli->outbuf,5, 0,True); SCVAL(cli->outbuf,smb_com,SMBwrite); SSVAL(cli->outbuf,smb_tid,cli->cnum); -- cgit From d7582b51863c44fdbffc8140a95950a3762d4b40 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 14 Jan 2008 13:46:06 -0800 Subject: Windows insists on write sizes < max_xmit on signed connections. Jeremy. (This used to be commit ef9b278b6289a9ecdd6b103927058f64fbb7eb97) --- source3/libsmb/clireadwrite.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 0b33e43563..6b39a885f0 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -404,6 +404,9 @@ ssize_t cli_write(struct cli_state *cli, mpx = 1; } + /* Default (small) writesize. */ + writesize = (cli->max_xmit - (smb_size+32)) & ~1023; + if (write_mode == 0 && !client_is_signing_on(cli) && !cli_encryption_on(cli) && @@ -415,11 +418,11 @@ ssize_t cli_write(struct cli_state *cli, } else if (cli->capabilities & CAP_LARGE_WRITEX) { if (cli->is_samba) { writesize = CLI_SAMBA_MAX_LARGE_WRITEX_SIZE; - } else { + } else if (!client_is_signing_on(cli)) { + /* Windows restricts signed writes to max_xmit. + * Found by Volker. */ writesize = CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE; } - } else { - writesize = (cli->max_xmit - (smb_size+32)) & ~1023; } blocks = (size + (writesize-1)) / writesize; -- cgit From f44713df4d636203354c55d9a9bc2538073cf0af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Jan 2008 17:33:19 -0800 Subject: Fix bug found by Derrell - windows returns an read return offset of zero if return size is zero. Should fix testread libsmbclient code. Jeremy. (This used to be commit df3c4648399f8d62ff6fe0013be8b89abc18f0f0) --- source3/libsmb/clireadwrite.c | 49 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 6b39a885f0..af13ed8f73 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -134,6 +134,8 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return -1; } + /* size2 is the number of bytes the server returned. + * Might be zero. */ size2 = SVAL(cli->inbuf, smb_vwv5); size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7))) << 16); @@ -145,27 +147,32 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return -1; } - if (!direct_reads) { - /* Copy data into buffer */ - p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); - memcpy(buf + total, p, size2); - } else { - /* Ensure the remaining data matches the return size. */ - ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); - - /* Ensure the size is correct. */ - if (toread != size2) { - DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; - } - - /* Read data directly into buffer */ - toread = cli_receive_smb_data(cli,buf+total,size2); - if (toread != size2) { - DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; + if (size2) { + /* smb_vwv6 is the offset in the packet of the returned + * data bytes. Only valid if size2 != 0. */ + + if (!direct_reads) { + /* Copy data into buffer */ + p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); + memcpy(buf + total, p, size2); + } else { + /* Ensure the remaining data matches the return size. */ + ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); + + /* Ensure the size is correct. */ + if (toread != size2) { + DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } + + /* Read data directly into buffer */ + toread = cli_receive_smb_data(cli,buf+total,size2); + if (toread != size2) { + DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } } } -- cgit From 62445788350b2f174537d877d721d92147f93ec7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 15:21:33 +0100 Subject: Add async cli_pull support This is the big (and potentially controversial) one. It took a phone call to explain to metze what is going on inside cli_pull_read_done, but I would really like everybody to understand this function. It is a very good and reasonably complex example of async programming. If we want more asynchronism in s3, this is what we will have to deal with :-) Make use of it in the smbclient "get" command. Volker (This used to be commit 76f9b360ee1d973630d82d401eeddce858189301) --- source3/libsmb/clireadwrite.c | 425 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 425 insertions(+) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index af13ed8f73..5aee8f18bd 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -19,6 +19,431 @@ #include "includes.h" +/**************************************************************************** + Calculate the recommended read buffer size +****************************************************************************/ +static size_t cli_read_max_bufsize(struct cli_state *cli) +{ + if (!client_is_signing_on(cli) && !cli_encryption_on(cli) == false + && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { + return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; + } + if (cli->capabilities & CAP_LARGE_READX) { + return cli->is_samba + ? CLI_SAMBA_MAX_LARGE_READX_SIZE + : CLI_WINDOWS_MAX_LARGE_READX_SIZE; + } + return (cli->max_xmit - (smb_size+32)) & ~1023; +} + +/* + * Send a read&x request + */ + +struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct cli_state *cli, int fnum, + off_t offset, size_t size) +{ + struct async_req *result; + struct cli_request *req; + bool bigoffset = False; + char *enc_buf; + + if (size > cli_read_max_bufsize(cli)) { + DEBUG(0, ("cli_read_andx_send got size=%d, can only handle " + "size=%d\n", (int)size, + (int)cli_read_max_bufsize(cli))); + return NULL; + } + + result = cli_request_new(mem_ctx, cli->event_ctx, cli, 12, 0, &req); + if (result == NULL) { + DEBUG(0, ("cli_request_new failed\n")); + return NULL; + } + + req = cli_request_get(result); + + req->data.read.ofs = offset; + req->data.read.size = size; + req->data.read.received = 0; + req->data.read.rcvbuf = NULL; + + if ((SMB_BIG_UINT)offset >> 32) + bigoffset = True; + + cli_set_message(req->outbuf, bigoffset ? 12 : 10, 0, False); + + SCVAL(req->outbuf,smb_com,SMBreadX); + SSVAL(req->outbuf,smb_tid,cli->cnum); + cli_setup_packet_buf(cli, req->outbuf); + + SCVAL(req->outbuf,smb_vwv0,0xFF); + SCVAL(req->outbuf,smb_vwv0+1,0); + SSVAL(req->outbuf,smb_vwv1,0); + SSVAL(req->outbuf,smb_vwv2,fnum); + SIVAL(req->outbuf,smb_vwv3,offset); + SSVAL(req->outbuf,smb_vwv5,size); + SSVAL(req->outbuf,smb_vwv6,size); + SSVAL(req->outbuf,smb_vwv7,(size >> 16)); + SSVAL(req->outbuf,smb_vwv8,0); + SSVAL(req->outbuf,smb_vwv9,0); + SSVAL(req->outbuf,smb_mid,req->mid); + + if (bigoffset) { + SIVAL(req->outbuf, smb_vwv10, + (((SMB_BIG_UINT)offset)>>32) & 0xffffffff); + } + + cli_calculate_sign_mac(cli, req->outbuf); + + event_fd_set_writeable(cli->fd_event); + + if (cli_encryption_on(cli)) { + NTSTATUS status; + status = cli_encrypt_message(cli, req->outbuf, &enc_buf); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Error in encrypting client message. " + "Error %s\n", nt_errstr(status))); + TALLOC_FREE(req); + return NULL; + } + req->outbuf = enc_buf; + req->enc_state = cli->trans_enc_state; + } + + return result; +} + +/* + * Pull the data out of a finished async read_and_x request. rcvbuf is + * talloced from the request, so better make sure that you copy it away before + * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not + * talloc_move it! + */ + +NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, + uint8_t **rcvbuf) +{ + struct cli_request *cli_req = cli_request_get(req); + NTSTATUS status; + size_t size; + + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; + } + + status = cli_pull_error(cli_req->inbuf); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* size is the number of bytes the server returned. + * Might be zero. */ + size = SVAL(cli_req->inbuf, smb_vwv5); + size |= (((unsigned int)(SVAL(cli_req->inbuf, smb_vwv7))) << 16); + + if (size > cli_req->data.read.size) { + DEBUG(5,("server returned more than we wanted!\n")); + return NT_STATUS_UNEXPECTED_IO_ERROR; + } + + if (size < 0) { + DEBUG(5,("read return < 0!\n")); + return NT_STATUS_UNEXPECTED_IO_ERROR; + } + + *rcvbuf = (uint8_t *) + (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6)); + *received = size; + return NT_STATUS_OK; +} + +/* + * Parallel read support. + * + * cli_pull sends as many read&x requests as the server would allow via + * max_mux at a time. When replies flow back in, the data is written into + * the callback function "sink" in the right order. + */ + +struct cli_pull_state { + struct async_req *req; + + struct cli_state *cli; + uint16_t fnum; + off_t start_offset; + size_t size; + + NTSTATUS (*sink)(char *buf, size_t n, void *priv); + void *priv; + + size_t chunk_size; + + /* + * Outstanding requests + */ + int num_reqs; + struct async_req **reqs; + + /* + * For how many bytes did we send requests already? + */ + off_t requested; + + /* + * Next request index to push into "sink". This walks around the "req" + * array, taking care that the requests are pushed to "sink" in the + * right order. If necessary (i.e. replies don't come in in the right + * order), replies are held back in "reqs". + */ + int top_req; + + /* + * How many bytes did we push into "sink"? + */ + + off_t pushed; +}; + +static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req) +{ + struct cli_pull_state *state = talloc_get_type_abort( + req->private_data, struct cli_pull_state); + char *result; + + result = async_req_print(mem_ctx, req); + if (result == NULL) { + return NULL; + } + + return talloc_asprintf_append_buffer( + result, "num_reqs=%d, top_req=%d", + state->num_reqs, state->top_req); +} + +static void cli_pull_read_done(struct async_req *read_req); + +/* + * Prepare an async pull request + */ + +struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, + uint16_t fnum, off_t start_offset, + size_t size, size_t window_size, + NTSTATUS (*sink)(char *buf, size_t n, + void *priv), + void *priv) +{ + struct async_req *result; + struct cli_pull_state *state; + int i; + + result = async_req_new(mem_ctx, cli->event_ctx); + if (result == NULL) { + goto failed; + } + state = talloc(result, struct cli_pull_state); + if (state == NULL) { + goto failed; + } + result->private_data = state; + result->print = cli_pull_print; + state->req = result; + + state->cli = cli; + state->fnum = fnum; + state->start_offset = start_offset; + state->size = size; + state->sink = sink; + state->priv = priv; + + state->pushed = 0; + state->top_req = 0; + state->chunk_size = cli_read_max_bufsize(cli); + + state->num_reqs = MAX(window_size/state->chunk_size, 1); + state->num_reqs = MIN(state->num_reqs, cli->max_mux); + + state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *, + state->num_reqs); + if (state->reqs == NULL) { + goto failed; + } + + state->requested = 0; + + for (i=0; inum_reqs; i++) { + size_t size_left, request_thistime; + + if (state->requested >= size) { + state->num_reqs = i; + break; + } + + size_left = size - state->requested; + request_thistime = MIN(size_left, state->chunk_size); + + state->reqs[i] = cli_read_andx_send( + state->reqs, cli, fnum, + state->start_offset + state->requested, + request_thistime); + + if (state->reqs[i] == NULL) { + goto failed; + } + + state->reqs[i]->async.fn = cli_pull_read_done; + state->reqs[i]->async.priv = result; + + state->requested += request_thistime; + } + return result; + +failed: + TALLOC_FREE(result); + return NULL; +} + +/* + * Handle incoming read replies, push the data into sink and send out new + * requests if necessary. + */ + +static void cli_pull_read_done(struct async_req *read_req) +{ + struct async_req *pull_req = talloc_get_type_abort( + read_req->async.priv, struct async_req); + struct cli_pull_state *state = talloc_get_type_abort( + pull_req->private_data, struct cli_pull_state); + struct cli_request *read_state = cli_request_get(read_req); + NTSTATUS status; + + status = cli_read_andx_recv(read_req, &read_state->data.read.received, + &read_state->data.read.rcvbuf); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(state->req, status); + return; + } + + /* + * This loop is the one to take care of out-of-order replies. All + * pending requests are in state->reqs, state->reqs[top_req] is the + * one that is to be pushed next. If however a request later than + * top_req is replied to, then we can't push yet. If top_req is + * replied to at a later point then, we need to push all the finished + * requests. + */ + + while (state->reqs[state->top_req] != NULL) { + struct cli_request *top_read; + + DEBUG(11, ("cli_pull_read_done: top_req = %d\n", + state->top_req)); + + if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) { + DEBUG(11, ("cli_pull_read_done: top request not yet " + "done\n")); + return; + } + + top_read = cli_request_get(state->reqs[state->top_req]); + + DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " + "pushed\n", (int)top_read->data.read.received, + (int)state->pushed)); + + status = state->sink((char *)top_read->data.read.rcvbuf, + top_read->data.read.received, + state->priv); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(state->req, status); + return; + } + state->pushed += top_read->data.read.received; + + TALLOC_FREE(state->reqs[state->top_req]); + + if (state->requested < state->size) { + struct async_req *new_req; + size_t size_left, request_thistime; + + size_left = state->size - state->requested; + request_thistime = MIN(size_left, state->chunk_size); + + DEBUG(10, ("cli_pull_read_done: Requesting %d bytes " + "at %d, position %d\n", + (int)request_thistime, + (int)(state->start_offset + + state->requested), + state->top_req)); + + new_req = cli_read_andx_send( + state->reqs, state->cli, state->fnum, + state->start_offset + state->requested, + request_thistime); + + if (async_req_nomem(new_req, state->req)) { + return; + } + + new_req->async.fn = cli_pull_read_done; + new_req->async.priv = pull_req; + + state->reqs[state->top_req] = new_req; + state->requested += request_thistime; + } + + state->top_req = (state->top_req+1) % state->num_reqs; + } + + async_req_done(pull_req); +} + +NTSTATUS cli_pull_recv(struct async_req *req, ssize_t *received) +{ + struct cli_pull_state *state = talloc_get_type_abort( + req->private_data, struct cli_pull_state); + + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; + } + *received = state->pushed; + return NT_STATUS_OK; +} + +NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, + off_t start_offset, size_t size, size_t window_size, + NTSTATUS (*sink)(char *buf, size_t n, void *priv), + void *priv, ssize_t *received) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct async_req *req; + NTSTATUS result = NT_STATUS_NO_MEMORY; + + if (cli_tmp_event_ctx(frame, cli) == NULL) { + goto nomem; + } + + req = cli_pull_send(frame, cli, fnum, start_offset, size, window_size, + sink, priv); + if (req == NULL) { + goto nomem; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(cli->event_ctx); + } + + result = cli_pull_recv(req, received); + nomem: + TALLOC_FREE(frame); + return result; +} + /**************************************************************************** Issue a single SMBread and don't wait for a reply. ****************************************************************************/ -- cgit From a01522749055d5d44865a255d094ff5255f8ac04 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 15:26:01 +0100 Subject: Convert cli_read to use cli_pull (This used to be commit d69b20111a849152a7d9108763207c813bf9068b) --- source3/libsmb/clireadwrite.c | 178 ++++-------------------------------------- 1 file changed, 15 insertions(+), 163 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 5aee8f18bd..c618509f01 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -444,175 +444,27 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, return result; } -/**************************************************************************** -Issue a single SMBread and don't wait for a reply. -****************************************************************************/ - -static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset, - size_t size, int i) +static NTSTATUS cli_read_sink(char *buf, size_t n, void *priv) { - bool bigoffset = False; - - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); - - if ((SMB_BIG_UINT)offset >> 32) - bigoffset = True; - - cli_set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); - - SCVAL(cli->outbuf,smb_com,SMBreadX); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); - - SCVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,fnum); - SIVAL(cli->outbuf,smb_vwv3,offset); - SSVAL(cli->outbuf,smb_vwv5,size); - SSVAL(cli->outbuf,smb_vwv6,size); - SSVAL(cli->outbuf,smb_vwv7,(size >> 16)); - SSVAL(cli->outbuf,smb_mid,cli->mid + i); - - if (bigoffset) { - SIVAL(cli->outbuf,smb_vwv10,(((SMB_BIG_UINT)offset)>>32) & 0xffffffff); - } - - return cli_send_smb(cli); + char **pbuf = (char **)priv; + memcpy(*pbuf, buf, n); + *pbuf += n; + return NT_STATUS_OK; } -/**************************************************************************** - Read size bytes at offset offset using SMBreadX. -****************************************************************************/ - -ssize_t cli_read(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) { - char *p; - size_t size2; - size_t readsize; - ssize_t total = 0; - /* We can only do direct reads if not signing or encrypting. */ - bool direct_reads = !client_is_signing_on(cli) && !cli_encryption_on(cli); - - if (size == 0) - return 0; - - /* - * Set readsize to the maximum size we can handle in one readX, - * rounded down to a multiple of 1024. - */ - - if (client_is_signing_on(cli) == false && - cli_encryption_on(cli) == false && - (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { - readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; - } else if (cli->capabilities & CAP_LARGE_READX) { - if (cli->is_samba) { - readsize = CLI_SAMBA_MAX_LARGE_READX_SIZE; - } else { - readsize = CLI_WINDOWS_MAX_LARGE_READX_SIZE; - } - } else { - readsize = (cli->max_xmit - (smb_size+32)) & ~1023; - } - - while (total < size) { - readsize = MIN(readsize, size-total); - - /* Issue a read and receive a reply */ - - if (!cli_issue_read(cli, fnum, offset, readsize, 0)) - return -1; - - if (direct_reads) { - if (!cli_receive_smb_readX_header(cli)) - return -1; - } else { - if (!cli_receive_smb(cli)) - return -1; - } - - /* Check for error. Make sure to check for DOS and NT - errors. */ - - if (cli_is_error(cli)) { - bool recoverable_error = False; - NTSTATUS status = NT_STATUS_OK; - uint8 eclass = 0; - uint32 ecode = 0; - - if (cli_is_nt_error(cli)) - status = cli_nt_error(cli); - else - cli_dos_error(cli, &eclass, &ecode); - - /* - * ERRDOS ERRmoredata or STATUS_MORE_ENRTIES is a - * recoverable error, plus we have valid data in the - * packet so don't error out here. - */ - - if ((eclass == ERRDOS && ecode == ERRmoredata) || - NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES)) - recoverable_error = True; - - if (!recoverable_error) - return -1; - } - - /* size2 is the number of bytes the server returned. - * Might be zero. */ - size2 = SVAL(cli->inbuf, smb_vwv5); - size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7))) << 16); - - if (size2 > readsize) { - DEBUG(5,("server returned more than we wanted!\n")); - return -1; - } else if (size2 < 0) { - DEBUG(5,("read return < 0!\n")); - return -1; - } - - if (size2) { - /* smb_vwv6 is the offset in the packet of the returned - * data bytes. Only valid if size2 != 0. */ - - if (!direct_reads) { - /* Copy data into buffer */ - p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); - memcpy(buf + total, p, size2); - } else { - /* Ensure the remaining data matches the return size. */ - ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); - - /* Ensure the size is correct. */ - if (toread != size2) { - DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; - } - - /* Read data directly into buffer */ - toread = cli_receive_smb_data(cli,buf+total,size2); - if (toread != size2) { - DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; - } - } - } - - total += size2; - offset += size2; - - /* - * If the server returned less than we asked for we're at EOF. - */ + NTSTATUS status; + ssize_t ret; - if (size2 < readsize) - break; + status = cli_pull(cli, fnum, offset, size, size, + cli_read_sink, &buf, &ret); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + return -1; } - - return total; + return ret; } #if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */ -- cgit From 973734cde620585e409d2c125184a2388ab26041 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 8 Mar 2008 22:28:01 +0100 Subject: Correctly calculate the max read size (This used to be commit f556c9e162e2bc0d16710e994a00edc33a146cd5) --- source3/libsmb/clireadwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index c618509f01..9bd8170673 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -24,7 +24,7 @@ ****************************************************************************/ static size_t cli_read_max_bufsize(struct cli_state *cli) { - if (!client_is_signing_on(cli) && !cli_encryption_on(cli) == false + if (!client_is_signing_on(cli) && !cli_encryption_on(cli) && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; } -- cgit From 16cbc22a99c0a302d248dc006ac0016042c1e3ec Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 18 Mar 2008 13:20:10 +0100 Subject: Fix bug 5334 I did not test with a zero length file :-) (This used to be commit 7d7a73944c2dcf078f7bc8de65d575f32f9aa851) --- source3/libsmb/clireadwrite.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 9bd8170673..13c024a264 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -262,6 +262,14 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, state->pushed = 0; state->top_req = 0; + + if (size == 0) { + if (!async_post_status(result, NT_STATUS_OK)) { + goto failed; + } + return result; + } + state->chunk_size = cli_read_max_bufsize(cli); state->num_reqs = MAX(window_size/state->chunk_size, 1); -- cgit From b2ec8372bac987525e3bfa448212ea4f1d8fe5d9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 19 Mar 2008 22:37:24 +0100 Subject: !NT_STATUS_IS_OK != NT_STATUS_IS_ERR When reading from a pipe, Windows return STATUS_BUFFER_OVERFLOW which is *not* an error. (This used to be commit 24018d882d1b1cfece47c533fe5bbca91de124cc) --- source3/libsmb/clireadwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 13c024a264..64a6b7b4eb 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -136,7 +136,7 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, status = cli_pull_error(cli_req->inbuf); - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_IS_ERR(status)) { return status; } -- cgit From 4b3351e5dc07e9350cc2a846b5efe4c7e2d599f6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 21 Mar 2008 13:39:48 +0100 Subject: On Solaris, size_t seems to be only 32 bit. Fix bug 5341, thanks a lot to Karoly Vegh for testing it! Volker (This used to be commit 19eb8c9316b10b1277121e90d0d3ef50ee562118) --- source3/libsmb/clireadwrite.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 64a6b7b4eb..f292fcb2d0 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -175,7 +175,7 @@ struct cli_pull_state { struct cli_state *cli; uint16_t fnum; off_t start_offset; - size_t size; + SMB_OFF_T size; NTSTATUS (*sink)(char *buf, size_t n, void *priv); void *priv; @@ -232,7 +232,7 @@ static void cli_pull_read_done(struct async_req *read_req); struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum, off_t start_offset, - size_t size, size_t window_size, + SMB_OFF_T size, size_t window_size, NTSTATUS (*sink)(char *buf, size_t n, void *priv), void *priv) @@ -284,7 +284,8 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, state->requested = 0; for (i=0; inum_reqs; i++) { - size_t size_left, request_thistime; + SMB_OFF_T size_left; + size_t request_thistime; if (state->requested >= size) { state->num_reqs = i; @@ -376,7 +377,8 @@ static void cli_pull_read_done(struct async_req *read_req) if (state->requested < state->size) { struct async_req *new_req; - size_t size_left, request_thistime; + SMB_OFF_T size_left; + size_t request_thistime; size_left = state->size - state->requested; request_thistime = MIN(size_left, state->chunk_size); @@ -424,7 +426,7 @@ NTSTATUS cli_pull_recv(struct async_req *req, ssize_t *received) } NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, - off_t start_offset, size_t size, size_t window_size, + off_t start_offset, SMB_OFF_T size, size_t window_size, NTSTATUS (*sink)(char *buf, size_t n, void *priv), void *priv, ssize_t *received) { -- cgit From 8f6b03b673ff9d2bc012eef0e2e093b4f02db362 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 28 Mar 2008 15:21:14 +0100 Subject: More ssize_t->SMB_OFF_T (This used to be commit 8dd6458049d1b9d6849730ac19c39b049a68f302) --- source3/libsmb/clireadwrite.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index f292fcb2d0..668a2693d3 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -191,7 +191,7 @@ struct cli_pull_state { /* * For how many bytes did we send requests already? */ - off_t requested; + SMB_OFF_T requested; /* * Next request index to push into "sink". This walks around the "req" @@ -205,7 +205,7 @@ struct cli_pull_state { * How many bytes did we push into "sink"? */ - off_t pushed; + SMB_OFF_T pushed; }; static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req) @@ -412,7 +412,7 @@ static void cli_pull_read_done(struct async_req *read_req) async_req_done(pull_req); } -NTSTATUS cli_pull_recv(struct async_req *req, ssize_t *received) +NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received) { struct cli_pull_state *state = talloc_get_type_abort( req->private_data, struct cli_pull_state); @@ -428,7 +428,7 @@ NTSTATUS cli_pull_recv(struct async_req *req, ssize_t *received) NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, off_t start_offset, SMB_OFF_T size, size_t window_size, NTSTATUS (*sink)(char *buf, size_t n, void *priv), - void *priv, ssize_t *received) + void *priv, SMB_OFF_T *received) { TALLOC_CTX *frame = talloc_stackframe(); struct async_req *req; @@ -466,7 +466,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) { NTSTATUS status; - ssize_t ret; + SMB_OFF_T ret; status = cli_pull(cli, fnum, offset, size, size, cli_read_sink, &buf, &ret); -- cgit From d1e99642f731919bce36dd089b000ef4433b4450 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Mar 2008 10:12:07 -0700 Subject: Fix bug #5326 - OS/2 servers give strange "high word" replies for print jobs. Jeremy. (This used to be commit d090d25cb702965b3d5e4635a26a06f2b62d235d) --- source3/libsmb/clireadwrite.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 668a2693d3..e79fd90614 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -745,7 +745,9 @@ ssize_t cli_write(struct cli_state *cli, break; bwritten += SVAL(cli->inbuf, smb_vwv2); - bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))<<16); + if (writesize > 0xFFFF) { + bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))<<16); + } } while (received < issued && cli_receive_smb(cli)) { -- cgit From b7d2e94296f2201177e2fc08b0c6e12e4a36af50 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Apr 2008 16:54:26 +0200 Subject: Fix bug 5399 Thanks to Jason Mader! Volker (This used to be commit 36740f4959194cfaa98b1e37eed08f22edbda1e4) --- source3/libsmb/clireadwrite.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index e79fd90614..12ba4b737f 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -150,11 +150,6 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, return NT_STATUS_UNEXPECTED_IO_ERROR; } - if (size < 0) { - DEBUG(5,("read return < 0!\n")); - return NT_STATUS_UNEXPECTED_IO_ERROR; - } - *rcvbuf = (uint8_t *) (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6)); *received = size; -- cgit From b04bcefc582a5df669a3dc1952e2af85700b2207 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 May 2008 12:39:08 -0700 Subject: Fix bug #5479, print spool shares require max_xmit to be adhered to. Jeremy. (This used to be commit 478a359edead0677281a3ca4e64db6521941b0f3) --- source3/libsmb/clireadwrite.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 12ba4b737f..515471e003 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -704,7 +704,12 @@ ssize_t cli_write(struct cli_state *cli, /* Only do massive writes if we can do them direct * with no signing or encrypting - not on a pipe. */ writesize = CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE; - } else if (cli->capabilities & CAP_LARGE_WRITEX) { + } else if ((cli->capabilities & CAP_LARGE_WRITEX) && + (strcmp(cli->dev, "LPT1:") != 0)) { + + /* Printer devices are restricted to max_xmit + * writesize in Vista and XPSP3. */ + if (cli->is_samba) { writesize = CLI_SAMBA_MAX_LARGE_WRITEX_SIZE; } else if (!client_is_signing_on(cli)) { -- cgit From d36434f31268b75040311352f23c92c9a61e8cda Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 May 2008 09:31:42 -0700 Subject: Security fix for CVE-2008-1105: Boundary failure when parsing SMB responses can result in a buffer overrun. Jeremy. (This used to be commit 23b825e9d2c74c5b940cf4d3aa56c18692259972) --- source3/libsmb/clireadwrite.c | 100 ------------------------------------------ 1 file changed, 100 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 515471e003..057e647983 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -472,106 +472,6 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, return ret; } -#if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */ - -/* This call is INCOMPATIBLE with SMB signing. If you remove the #if 0 - you must fix ensure you don't attempt to sign the packets - data - *will* be currupted */ - -/**************************************************************************** -Issue a single SMBreadraw and don't wait for a reply. -****************************************************************************/ - -static bool cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, - size_t size, int i) -{ - - if (!cli->sign_info.use_smb_signing) { - DEBUG(0, ("Cannot use readraw and SMB Signing\n")); - return False; - } - - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); - - cli_set_message(cli->outbuf,10,0,True); - - SCVAL(cli->outbuf,smb_com,SMBreadbraw); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); - - SSVAL(cli->outbuf,smb_vwv0,fnum); - SIVAL(cli->outbuf,smb_vwv1,offset); - SSVAL(cli->outbuf,smb_vwv2,size); - SSVAL(cli->outbuf,smb_vwv3,size); - SSVAL(cli->outbuf,smb_mid,cli->mid + i); - - return cli_send_smb(cli); -} - -/**************************************************************************** - Tester for the readraw call. -****************************************************************************/ - -ssize_t cli_readraw(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) -{ - char *p; - int size2; - size_t readsize; - ssize_t total = 0; - - if (size == 0) - return 0; - - /* - * Set readsize to the maximum size we can handle in one readraw. - */ - - readsize = 0xFFFF; - - while (total < size) { - readsize = MIN(readsize, size-total); - - /* Issue a read and receive a reply */ - - if (!cli_issue_readraw(cli, fnum, offset, readsize, 0)) - return -1; - - if (!client_receive_smb(cli->fd, cli->inbuf, cli->timeout)) - return -1; - - size2 = smb_len(cli->inbuf); - - if (size2 > readsize) { - DEBUG(5,("server returned more than we wanted!\n")); - return -1; - } else if (size2 < 0) { - DEBUG(5,("read return < 0!\n")); - return -1; - } - - /* Copy data into buffer */ - - if (size2) { - p = cli->inbuf + 4; - memcpy(buf + total, p, size2); - } - - total += size2; - offset += size2; - - /* - * If the server returned less than we asked for we're at EOF. - */ - - if (size2 < readsize) - break; - } - - return total; -} -#endif - /**************************************************************************** Issue a single SMBwrite and don't wait for a reply. ****************************************************************************/ -- cgit From 711efc06c82349faa979c3653226f4e944f59d18 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 1 Aug 2008 16:05:49 +0200 Subject: cli_request_new() already gave use the req, remove a pointless function call (This used to be commit 08e97bd369ebe3ab1fd92433b168585faea92c68) --- source3/libsmb/clireadwrite.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 057e647983..a57f1e0785 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -62,8 +62,6 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, return NULL; } - req = cli_request_get(result); - req->data.read.ofs = offset; req->data.read.size = size; req->data.read.received = 0; -- cgit From 56cd17dfe145c2df2b39ad295136c4922bee8e43 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 13 Aug 2008 19:57:19 +0200 Subject: Protect against short read&x replies (This used to be commit 4ed73cbbbeff4b554cc8d28252b756241396b3a1) --- source3/libsmb/clireadwrite.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index a57f1e0785..4d3027694f 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -138,6 +138,10 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, return status; } + if (wct < 12) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + /* size is the number of bytes the server returned. * Might be zero. */ size = SVAL(cli_req->inbuf, smb_vwv5); -- cgit From 1924e7931cf83124529edb79620a8494ddcad0e9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 23 Aug 2008 15:40:43 +0200 Subject: Revert "Protect against short read&x replies" This reverts commit 4ed73cbbbeff4b554cc8d28252b756241396b3a1. ... how did this end up here?? Volker (This used to be commit 7dd9fd0956bd1c46105d1072c4774972933ab9ec) --- source3/libsmb/clireadwrite.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 4d3027694f..a57f1e0785 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -138,10 +138,6 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, return status; } - if (wct < 12) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - /* size is the number of bytes the server returned. * Might be zero. */ size = SVAL(cli_req->inbuf, smb_vwv5); -- cgit From 58aa97c0d9db06588d1aba4f06a3c98ed2098d8f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 1 Aug 2008 23:14:51 +0200 Subject: Refactoring: Add the routine cli_request_send() cli_request_send() is supposed to bundle all generic SMB-header handling. This makes cli_request_new static to async_smb.c. (This used to be commit 7e73dd4e7622db64d30d48ba106892e0895fc188) --- source3/libsmb/clireadwrite.c | 71 +++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 46 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index a57f1e0785..2b34fce5bd 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -47,7 +47,9 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, struct async_req *result; struct cli_request *req; bool bigoffset = False; - char *enc_buf; + + uint16_t vwv[12]; + uint8_t wct = 10; if (size > cli_read_max_bufsize(cli)) { DEBUG(0, ("cli_read_andx_send got size=%d, can only handle " @@ -56,60 +58,37 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, return NULL; } - result = cli_request_new(mem_ctx, cli->event_ctx, cli, 12, 0, &req); + SCVAL(vwv + 0, 0, 0xFF); + SCVAL(vwv + 0, 1, 0); + SSVAL(vwv + 1, 0, 0); + SSVAL(vwv + 2, 0, fnum); + SIVAL(vwv + 3, 0, offset); + SSVAL(vwv + 5, 0, size); + SSVAL(vwv + 6, 0, size); + SSVAL(vwv + 7, 0, (size >> 16)); + SSVAL(vwv + 8, 0, 0); + SSVAL(vwv + 9, 0, 0); + + if ((SMB_BIG_UINT)offset >> 32) { + bigoffset = True; + SIVAL(vwv + 10, 0, + (((SMB_BIG_UINT)offset)>>32) & 0xffffffff); + wct += 2; + } + + result = cli_request_send(mem_ctx, cli, SMBreadX, 0, wct, vwv, + 0, NULL); if (result == NULL) { - DEBUG(0, ("cli_request_new failed\n")); return NULL; } + req = cli_request_get(result); + req->data.read.ofs = offset; req->data.read.size = size; req->data.read.received = 0; req->data.read.rcvbuf = NULL; - if ((SMB_BIG_UINT)offset >> 32) - bigoffset = True; - - cli_set_message(req->outbuf, bigoffset ? 12 : 10, 0, False); - - SCVAL(req->outbuf,smb_com,SMBreadX); - SSVAL(req->outbuf,smb_tid,cli->cnum); - cli_setup_packet_buf(cli, req->outbuf); - - SCVAL(req->outbuf,smb_vwv0,0xFF); - SCVAL(req->outbuf,smb_vwv0+1,0); - SSVAL(req->outbuf,smb_vwv1,0); - SSVAL(req->outbuf,smb_vwv2,fnum); - SIVAL(req->outbuf,smb_vwv3,offset); - SSVAL(req->outbuf,smb_vwv5,size); - SSVAL(req->outbuf,smb_vwv6,size); - SSVAL(req->outbuf,smb_vwv7,(size >> 16)); - SSVAL(req->outbuf,smb_vwv8,0); - SSVAL(req->outbuf,smb_vwv9,0); - SSVAL(req->outbuf,smb_mid,req->mid); - - if (bigoffset) { - SIVAL(req->outbuf, smb_vwv10, - (((SMB_BIG_UINT)offset)>>32) & 0xffffffff); - } - - cli_calculate_sign_mac(cli, req->outbuf); - - event_fd_set_writeable(cli->fd_event); - - if (cli_encryption_on(cli)) { - NTSTATUS status; - status = cli_encrypt_message(cli, req->outbuf, &enc_buf); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Error in encrypting client message. " - "Error %s\n", nt_errstr(status))); - TALLOC_FREE(req); - return NULL; - } - req->outbuf = enc_buf; - req->enc_state = cli->trans_enc_state; - } - return result; } -- cgit From 2650207d4adbfd68974fc2b342dd2af079a2552c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Aug 2008 14:17:43 +0200 Subject: Remove cli->event_ctx, pass it explicitly Storing the event_context as permanent state in struct cli_state creates more complex code than necessary IMO. (This used to be commit debb37f703075008e5ea7d34d214cfa4d0f8f916) --- source3/libsmb/clireadwrite.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 2b34fce5bd..d2c8f3c1ba 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -41,6 +41,7 @@ static size_t cli_read_max_bufsize(struct cli_state *cli) */ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, struct cli_state *cli, int fnum, off_t offset, size_t size) { @@ -76,7 +77,7 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, wct += 2; } - result = cli_request_send(mem_ctx, cli, SMBreadX, 0, wct, vwv, + result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv, 0, NULL); if (result == NULL) { return NULL; @@ -144,6 +145,7 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, struct cli_pull_state { struct async_req *req; + struct event_context *ev; struct cli_state *cli; uint16_t fnum; off_t start_offset; @@ -202,7 +204,9 @@ static void cli_pull_read_done(struct async_req *read_req); * Prepare an async pull request */ -struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, +struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint16_t fnum, off_t start_offset, SMB_OFF_T size, size_t window_size, NTSTATUS (*sink)(char *buf, size_t n, @@ -213,7 +217,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, struct cli_pull_state *state; int i; - result = async_req_new(mem_ctx, cli->event_ctx); + result = async_req_new(mem_ctx, ev); if (result == NULL) { goto failed; } @@ -226,6 +230,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, state->req = result; state->cli = cli; + state->ev = ev; state->fnum = fnum; state->start_offset = start_offset; state->size = size; @@ -268,7 +273,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, request_thistime = MIN(size_left, state->chunk_size); state->reqs[i] = cli_read_andx_send( - state->reqs, cli, fnum, + state->reqs, ev, cli, fnum, state->start_offset + state->requested, request_thistime); @@ -363,7 +368,8 @@ static void cli_pull_read_done(struct async_req *read_req) state->top_req)); new_req = cli_read_andx_send( - state->reqs, state->cli, state->fnum, + state->reqs, state->ev, state->cli, + state->fnum, state->start_offset + state->requested, request_thistime); @@ -403,21 +409,30 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, void *priv, SMB_OFF_T *received) { TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; struct async_req *req; NTSTATUS result = NT_STATUS_NO_MEMORY; - if (cli_tmp_event_ctx(frame, cli) == NULL) { + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + return NT_STATUS_INVALID_PARAMETER; + } + + ev = event_context_init(frame); + if (ev == NULL) { goto nomem; } - req = cli_pull_send(frame, cli, fnum, start_offset, size, window_size, - sink, priv); + req = cli_pull_send(frame, ev, cli, fnum, start_offset, size, + window_size, sink, priv); if (req == NULL) { goto nomem; } while (req->state < ASYNC_REQ_DONE) { - event_loop_once(cli->event_ctx); + event_loop_once(ev); } result = cli_pull_recv(req, received); -- cgit From 128524930d490fb5ea637d99bffb36157c80869b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Aug 2008 13:33:41 +0200 Subject: Add cli_pull_reply Along the lines of cli_request_send this abstracts away the smb-level buffer handling when parsing replies we got from the server. (This used to be commit 253134d3aaa359fdfb665709dd5686f69af7f8fd) --- source3/libsmb/clireadwrite.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index d2c8f3c1ba..b64a4c68f3 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -104,6 +104,10 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, uint8_t **rcvbuf) { struct cli_request *cli_req = cli_request_get(req); + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; NTSTATUS status; size_t size; @@ -112,24 +116,27 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, return req->status; } - status = cli_pull_error(cli_req->inbuf); + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); if (NT_STATUS_IS_ERR(status)) { return status; } + if (wct < 12) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + /* size is the number of bytes the server returned. * Might be zero. */ - size = SVAL(cli_req->inbuf, smb_vwv5); - size |= (((unsigned int)(SVAL(cli_req->inbuf, smb_vwv7))) << 16); + size = SVAL(vwv + 5, 0); + size |= (((unsigned int)SVAL(vwv + 7, 0)) << 16); if (size > cli_req->data.read.size) { DEBUG(5,("server returned more than we wanted!\n")); return NT_STATUS_UNEXPECTED_IO_ERROR; } - *rcvbuf = (uint8_t *) - (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6)); + *rcvbuf = (uint8_t *)(smb_base(cli_req->inbuf) + SVAL(vwv + 6, 0)); *received = size; return NT_STATUS_OK; } -- cgit From f294f51bf0d136208fee1be343684ea890a499d0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Aug 2008 15:44:14 +0200 Subject: Remove cli_request_get() req->private_data==NULL at this point is definitely a bug. (This used to be commit ce3dc9f616cafc1289a94ac7cae0beca967d836e) --- source3/libsmb/clireadwrite.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/clireadwrite.c') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index b64a4c68f3..ec63281630 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -83,7 +83,7 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, return NULL; } - req = cli_request_get(result); + req = talloc_get_type_abort(result->private_data, struct cli_request); req->data.read.ofs = offset; req->data.read.size = size; @@ -103,7 +103,8 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, uint8_t **rcvbuf) { - struct cli_request *cli_req = cli_request_get(req); + struct cli_request *cli_req = talloc_get_type_abort( + req->private_data, struct cli_request); uint8_t wct; uint16_t *vwv; uint16_t num_bytes; @@ -311,7 +312,8 @@ static void cli_pull_read_done(struct async_req *read_req) read_req->async.priv, struct async_req); struct cli_pull_state *state = talloc_get_type_abort( pull_req->private_data, struct cli_pull_state); - struct cli_request *read_state = cli_request_get(read_req); + struct cli_request *read_state = talloc_get_type_abort( + read_req->private_data, struct cli_request); NTSTATUS status; status = cli_read_andx_recv(read_req, &read_state->data.read.received, @@ -342,7 +344,9 @@ static void cli_pull_read_done(struct async_req *read_req) return; } - top_read = cli_request_get(state->reqs[state->top_req]); + top_read = talloc_get_type_abort( + state->reqs[state->top_req]->private_data, + struct cli_request); DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " "pushed\n", (int)top_read->data.read.received, -- cgit