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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 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_incl.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_com_seek(struct smb_request *sr) 84 { 85 ushort_t mode; 86 int32_t off; 87 uint32_t off_ret; 88 int rc; 89 90 if (smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &mode, &off) != 0) 91 return (SDRC_ERROR_REPLY); 92 93 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 94 if (sr->fid_ofile == NULL) { 95 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 96 return (SDRC_ERROR_REPLY); 97 } 98 99 if (mode == SMB_SEEK_END) 100 (void) smb_set_file_size(sr); 101 102 if ((rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret)) != 0) { 103 if (rc == EINVAL) { 104 smbsr_error(sr, 0, ERRDOS, ERRbadfunc); 105 return (SDRC_ERROR_REPLY); 106 } else { 107 smbsr_error(sr, 0, ERRSRV, ERRerror); 108 return (SDRC_ERROR_REPLY); 109 } 110 } 111 112 if (smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0)) 113 return (SDRC_ERROR_REPLY); 114 115 return (SDRC_NORMAL_REPLY); 116 } 117