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 /* 27 * The seek message is sent to set the current file pointer for FID. 28 * This request should generally only be used by clients wishing to 29 * find the size of a file, since all read and write requests include 30 * the read or write file position as part of the SMB. This request 31 * is inappropriate for large files, as the offsets specified are only 32 * 32 bits. 33 * 34 * The CIFS/1.0 (1996) spec contains the following incomplete statement: 35 * 36 * "A seek which results in an Offset which can not be expressed 37 * in 32 bits returns the least significant." 38 * 39 * It would probably be a mistake to make an assumption about what this 40 * statement means. So, for now, we return an error if the resultant 41 * file offset is beyond the 32-bit limit. 42 */ 43 44 #include <smbsrv/smb_incl.h> 45 46 47 /* 48 * smb_com_seek 49 * 50 * Client Request Description 51 * ================================== ================================= 52 * UCHAR WordCount; Count of parameter words = 4 53 * USHORT Fid; File handle 54 * USHORT Mode; Seek mode: 0, 1 or 2 55 * LONG Offset; Relative offset 56 * USHORT ByteCount; Count of data bytes = 0 57 * 58 * The starting point of the seek is set by Mode: 59 * 60 * 0 seek from start of file 61 * 1 seek from current current position 62 * 2 seek from end of file 63 * 64 * The "current position" reflects the offset plus data length specified in 65 * the previous read, write or seek request, and the pointer set by this 66 * command will be replaced by the offset specified in the next read, write 67 * or seek command. 68 * 69 * Server Response Description 70 * ================================== ================================= 71 * UCHAR WordCount; Count of parameter words = 2 72 * ULONG Offset; Offset from start of file 73 * USHORT ByteCount; Count of data bytes = 0 74 * 75 * The response returns the new file pointer in Offset, which is expressed 76 * as the offset from the start of the file, and may be beyond the current 77 * end of file. An attempt to seek before the start of the file sets the 78 * current file pointer to the start of the file. 79 */ 80 smb_sdrc_t 81 smb_pre_seek(smb_request_t *sr) 82 { 83 DTRACE_SMB_1(op__Seek__start, smb_request_t *, sr); 84 return (SDRC_SUCCESS); 85 } 86 87 void 88 smb_post_seek(smb_request_t *sr) 89 { 90 DTRACE_SMB_1(op__Seek__done, smb_request_t *, sr); 91 } 92 93 smb_sdrc_t 94 smb_com_seek(smb_request_t *sr) 95 { 96 ushort_t mode; 97 int32_t off; 98 uint32_t off_ret; 99 int rc; 100 101 if (smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &mode, &off) != 0) 102 return (SDRC_ERROR); 103 104 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 105 if (sr->fid_ofile == NULL) { 106 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 107 return (SDRC_ERROR); 108 } 109 110 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 111 112 if (mode == SMB_SEEK_END) 113 (void) smb_set_file_size(sr, sr->fid_ofile->f_node); 114 115 if ((rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret)) != 0) { 116 if (rc == EINVAL) { 117 smbsr_error(sr, 0, ERRDOS, ERRbadfunc); 118 return (SDRC_ERROR); 119 } else { 120 smbsr_error(sr, 0, ERRSRV, ERRerror); 121 return (SDRC_ERROR); 122 } 123 } 124 125 if (smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0)) 126 return (SDRC_ERROR); 127 128 return (SDRC_SUCCESS); 129 } 130