1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21da6c28aaSamw /*
22cb174861Sjoyce mcintosh * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*68b2bbf2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw */
25da6c28aaSamw
26bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
27da6c28aaSamw #include <smbsrv/smb_fsops.h>
28da6c28aaSamw
29cb174861Sjoyce mcintosh /*
302c2961f8Sjose borrego * The maximum number of bytes to return from SMB Core
312c2961f8Sjose borrego * SmbRead or SmbLockAndRead.
322c2961f8Sjose borrego */
332c2961f8Sjose borrego #define SMB_CORE_READ_MAX 4432
34da6c28aaSamw
352c2961f8Sjose borrego /*
362c2961f8Sjose borrego * The limit in bytes for SmbReadX.
372c2961f8Sjose borrego */
382c2961f8Sjose borrego #define SMB_READX_MAX 0x10000
392c2961f8Sjose borrego
402c2961f8Sjose borrego int smb_common_read(smb_request_t *, smb_rw_param_t *);
41da6c28aaSamw
42da6c28aaSamw /*
43da6c28aaSamw * Read bytes from a file or named pipe (SMB Core).
44da6c28aaSamw *
45da6c28aaSamw * The requested count specifies the number of bytes desired. Offset
46da6c28aaSamw * is limited to 32 bits, so this client request is inappropriate for
47da6c28aaSamw * files with 64 bit offsets.
48da6c28aaSamw *
49da6c28aaSamw * On return, count is the number of bytes actually being returned, which
50da6c28aaSamw * may be less than the count requested only if a read specifies bytes
51da6c28aaSamw * beyond the current file size. In this case only the bytes that exist
52da6c28aaSamw * are returned. A read completely beyond the end of file results in a
53da6c28aaSamw * response of length zero. This is the only circumstance when a zero
54da6c28aaSamw * length response is generated. A count returned which is less than the
55da6c28aaSamw * count requested is the end of file indicator.
56da6c28aaSamw */
577b59d02dSjb150015 smb_sdrc_t
smb_pre_read(smb_request_t * sr)58faa1795aSjb150015 smb_pre_read(smb_request_t *sr)
59da6c28aaSamw {
60faa1795aSjb150015 smb_rw_param_t *param;
61da6c28aaSamw uint32_t off_low;
622c2961f8Sjose borrego uint16_t count;
63da6c28aaSamw uint16_t remcnt;
64da6c28aaSamw int rc;
65da6c28aaSamw
66faa1795aSjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
67faa1795aSjb150015 sr->arg.rw = param;
68da6c28aaSamw
69faa1795aSjb150015 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
702c2961f8Sjose borrego &count, &off_low, &remcnt);
71faa1795aSjb150015
72faa1795aSjb150015 param->rw_offset = (uint64_t)off_low;
732c2961f8Sjose borrego param->rw_count = (uint32_t)count;
74faa1795aSjb150015 param->rw_mincnt = 0;
75faa1795aSjb150015
76faa1795aSjb150015 DTRACE_SMB_2(op__Read__start, smb_request_t *, sr,
77faa1795aSjb150015 smb_rw_param_t *, param);
78faa1795aSjb150015
79faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
80faa1795aSjb150015 }
81faa1795aSjb150015
82faa1795aSjb150015 void
smb_post_read(smb_request_t * sr)83faa1795aSjb150015 smb_post_read(smb_request_t *sr)
84faa1795aSjb150015 {
85faa1795aSjb150015 DTRACE_SMB_2(op__Read__done, smb_request_t *, sr,
86faa1795aSjb150015 smb_rw_param_t *, sr->arg.rw);
87faa1795aSjb150015
88faa1795aSjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
89faa1795aSjb150015 }
90faa1795aSjb150015
91faa1795aSjb150015 smb_sdrc_t
smb_com_read(smb_request_t * sr)92faa1795aSjb150015 smb_com_read(smb_request_t *sr)
93faa1795aSjb150015 {
94faa1795aSjb150015 smb_rw_param_t *param = sr->arg.rw;
952c2961f8Sjose borrego uint16_t count;
96faa1795aSjb150015 int rc;
97da6c28aaSamw
982c2961f8Sjose borrego smbsr_lookup_file(sr);
99da6c28aaSamw if (sr->fid_ofile == NULL) {
100dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
101faa1795aSjb150015 return (SDRC_ERROR);
102da6c28aaSamw }
103da6c28aaSamw
104b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
105b89a8333Snatalie li - Sun Microsystems - Irvine United States
1062c2961f8Sjose borrego if (param->rw_count > SMB_CORE_READ_MAX)
1072c2961f8Sjose borrego param->rw_count = SMB_CORE_READ_MAX;
1082c2961f8Sjose borrego
109faa1795aSjb150015 if ((rc = smb_common_read(sr, param)) != 0) {
110dc20a302Sas200622 smbsr_errno(sr, rc);
111faa1795aSjb150015 return (SDRC_ERROR);
112da6c28aaSamw }
113da6c28aaSamw
1142c2961f8Sjose borrego count = (uint16_t)param->rw_count;
1157b59d02dSjb150015 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
1162c2961f8Sjose borrego 5, count, VAR_BCC, 0x01, count, &sr->raw_data);
117da6c28aaSamw
118faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
119da6c28aaSamw }
120da6c28aaSamw
121da6c28aaSamw /*
122da6c28aaSamw * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/
123da6c28aaSamw * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
124da6c28aaSamw * attempt to use it on non-disk shares.
125da6c28aaSamw *
126da6c28aaSamw * The requested count specifies the number of bytes desired. Offset
127da6c28aaSamw * specifies the offset in the file of the first byte to be locked then
128da6c28aaSamw * read. Note that offset is limited to 32 bits, so this client request
129da6c28aaSamw * is inappropriate for files with 64 bit offsets.
130da6c28aaSamw *
131da6c28aaSamw * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
132da6c28aaSamw * immediately an error should be returned to the client. If an error
133da6c28aaSamw * occurs on the lock, the bytes should not be read.
134da6c28aaSamw *
135da6c28aaSamw * On return, count is the number of bytes actually being returned, which
136da6c28aaSamw * may be less than the count requested only if a read specifies bytes
137da6c28aaSamw * beyond the current file size. In this case only the bytes that exist
138da6c28aaSamw * are returned. A read completely beyond the end of file results in a
139da6c28aaSamw * response of length zero. This is the only circumstance when a zero
140da6c28aaSamw * length response is generated. A count returned which is less than the
141da6c28aaSamw * count requested is the end of file indicator.
142da6c28aaSamw */
1437b59d02dSjb150015 smb_sdrc_t
smb_pre_lock_and_read(smb_request_t * sr)144faa1795aSjb150015 smb_pre_lock_and_read(smb_request_t *sr)
145da6c28aaSamw {
146faa1795aSjb150015 smb_rw_param_t *param;
147da6c28aaSamw uint32_t off_low;
1482c2961f8Sjose borrego uint16_t count;
1492c2961f8Sjose borrego uint16_t remcnt;
150faa1795aSjb150015 int rc;
151faa1795aSjb150015
152faa1795aSjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
153faa1795aSjb150015 sr->arg.rw = param;
154faa1795aSjb150015
155faa1795aSjb150015 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
1562c2961f8Sjose borrego &count, &off_low, &remcnt);
157faa1795aSjb150015
158faa1795aSjb150015 param->rw_offset = (uint64_t)off_low;
1592c2961f8Sjose borrego param->rw_count = (uint32_t)count;
160faa1795aSjb150015 param->rw_mincnt = 0;
161faa1795aSjb150015
162faa1795aSjb150015 DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr,
163faa1795aSjb150015 smb_rw_param_t *, param);
164faa1795aSjb150015
165faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
166faa1795aSjb150015 }
167faa1795aSjb150015
168faa1795aSjb150015 void
smb_post_lock_and_read(smb_request_t * sr)169faa1795aSjb150015 smb_post_lock_and_read(smb_request_t *sr)
170faa1795aSjb150015 {
171faa1795aSjb150015 DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr,
172faa1795aSjb150015 smb_rw_param_t *, sr->arg.rw);
173faa1795aSjb150015
174faa1795aSjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
175faa1795aSjb150015 }
176faa1795aSjb150015
177faa1795aSjb150015 smb_sdrc_t
smb_com_lock_and_read(smb_request_t * sr)178faa1795aSjb150015 smb_com_lock_and_read(smb_request_t *sr)
179faa1795aSjb150015 {
180faa1795aSjb150015 smb_rw_param_t *param = sr->arg.rw;
181faa1795aSjb150015 DWORD status;
1822c2961f8Sjose borrego uint16_t count;
183da6c28aaSamw int rc;
184da6c28aaSamw
185da6c28aaSamw if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
186dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
187faa1795aSjb150015 return (SDRC_ERROR);
188da6c28aaSamw }
189da6c28aaSamw
1902c2961f8Sjose borrego smbsr_lookup_file(sr);
191da6c28aaSamw if (sr->fid_ofile == NULL) {
192dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
193faa1795aSjb150015 return (SDRC_ERROR);
194da6c28aaSamw }
195da6c28aaSamw
196b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
197b89a8333Snatalie li - Sun Microsystems - Irvine United States
1986537f381Sas200622 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
1992c2961f8Sjose borrego 0, SMB_LOCK_TYPE_READWRITE);
2002c2961f8Sjose borrego
201faa1795aSjb150015 if (status != NT_STATUS_SUCCESS) {
202faa1795aSjb150015 smb_lock_range_error(sr, status);
203faa1795aSjb150015 return (SDRC_ERROR);
204da6c28aaSamw }
205da6c28aaSamw
2062c2961f8Sjose borrego if (param->rw_count > SMB_CORE_READ_MAX)
2072c2961f8Sjose borrego param->rw_count = SMB_CORE_READ_MAX;
2082c2961f8Sjose borrego
209faa1795aSjb150015 if ((rc = smb_common_read(sr, param)) != 0) {
210dc20a302Sas200622 smbsr_errno(sr, rc);
211faa1795aSjb150015 return (SDRC_ERROR);
212da6c28aaSamw }
213da6c28aaSamw
2142c2961f8Sjose borrego count = (uint16_t)param->rw_count;
2157b59d02dSjb150015 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
2162c2961f8Sjose borrego 5, count, VAR_BCC, 0x1, count, &sr->raw_data);
217da6c28aaSamw
218faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
219da6c28aaSamw }
220da6c28aaSamw
221da6c28aaSamw /*
222da6c28aaSamw * Read bytes from a file (SMB Core). This request was extended in
223da6c28aaSamw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
224da6c28aaSamw * 12 and including additional offset information.
2252c2961f8Sjose borrego *
2262c2961f8Sjose borrego * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
2272c2961f8Sjose borrego * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
2282c2961f8Sjose borrego * than the negotiated buffer size. If maxcnt_high is 0xFF, it must
2292c2961f8Sjose borrego * be ignored. Otherwise, maxcnt_high represents the upper 16 bits
2302c2961f8Sjose borrego * of rw_count.
231da6c28aaSamw */
2327b59d02dSjb150015 smb_sdrc_t
smb_pre_read_andx(smb_request_t * sr)233faa1795aSjb150015 smb_pre_read_andx(smb_request_t *sr)
234da6c28aaSamw {
235faa1795aSjb150015 smb_rw_param_t *param;
236da6c28aaSamw uint32_t off_low;
237da6c28aaSamw uint32_t off_high;
2382c2961f8Sjose borrego uint32_t maxcnt_high;
2392c2961f8Sjose borrego uint16_t maxcnt_low;
2402c2961f8Sjose borrego uint16_t mincnt;
241da6c28aaSamw uint16_t remcnt;
242da6c28aaSamw int rc;
243da6c28aaSamw
244faa1795aSjb150015 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
245faa1795aSjb150015 sr->arg.rw = param;
246faa1795aSjb150015
247da6c28aaSamw if (sr->smb_wct == 12) {
2482c2961f8Sjose borrego rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx,
2492c2961f8Sjose borrego &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
2502c2961f8Sjose borrego &remcnt, &off_high);
251da6c28aaSamw
2522c2961f8Sjose borrego param->rw_offset = ((uint64_t)off_high << 32) |
2532c2961f8Sjose borrego (uint64_t)off_low;
2542c2961f8Sjose borrego
2552c2961f8Sjose borrego param->rw_count = (uint32_t)maxcnt_low;
2563a6c5f83SAlan Wright
2573a6c5f83SAlan Wright if ((sr->session->capabilities & CAP_LARGE_READX) &&
2583a6c5f83SAlan Wright (maxcnt_high < 0xFF))
2592c2961f8Sjose borrego param->rw_count |= maxcnt_high << 16;
260da6c28aaSamw } else {
2612c2961f8Sjose borrego rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx,
2622c2961f8Sjose borrego &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
2632c2961f8Sjose borrego &remcnt);
264da6c28aaSamw
265faa1795aSjb150015 param->rw_offset = (uint64_t)off_low;
2662c2961f8Sjose borrego param->rw_count = (uint32_t)maxcnt_low;
267da6c28aaSamw }
268da6c28aaSamw
269faa1795aSjb150015 param->rw_mincnt = 0;
270da6c28aaSamw
271faa1795aSjb150015 DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr,
272faa1795aSjb150015 smb_rw_param_t *, param);
273faa1795aSjb150015
274faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
275faa1795aSjb150015 }
276faa1795aSjb150015
277faa1795aSjb150015 void
smb_post_read_andx(smb_request_t * sr)278faa1795aSjb150015 smb_post_read_andx(smb_request_t *sr)
279faa1795aSjb150015 {
280faa1795aSjb150015 DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr,
281faa1795aSjb150015 smb_rw_param_t *, sr->arg.rw);
282faa1795aSjb150015
283faa1795aSjb150015 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
284faa1795aSjb150015 }
285faa1795aSjb150015
286faa1795aSjb150015 smb_sdrc_t
smb_com_read_andx(smb_request_t * sr)287faa1795aSjb150015 smb_com_read_andx(smb_request_t *sr)
288faa1795aSjb150015 {
289faa1795aSjb150015 smb_rw_param_t *param = sr->arg.rw;
2902c2961f8Sjose borrego uint16_t datalen_high;
2912c2961f8Sjose borrego uint16_t datalen_low;
2922c2961f8Sjose borrego uint16_t data_offset;
293faa1795aSjb150015 uint16_t offset2;
294faa1795aSjb150015 int rc;
295da6c28aaSamw
2962c2961f8Sjose borrego smbsr_lookup_file(sr);
297da6c28aaSamw if (sr->fid_ofile == NULL) {
298dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
299faa1795aSjb150015 return (SDRC_ERROR);
300da6c28aaSamw }
301da6c28aaSamw
302b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
303b89a8333Snatalie li - Sun Microsystems - Irvine United States
3042c2961f8Sjose borrego if (param->rw_count >= SMB_READX_MAX)
3052c2961f8Sjose borrego param->rw_count = 0;
3062c2961f8Sjose borrego
307faa1795aSjb150015 if ((rc = smb_common_read(sr, param)) != 0) {
308dc20a302Sas200622 smbsr_errno(sr, rc);
309faa1795aSjb150015 return (SDRC_ERROR);
310da6c28aaSamw }
311da6c28aaSamw
3122c2961f8Sjose borrego datalen_low = param->rw_count & 0xFFFF;
3132c2961f8Sjose borrego datalen_high = (param->rw_count >> 16) & 0xFF;
314da6c28aaSamw
315da6c28aaSamw /*
3162c2961f8Sjose borrego * If this is a secondary command, the data offset
3172c2961f8Sjose borrego * includes the previous wct + sizeof(wct).
318da6c28aaSamw */
3192c2961f8Sjose borrego data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1;
3202c2961f8Sjose borrego
321da6c28aaSamw if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
3222c2961f8Sjose borrego data_offset += 60;
3232c2961f8Sjose borrego offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60;
3242c2961f8Sjose borrego
3252c2961f8Sjose borrego rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC",
326da6c28aaSamw 12, /* wct */
3272c2961f8Sjose borrego param->rw_andx, /* secondary andx command */
3282c2961f8Sjose borrego offset2, /* offset to next command */
3292c2961f8Sjose borrego 0, /* set to 0 for named pipes */
3302c2961f8Sjose borrego datalen_low, /* data byte count */
3312c2961f8Sjose borrego data_offset, /* offset from start to data */
3322c2961f8Sjose borrego datalen_high, /* data byte count */
333da6c28aaSamw VAR_BCC, /* BCC marker */
3342c2961f8Sjose borrego 0x00, /* padding */
335da6c28aaSamw &sr->raw_data);
336da6c28aaSamw } else {
3372c2961f8Sjose borrego data_offset += 59;
3382c2961f8Sjose borrego offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59;
3392c2961f8Sjose borrego
3402c2961f8Sjose borrego rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC",
341da6c28aaSamw 12, /* wct */
3422c2961f8Sjose borrego param->rw_andx, /* secondary andx command */
3432c2961f8Sjose borrego offset2, /* offset to next command */
3442c2961f8Sjose borrego -1, /* must be -1 for regular files */
3452c2961f8Sjose borrego datalen_low, /* data byte count */
3462c2961f8Sjose borrego data_offset, /* offset from start to data */
3472c2961f8Sjose borrego datalen_high, /* data byte count */
348da6c28aaSamw VAR_BCC, /* BCC marker */
349da6c28aaSamw &sr->raw_data);
350da6c28aaSamw }
351da6c28aaSamw
352faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
353da6c28aaSamw }
354da6c28aaSamw
355da6c28aaSamw /*
356da6c28aaSamw * Common function for reading files or IPC/MSRPC named pipes. All
357da6c28aaSamw * protocol read functions should lookup the fid before calling this
358da6c28aaSamw * function. We can't move the fid lookup here because lock-and-read
359da6c28aaSamw * requires the fid to do locking before attempting the read.
360da6c28aaSamw *
361cb174861Sjoyce mcintosh * Reading from a file should break oplocks on the file to LEVEL_II.
362cb174861Sjoyce mcintosh * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not
363cb174861Sjoyce mcintosh * required as it is a no-op. If there's anything greater than a
364cb174861Sjoyce mcintosh * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile
365cb174861Sjoyce mcintosh * on which the read is occuring and therefore would not be broken.
366cb174861Sjoyce mcintosh *
367da6c28aaSamw * Returns errno values.
368da6c28aaSamw */
369da6c28aaSamw int
smb_common_read(smb_request_t * sr,smb_rw_param_t * param)370faa1795aSjb150015 smb_common_read(smb_request_t *sr, smb_rw_param_t *param)
371da6c28aaSamw {
372da6c28aaSamw smb_ofile_t *ofile = sr->fid_ofile;
373da6c28aaSamw smb_node_t *node;
374faa1795aSjb150015 smb_vdb_t *vdb = ¶m->rw_vdb;
375da6c28aaSamw struct mbuf *top;
376da6c28aaSamw int rc;
377da6c28aaSamw
3782c2961f8Sjose borrego vdb->vdb_tag = 0;
3792c2961f8Sjose borrego vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
3802c2961f8Sjose borrego vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
3812c2961f8Sjose borrego vdb->vdb_uio.uio_resid = param->rw_count;
3822c2961f8Sjose borrego vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
3832c2961f8Sjose borrego vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
384f96bd5c8SAlan Wright vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
385da6c28aaSamw
386da6c28aaSamw switch (sr->tid_tree->t_res_type & STYPE_MASK) {
387da6c28aaSamw case STYPE_DISKTREE:
388da6c28aaSamw node = ofile->f_node;
389da6c28aaSamw
390037cac00Sjoyce mcintosh if (!smb_node_is_dir(node)) {
391faa1795aSjb150015 rc = smb_lock_range_access(sr, node, param->rw_offset,
392faa1795aSjb150015 param->rw_count, B_FALSE);
393da6c28aaSamw if (rc != NT_STATUS_SUCCESS) {
394da6c28aaSamw rc = ERANGE;
395da6c28aaSamw break;
396da6c28aaSamw }
397da6c28aaSamw }
398da6c28aaSamw
3992c2961f8Sjose borrego if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
4009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
4012c2961f8Sjose borrego /*
4029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
4039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * reads.
4042c2961f8Sjose borrego *
4052c2961f8Sjose borrego * Reject request if the file has been opened
4069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
4079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * set.
4082c2961f8Sjose borrego */
4092c2961f8Sjose borrego rc = EACCES;
4102c2961f8Sjose borrego break;
4112c2961f8Sjose borrego }
4122c2961f8Sjose borrego
4132c2961f8Sjose borrego sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
4142c2961f8Sjose borrego top = smb_mbuf_allocate(&vdb->vdb_uio);
415da6c28aaSamw
416037cac00Sjoyce mcintosh rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio);
417da6c28aaSamw
4182c2961f8Sjose borrego sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
419da6c28aaSamw smb_mbuf_trim(top, sr->raw_data.max_bytes);
420da6c28aaSamw MBC_ATTACH_MBUF(&sr->raw_data, top);
421da6c28aaSamw break;
422da6c28aaSamw
423da6c28aaSamw case STYPE_IPC:
424*68b2bbf2SGordon Ross sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
425*68b2bbf2SGordon Ross top = smb_mbuf_allocate(&vdb->vdb_uio);
426*68b2bbf2SGordon Ross
4272c2961f8Sjose borrego rc = smb_opipe_read(sr, &vdb->vdb_uio);
428*68b2bbf2SGordon Ross
429*68b2bbf2SGordon Ross sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
430*68b2bbf2SGordon Ross smb_mbuf_trim(top, sr->raw_data.max_bytes);
431*68b2bbf2SGordon Ross MBC_ATTACH_MBUF(&sr->raw_data, top);
432da6c28aaSamw break;
433da6c28aaSamw
434da6c28aaSamw default:
435da6c28aaSamw rc = EACCES;
436da6c28aaSamw break;
437da6c28aaSamw }
438da6c28aaSamw
4392c2961f8Sjose borrego param->rw_count -= vdb->vdb_uio.uio_resid;
440da6c28aaSamw
441da6c28aaSamw if (rc != 0)
442da6c28aaSamw return (rc);
443da6c28aaSamw
444faa1795aSjb150015 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) {
445da6c28aaSamw /*
446da6c28aaSamw * mincnt is only used by read-raw and is typically
447da6c28aaSamw * zero. If mincnt is greater than zero and the
448da6c28aaSamw * number of bytes read is less than mincnt, tell
449da6c28aaSamw * the client that we read nothing.
450da6c28aaSamw */
451faa1795aSjb150015 param->rw_count = 0;
452da6c28aaSamw }
453da6c28aaSamw
454faa1795aSjb150015 param->rw_offset += param->rw_count;
455da6c28aaSamw mutex_enter(&sr->fid_ofile->f_mutex);
456faa1795aSjb150015 ofile->f_seek_pos = param->rw_offset;
457da6c28aaSamw mutex_exit(&sr->fid_ofile->f_mutex);
458da6c28aaSamw return (rc);
459da6c28aaSamw }
460