summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libsmb/clireadwrite.c6
-rw-r--r--source3/smbd/reply.c7
-rw-r--r--source3/utils/torture.c51
3 files changed, 61 insertions, 3 deletions
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));
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 7cb23d8629..d3f2527b35 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2674,6 +2674,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
unsigned int smblen = smb_len(inbuf);
char *data;
+ BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
START_PROFILE(SMBwriteX);
/* If it's an IPC, pass off the pipe handler. */
@@ -2687,7 +2688,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
CHECK_ERROR(fsp);
/* Deal with possible LARGE_WRITEX */
- if (smblen > 0xFFFF)
+ if (large_writeX)
numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
@@ -2742,7 +2743,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
set_message(outbuf,6,0,True);
SSVAL(outbuf,smb_vwv2,nwritten);
-
+ if (large_writeX)
+ SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
+
if (nwritten < (ssize_t)numtowrite) {
CVAL(outbuf,smb_rcls) = ERRHRD;
SSVAL(outbuf,smb_err,ERRdiskfull);
diff --git a/source3/utils/torture.c b/source3/utils/torture.c
index 7298cd9b9a..982be77151 100644
--- a/source3/utils/torture.c
+++ b/source3/utils/torture.c
@@ -483,6 +483,54 @@ static void run_readwritemulti(int dummy)
close_connection(&cli);
}
+static void run_readwritelarge(int dummy)
+{
+ static struct cli_state cli1;
+ int fnum1;
+ char *lockfname = "\\large.dat";
+ size_t fsize;
+ char buf[0x10000];
+
+ if (!open_connection(&cli1)) {
+ return;
+ }
+ cli_sockopt(&cli1, sockops);
+ memset(buf,'\0',sizeof(buf));
+
+ cli1.max_xmit = 0x11000;
+
+ printf("starting readwritelarge\n");
+
+ cli_unlink(&cli1, lockfname);
+
+ fnum1 = cli_open(&cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE);
+ if (fnum1 == -1) {
+ printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(&cli1));
+ return;
+ }
+
+ cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf));
+
+ if (!cli_close(&cli1, fnum1)) {
+ printf("close failed (%s)\n", cli_errstr(&cli1));
+ }
+
+ if (!cli_qpathinfo(&cli1, lockfname, NULL, NULL, NULL, &fsize, NULL)) {
+ printf("qpathinfo failed (%s)\n", cli_errstr(&cli1));
+ }
+
+ if (fsize == sizeof(buf))
+ printf("readwritelarge test succeeded (size = %x)\n", fsize);
+ else
+ printf("readwritelarge test failed (size = %x)\n", fsize);
+
+ if (!cli_unlink(&cli1, lockfname)) {
+ printf("unlink failed (%s)\n", cli_errstr(&cli1));
+ }
+
+ close_connection(&cli1);
+}
+
int line_count = 0;
/* run a test that simulates an approximate netbench client load */
@@ -2722,6 +2770,7 @@ static struct {
{"TCON", run_tcon_test, 0},
{"RW1", run_readwritetest, 0},
{"RW2", run_readwritemulti, FLAG_MULTIPROC},
+ {"RW3", run_readwritelarge, 0},
{"OPEN", run_opentest, 0},
{"DELETE", run_deletetest, 0},
{NULL, NULL, 0}};
@@ -2811,6 +2860,8 @@ static void usage(void)
codepage_initialise(lp_client_code_page());
+ codepage_initialise(lp_client_code_page());
+
lp_load(servicesf,True,False,False);
load_interfaces();