smb_read.c revision 68b2bbf26c7040fea4281dcb58b81e7627e46f34
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * CDDL HEADER START
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * The contents of this file are subject to the terms of the
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Common Development and Distribution License (the "License").
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * You may not use this file except in compliance with the License.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * or http://www.opensolaris.org/os/licensing.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * See the License for the specific language governing permissions
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * and limitations under the License.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * When distributing Covered Code, include this CDDL HEADER in each
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * If applicable, add the following below this CDDL HEADER, with the
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * fields enclosed by brackets "[]" replaced with your own identifying
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * information: Portions Copyright [yyyy] [name of copyright owner]
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * CDDL HEADER END
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync#include <smbsrv/smb_kproto.h>
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync#include <smbsrv/smb_fsops.h>
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * The maximum number of bytes to return from SMB Core
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * SmbRead or SmbLockAndRead.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync#define SMB_CORE_READ_MAX 4432
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * The limit in bytes for SmbReadX.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync#define SMB_READX_MAX 0x10000
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncint smb_common_read(smb_request_t *, smb_rw_param_t *);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Read bytes from a file or named pipe (SMB Core).
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * The requested count specifies the number of bytes desired. Offset
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * is limited to 32 bits, so this client request is inappropriate for
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * files with 64 bit offsets.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * On return, count is the number of bytes actually being returned, which
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * may be less than the count requested only if a read specifies bytes
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * beyond the current file size. In this case only the bytes that exist
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * are returned. A read completely beyond the end of file results in a
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * response of length zero. This is the only circumstance when a zero
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * length response is generated. A count returned which is less than the
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * count requested is the end of file indicator.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_sdrc_t
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_pre_read(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *param;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint32_t off_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t remcnt;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync int rc;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->arg.rw = param;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &count, &off_low, &remcnt);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_offset = (uint64_t)off_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = (uint32_t)count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_mincnt = 0;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync DTRACE_SMB_2(op__Read__start, smb_request_t *, sr,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *, param);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncvoid
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_post_read(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync DTRACE_SMB_2(op__Read__done, smb_request_t *, sr,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *, sr->arg.rw);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_sdrc_t
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_com_read(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *param = sr->arg.rw;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync int rc;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_lookup_file(sr);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (sr->fid_ofile == NULL) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (param->rw_count > SMB_CORE_READ_MAX)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = SMB_CORE_READ_MAX;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if ((rc = smb_common_read(sr, param)) != 0) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_errno(sr, rc);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync count = (uint16_t)param->rw_count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync 5, count, VAR_BCC, 0x01, count, &sr->raw_data);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * attempt to use it on non-disk shares.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * The requested count specifies the number of bytes desired. Offset
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * specifies the offset in the file of the first byte to be locked then
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * read. Note that offset is limited to 32 bits, so this client request
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * is inappropriate for files with 64 bit offsets.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * immediately an error should be returned to the client. If an error
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * occurs on the lock, the bytes should not be read.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * On return, count is the number of bytes actually being returned, which
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * may be less than the count requested only if a read specifies bytes
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * beyond the current file size. In this case only the bytes that exist
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * are returned. A read completely beyond the end of file results in a
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * response of length zero. This is the only circumstance when a zero
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * length response is generated. A count returned which is less than the
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * count requested is the end of file indicator.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_sdrc_t
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_pre_lock_and_read(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *param;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint32_t off_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t remcnt;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync int rc;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->arg.rw = param;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &count, &off_low, &remcnt);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_offset = (uint64_t)off_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = (uint32_t)count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_mincnt = 0;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *, param);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncvoid
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_post_lock_and_read(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *, sr->arg.rw);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_sdrc_t
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_com_lock_and_read(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *param = sr->arg.rw;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync DWORD status;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync int rc;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_lookup_file(sr);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (sr->fid_ofile == NULL) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync 0, SMB_LOCK_TYPE_READWRITE);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (status != NT_STATUS_SUCCESS) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_lock_range_error(sr, status);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (param->rw_count > SMB_CORE_READ_MAX)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = SMB_CORE_READ_MAX;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if ((rc = smb_common_read(sr, param)) != 0) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_errno(sr, rc);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync count = (uint16_t)param->rw_count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync 5, count, VAR_BCC, 0x1, count, &sr->raw_data);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Read bytes from a file (SMB Core). This request was extended in
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * 12 and including additional offset information.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * than the negotiated buffer size. If maxcnt_high is 0xFF, it must
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * be ignored. Otherwise, maxcnt_high represents the upper 16 bits
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * of rw_count.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_sdrc_t
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_pre_read_andx(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *param;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint32_t off_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint32_t off_high;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint32_t maxcnt_high;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t maxcnt_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t mincnt;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t remcnt;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync int rc;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->arg.rw = param;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (sr->smb_wct == 12) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", &param->rw_andx,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &remcnt, &off_high);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_offset = ((uint64_t)off_high << 32) |
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync (uint64_t)off_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = (uint32_t)maxcnt_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if ((sr->session->capabilities & CAP_LARGE_READX) &&
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync (maxcnt_high < 0xFF))
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count |= maxcnt_high << 16;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync } else {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_decode_vwv(sr, "b3.wlwwlw", &param->rw_andx,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &remcnt);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_offset = (uint64_t)off_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = (uint32_t)maxcnt_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_mincnt = 0;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *, param);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncvoid
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_post_read_andx(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *, sr->arg.rw);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_sdrc_t
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_com_read_andx(smb_request_t *sr)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_rw_param_t *param = sr->arg.rw;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t datalen_high;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t datalen_low;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t data_offset;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync uint16_t offset2;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync int rc;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_lookup_file(sr);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (sr->fid_ofile == NULL) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (param->rw_count >= SMB_READX_MAX)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = 0;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if ((rc = smb_common_read(sr, param)) != 0) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smbsr_errno(sr, rc);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync datalen_low = param->rw_count & 0xFFFF;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync datalen_high = (param->rw_count >> 16) & 0xFF;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync /*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * If this is a secondary command, the data offset
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * includes the previous wct + sizeof(wct).
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync data_offset += 60;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC",
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync 12, /* wct */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_andx, /* secondary andx command */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync offset2, /* offset to next command */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync 0, /* set to 0 for named pipes */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync datalen_low, /* data byte count */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync data_offset, /* offset from start to data */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync datalen_high, /* data byte count */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync VAR_BCC, /* BCC marker */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync 0x00, /* padding */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &sr->raw_data);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync } else {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync data_offset += 59;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC",
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync 12, /* wct */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_andx, /* secondary andx command */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync offset2, /* offset to next command */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync -1, /* must be -1 for regular files */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync datalen_low, /* data byte count */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync data_offset, /* offset from start to data */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync datalen_high, /* data byte count */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync VAR_BCC, /* BCC marker */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync &sr->raw_data);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync/*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Common function for reading files or IPC/MSRPC named pipes. All
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * protocol read functions should lookup the fid before calling this
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * function. We can't move the fid lookup here because lock-and-read
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * requires the fid to do locking before attempting the read.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Reading from a file should break oplocks on the file to LEVEL_II.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * required as it is a no-op. If there's anything greater than a
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * on which the read is occuring and therefore would not be broken.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Returns errno values.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncint
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsyncsmb_common_read(smb_request_t *sr, smb_rw_param_t *param)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync{
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_ofile_t *ofile = sr->fid_ofile;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_node_t *node;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_vdb_t *vdb = &param->rw_vdb;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync struct mbuf *top;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync int rc;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync vdb->vdb_tag = 0;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync vdb->vdb_uio.uio_resid = param->rw_count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync switch (sr->tid_tree->t_res_type & STYPE_MASK) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync case STYPE_DISKTREE:
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync node = ofile->f_node;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (!smb_node_is_dir(node)) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smb_lock_range_access(sr, node, param->rw_offset,
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count, B_FALSE);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (rc != NT_STATUS_SUCCESS) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = ERANGE;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync break;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync /*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * reads.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync *
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * Reject request if the file has been opened
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * set.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = EACCES;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync break;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync top = smb_mbuf_allocate(&vdb->vdb_uio);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_mbuf_trim(top, sr->raw_data.max_bytes);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync MBC_ATTACH_MBUF(&sr->raw_data, top);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync break;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync case STYPE_IPC:
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync top = smb_mbuf_allocate(&vdb->vdb_uio);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = smb_opipe_read(sr, &vdb->vdb_uio);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync smb_mbuf_trim(top, sr->raw_data.max_bytes);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync MBC_ATTACH_MBUF(&sr->raw_data, top);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync break;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync default:
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync rc = EACCES;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync break;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count -= vdb->vdb_uio.uio_resid;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (rc != 0)
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (rc);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) {
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync /*
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * mincnt is only used by read-raw and is typically
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * zero. If mincnt is greater than zero and the
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * number of bytes read is less than mincnt, tell
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync * the client that we read nothing.
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync */
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_count = 0;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync }
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync param->rw_offset += param->rw_count;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync mutex_enter(&sr->fid_ofile->f_mutex);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync ofile->f_seek_pos = param->rw_offset;
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync mutex_exit(&sr->fid_ofile->f_mutex);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync return (rc);
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync}
a260560bdbc7bd737d59547882cd5e8d77b80d0avboxsync