Line data Source code
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 : ****************************************************************************/
29 620 : ssize_t smbcli_read(struct smbcli_tree *tree, int fnum, void *_buf, off_t offset,
30 : size_t size)
31 : {
32 620 : uint8_t *buf = (uint8_t *)_buf;
33 : union smb_read parms;
34 : int readsize;
35 620 : ssize_t total = 0;
36 :
37 620 : if (size == 0) {
38 0 : return 0;
39 : }
40 :
41 620 : parms.readx.level = RAW_READ_READX;
42 620 : 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 620 : readsize = (tree->session->transport->negotiate.max_xmit - (MIN_SMB_SIZE+32));
49 620 : if (readsize > 0xFFFF) readsize = 0xFFFF;
50 :
51 1773 : while (total < size) {
52 : NTSTATUS status;
53 :
54 729 : readsize = MIN(readsize, size-total);
55 :
56 729 : parms.readx.in.offset = offset;
57 729 : parms.readx.in.mincnt = readsize;
58 729 : parms.readx.in.maxcnt = readsize;
59 729 : parms.readx.in.remaining = size - total;
60 729 : parms.readx.in.read_for_execute = false;
61 729 : parms.readx.out.data = buf + total;
62 :
63 729 : status = smb_raw_read(tree, &parms);
64 :
65 729 : if (!NT_STATUS_IS_OK(status)) {
66 160 : return -1;
67 : }
68 :
69 569 : total += parms.readx.out.nread;
70 569 : offset += parms.readx.out.nread;
71 :
72 : /* If the server returned less than we asked for we're at EOF */
73 569 : if (parms.readx.out.nread < readsize)
74 18 : break;
75 : }
76 :
77 460 : return total;
78 : }
79 :
80 :
81 : /****************************************************************************
82 : write to a file
83 : write_mode: 0x0001 disallow write caching
84 : 0x0002 return bytes remaining
85 : 0x0004 use raw named pipe protocol
86 : 0x0008 start of message mode named pipe protocol
87 : ****************************************************************************/
88 977 : ssize_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 977 : const uint8_t *buf = (const uint8_t *)_buf;
93 : union smb_write parms;
94 977 : int block = (tree->session->transport->negotiate.max_xmit - (MIN_SMB_SIZE+32));
95 977 : ssize_t total = 0;
96 :
97 977 : if (size == 0) {
98 0 : return 0;
99 : }
100 :
101 977 : if (block > 0xFFFF) block = 0xFFFF;
102 :
103 :
104 977 : parms.writex.level = RAW_WRITE_WRITEX;
105 977 : parms.writex.in.file.fnum = fnum;
106 977 : parms.writex.in.wmode = write_mode;
107 977 : parms.writex.in.remaining = 0;
108 :
109 : do {
110 : NTSTATUS status;
111 :
112 1094 : block = MIN(block, size - total);
113 :
114 1094 : parms.writex.in.offset = offset;
115 1094 : parms.writex.in.count = block;
116 1094 : parms.writex.in.data = buf;
117 :
118 1094 : status = smb_raw_write(tree, &parms);
119 :
120 1094 : if (!NT_STATUS_IS_OK(status)) {
121 196 : return -1;
122 : }
123 :
124 898 : offset += parms.writex.out.nwritten;
125 898 : total += parms.writex.out.nwritten;
126 898 : buf += parms.writex.out.nwritten;
127 898 : } while (total < size);
128 :
129 781 : return total;
130 : }
131 :
132 : /****************************************************************************
133 : write to a file using a SMBwrite and not bypassing 0 byte writes
134 : ****************************************************************************/
135 1 : ssize_t smbcli_smbwrite(struct smbcli_tree *tree,
136 : int fnum, const void *_buf, off_t offset, size_t size1)
137 : {
138 1 : const uint8_t *buf = (const uint8_t *)_buf;
139 : union smb_write parms;
140 1 : ssize_t total = 0;
141 :
142 1 : parms.write.level = RAW_WRITE_WRITE;
143 1 : parms.write.in.remaining = 0;
144 :
145 : do {
146 1 : size_t size = MIN(size1, tree->session->transport->negotiate.max_xmit - 48);
147 1 : if (size > 0xFFFF) size = 0xFFFF;
148 :
149 1 : parms.write.in.file.fnum = fnum;
150 1 : parms.write.in.offset = offset;
151 1 : parms.write.in.count = size;
152 1 : parms.write.in.data = buf + total;
153 :
154 1 : if (NT_STATUS_IS_ERR(smb_raw_write(tree, &parms)))
155 0 : return -1;
156 :
157 1 : size = parms.write.out.nwritten;
158 1 : if (size == 0)
159 0 : break;
160 :
161 1 : size1 -= size;
162 1 : total += size;
163 1 : offset += size;
164 1 : } while (size1);
165 :
166 1 : return total;
167 : }
|