• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/libcli/
1/*
2   Unix SMB/CIFS implementation.
3   client file read/write routines
4   Copyright (C) Andrew Tridgell 1994-1998
5   Copyright (C) James Myers 2003
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22#include "libcli/raw/libcliraw.h"
23#include "libcli/raw/raw_proto.h"
24#include "libcli/libcli.h"
25
26/****************************************************************************
27  Read size bytes at offset offset using SMBreadX.
28****************************************************************************/
29ssize_t smbcli_read(struct smbcli_tree *tree, int fnum, void *_buf, off_t offset,
30		 size_t size)
31{
32	uint8_t *buf = (uint8_t *)_buf;
33	union smb_read parms;
34	int readsize;
35	ssize_t total = 0;
36
37	if (size == 0) {
38		return 0;
39	}
40
41	parms.readx.level = RAW_READ_READX;
42	parms.readx.in.file.fnum = fnum;
43
44	/*
45	 * Set readsize to the maximum size we can handle in one readX,
46	 * rounded down to a multiple of 1024.
47	 */
48	readsize = (tree->session->transport->negotiate.max_xmit - (MIN_SMB_SIZE+32));
49	if (readsize > 0xFFFF) readsize = 0xFFFF;
50
51	while (total < size) {
52		NTSTATUS status;
53
54		readsize = MIN(readsize, size-total);
55
56		parms.readx.in.offset    = offset;
57		parms.readx.in.mincnt    = readsize;
58		parms.readx.in.maxcnt    = readsize;
59		parms.readx.in.remaining = size - total;
60		parms.readx.in.read_for_execute = false;
61		parms.readx.out.data     = buf + total;
62
63		status = smb_raw_read(tree, &parms);
64
65		if (!NT_STATUS_IS_OK(status)) {
66			return -1;
67		}
68
69		total += parms.readx.out.nread;
70		offset += parms.readx.out.nread;
71
72		/* If the server returned less than we asked for we're at EOF */
73		if (parms.readx.out.nread < readsize)
74			break;
75	}
76
77	return total;
78}
79
80
81/****************************************************************************
82  write to a file
83  write_mode: 0x0001 disallow write cacheing
84              0x0002 return bytes remaining
85              0x0004 use raw named pipe protocol
86              0x0008 start of message mode named pipe protocol
87****************************************************************************/
88ssize_t smbcli_write(struct smbcli_tree *tree,
89		     int fnum, uint16_t write_mode,
90		     const void *_buf, off_t offset, size_t size)
91{
92	const uint8_t *buf = (const uint8_t *)_buf;
93	union smb_write parms;
94	int block = (tree->session->transport->negotiate.max_xmit - (MIN_SMB_SIZE+32));
95	ssize_t total = 0;
96
97	if (size == 0) {
98		return 0;
99	}
100
101	if (block > 0xFFFF) block = 0xFFFF;
102
103
104	parms.writex.level = RAW_WRITE_WRITEX;
105	parms.writex.in.file.fnum = fnum;
106	parms.writex.in.wmode = write_mode;
107	parms.writex.in.remaining = 0;
108
109	while (total < size) {
110		NTSTATUS status;
111
112		block = MIN(block, size - total);
113
114		parms.writex.in.offset = offset;
115		parms.writex.in.count = block;
116		parms.writex.in.data = buf;
117
118		status = smb_raw_write(tree, &parms);
119
120		if (!NT_STATUS_IS_OK(status)) {
121			return -1;
122		}
123
124		offset += parms.writex.out.nwritten;
125		total += parms.writex.out.nwritten;
126		buf += parms.writex.out.nwritten;
127	}
128
129	return total;
130}
131
132/****************************************************************************
133  write to a file using a SMBwrite and not bypassing 0 byte writes
134****************************************************************************/
135ssize_t smbcli_smbwrite(struct smbcli_tree *tree,
136		     int fnum, const void *_buf, off_t offset, size_t size1)
137{
138	const uint8_t *buf = (const uint8_t *)_buf;
139	union smb_write parms;
140	ssize_t total = 0;
141
142	parms.write.level = RAW_WRITE_WRITE;
143	parms.write.in.remaining = 0;
144
145	do {
146		size_t size = MIN(size1, tree->session->transport->negotiate.max_xmit - 48);
147		if (size > 0xFFFF) size = 0xFFFF;
148
149		parms.write.in.file.fnum = fnum;
150		parms.write.in.offset = offset;
151		parms.write.in.count = size;
152		parms.write.in.data = buf + total;
153
154		if (NT_STATUS_IS_ERR(smb_raw_write(tree, &parms)))
155			return -1;
156
157		size = parms.write.out.nwritten;
158		if (size == 0)
159			break;
160
161		size1 -= size;
162		total += size;
163		offset += size;
164	} while (size1);
165
166	return total;
167}
168