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 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 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 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 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 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 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 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 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 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 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