1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 26 */ 27 28 /* 29 * The seek message is sent to set the current file pointer for FID. 30 * This request should generally only be used by clients wishing to 31 * find the size of a file, since all read and write requests include 32 * the read or write file position as part of the SMB. This request 33 * is inappropriate for large files, as the offsets specified are only 34 * 32 bits. 35 * 36 * The CIFS/1.0 (1996) spec contains the following incomplete statement: 37 * 38 * "A seek which results in an Offset which can not be expressed 39 * in 32 bits returns the least significant." 40 * 41 * It would probably be a mistake to make an assumption about what this 42 * statement means. So, for now, we return an error if the resultant 43 * file offset is beyond the 32-bit limit. 44 */ 45 46 #include <smbsrv/smb_kproto.h> 47 48 49 /* 50 * smb_com_seek 51 * 52 * Client Request Description 53 * ================================== ================================= 54 * UCHAR WordCount; Count of parameter words = 4 55 * USHORT Fid; File handle 56 * USHORT Mode; Seek mode: 0, 1 or 2 57 * LONG Offset; Relative offset 58 * USHORT ByteCount; Count of data bytes = 0 59 * 60 * The starting point of the seek is set by Mode: 61 * 62 * 0 seek from start of file 63 * 1 seek from current current position 64 * 2 seek from end of file 65 * 66 * The "current position" reflects the offset plus data length specified in 67 * the previous read, write or seek request, and the pointer set by this 68 * command will be replaced by the offset specified in the next read, write 69 * or seek command. 70 * 71 * Server Response Description 72 * ================================== ================================= 73 * UCHAR WordCount; Count of parameter words = 2 74 * ULONG Offset; Offset from start of file 75 * USHORT ByteCount; Count of data bytes = 0 76 * 77 * The response returns the new file pointer in Offset, which is expressed 78 * as the offset from the start of the file, and may be beyond the current 79 * end of file. An attempt to seek before the start of the file sets the 80 * current file pointer to the start of the file. 81 */ 82 smb_sdrc_t 83 smb_pre_seek(smb_request_t *sr) 84 { 85 DTRACE_SMB_START(op__Seek, smb_request_t *, sr); 86 return (SDRC_SUCCESS); 87 } 88 89 void 90 smb_post_seek(smb_request_t *sr) 91 { 92 DTRACE_SMB_DONE(op__Seek, smb_request_t *, sr); 93 } 94 95 smb_sdrc_t 96 smb_com_seek(smb_request_t *sr) 97 { 98 ushort_t mode; 99 int32_t off; 100 uint32_t off_ret; 101 int rc; 102 103 if (smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &mode, &off) != 0) 104 return (SDRC_ERROR); 105 106 smbsr_lookup_file(sr); 107 if (sr->fid_ofile == NULL) { 108 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 109 return (SDRC_ERROR); 110 } 111 112 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 113 114 if ((rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret)) != 0) { 115 if (rc == EINVAL) { 116 smbsr_error(sr, 0, ERRDOS, ERRbadfunc); 117 return (SDRC_ERROR); 118 } else { 119 smbsr_error(sr, 0, ERRSRV, ERRerror); 120 return (SDRC_ERROR); 121 } 122 } 123 124 if (smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0)) 125 return (SDRC_ERROR); 126 127 return (SDRC_SUCCESS); 128 } 129