diff options
author | Jeremy Allison <jra@samba.org> | 2007-05-16 00:07:38 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:22:08 -0500 |
commit | 32106b23951e01fb17f814584ebbcc8d7288cb75 (patch) | |
tree | e14389fd1be0e7dae592d74f8c8518dd9a1b60a0 /source3/libsmb/clireadwrite.c | |
parent | 074af4b39d12312fc376e8d2f7bf84f0fd830874 (diff) | |
download | samba-32106b23951e01fb17f814584ebbcc8d7288cb75.tar.gz samba-32106b23951e01fb17f814584ebbcc8d7288cb75.tar.bz2 samba-32106b23951e01fb17f814584ebbcc8d7288cb75.zip |
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)
Diffstat (limited to 'source3/libsmb/clireadwrite.c')
-rw-r--r-- | source3/libsmb/clireadwrite.c | 50 |
1 files changed, 40 insertions, 10 deletions
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; |