mirror of
https://github.com/samba-team/samba.git
synced 2025-02-26 21:57:41 +03:00
Convert cli_read to use cli_pull
(This used to be commit d69b20111a849152a7d9108763207c813bf9068b)
This commit is contained in:
parent
6244578835
commit
a015227490
@ -444,175 +444,27 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
static NTSTATUS cli_read_sink(char *buf, size_t n, void *priv)
|
||||||
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;
|
char **pbuf = (char **)priv;
|
||||||
|
memcpy(*pbuf, buf, n);
|
||||||
memset(cli->outbuf,'\0',smb_size);
|
*pbuf += n;
|
||||||
memset(cli->inbuf,'\0',smb_size);
|
return NT_STATUS_OK;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
ssize_t cli_read(struct cli_state *cli, int fnum, char *buf,
|
||||||
Read size bytes at offset offset using SMBreadX.
|
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;
|
NTSTATUS status;
|
||||||
size_t size2;
|
ssize_t ret;
|
||||||
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)
|
status = cli_pull(cli, fnum, offset, size, size,
|
||||||
return 0;
|
cli_read_sink, &buf, &ret);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
/*
|
cli_set_error(cli, status);
|
||||||
* Set readsize to the maximum size we can handle in one readX,
|
return -1;
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (size2 < readsize)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */
|
#if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user