diff options
-rw-r--r-- | source3/libsmb/clireadwrite.c | 6 | ||||
-rw-r--r-- | source3/smbd/reply.c | 7 | ||||
-rw-r--r-- | source3/utils/torture.c | 51 |
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(); |