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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 /* 27 * Common functions supporting both: 28 * SMB1 Trans2 Set File/Path Info, 29 * SMB2 Set File Info 30 */ 31 32 #include <smbsrv/smb_kproto.h> 33 #include <smbsrv/smb_fsops.h> 34 35 /* 36 * smb_set_basic_info 37 * [MS-FSCC] 2.4.7 38 * FileBasicInformation 39 * SMB_SET_FILE_BASIC_INFO 40 * SMB_FILE_BASIC_INFORMATION 41 * 42 * Sets basic file/path information. 43 * 44 * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the 45 * target is not a directory. 46 * 47 * For compatibility with windows servers: 48 * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set 49 * clear (0) the file's attributes. 50 * - if the specified attributes are 0 do NOT change the file's attributes. 51 */ 52 uint32_t 53 smb_set_basic_info(smb_request_t *sr, smb_setinfo_t *si) 54 { 55 smb_attr_t *attr = &si->si_attr; 56 smb_node_t *node = si->si_node; 57 uint64_t crtime, atime, mtime, ctime; 58 uint32_t attributes; 59 int rc; 60 61 if (smb_mbc_decodef(&si->si_data, "qqqql", 62 &crtime, &atime, &mtime, &ctime, &attributes) != 0) 63 return (NT_STATUS_INFO_LENGTH_MISMATCH); 64 65 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) && 66 (!smb_node_is_dir(node))) 67 return (NT_STATUS_INVALID_PARAMETER); 68 69 bzero(attr, sizeof (*attr)); 70 if (atime != 0 && atime != (uint64_t)-1) { 71 smb_time_nt_to_unix(atime, &attr->sa_vattr.va_atime); 72 attr->sa_mask |= SMB_AT_ATIME; 73 } 74 if (mtime != 0 && mtime != (uint64_t)-1) { 75 smb_time_nt_to_unix(mtime, &attr->sa_vattr.va_mtime); 76 attr->sa_mask |= SMB_AT_MTIME; 77 } 78 if (ctime != 0 && ctime != (uint64_t)-1) { 79 smb_time_nt_to_unix(ctime, &attr->sa_vattr.va_ctime); 80 attr->sa_mask |= SMB_AT_CTIME; 81 } 82 if (crtime != 0 && crtime != (uint64_t)-1) { 83 smb_time_nt_to_unix(crtime, &attr->sa_crtime); 84 attr->sa_mask |= SMB_AT_CRTIME; 85 } 86 87 if (attributes != 0) { 88 attr->sa_dosattr = attributes; 89 attr->sa_mask |= SMB_AT_DOSATTR; 90 } 91 92 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr); 93 if (rc != 0) 94 return (smb_errno2status(rc)); 95 96 return (0); 97 } 98 99 /* 100 * smb_set_eof_info 101 * FileEndOfFileInformation 102 * SMB_SET_FILE_END_OF_FILE_INFO 103 * SMB_FILE_END_OF_FILE_INFORMATION 104 */ 105 uint32_t 106 smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *si) 107 { 108 smb_attr_t *attr = &si->si_attr; 109 smb_node_t *node = si->si_node; 110 uint64_t eof; 111 int rc; 112 113 if (smb_mbc_decodef(&si->si_data, "q", &eof) != 0) 114 return (NT_STATUS_INFO_LENGTH_MISMATCH); 115 116 if (smb_node_is_dir(node)) 117 return (NT_STATUS_INVALID_PARAMETER); 118 119 /* If opened by path, break exclusive oplock */ 120 if (sr->fid_ofile == NULL) 121 (void) smb_oplock_break(sr, node, 122 SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE); 123 124 bzero(attr, sizeof (*attr)); 125 attr->sa_mask = SMB_AT_SIZE; 126 attr->sa_vattr.va_size = (u_offset_t)eof; 127 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr); 128 if (rc != 0) 129 return (smb_errno2status(rc)); 130 131 smb_oplock_break_levelII(node); 132 return (0); 133 } 134 135 /* 136 * smb_set_alloc_info 137 * FileAllocationInformation 138 * SMB_SET_FILE_ALLOCATION_INFO 139 * SMB_FILE_ALLOCATION_INFORMATION 140 */ 141 uint32_t 142 smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *si) 143 { 144 smb_attr_t *attr = &si->si_attr; 145 smb_node_t *node = si->si_node; 146 uint64_t allocsz; 147 int rc; 148 149 if (smb_mbc_decodef(&si->si_data, "q", &allocsz) != 0) 150 return (NT_STATUS_INFO_LENGTH_MISMATCH); 151 152 if (smb_node_is_dir(node)) 153 return (NT_STATUS_INVALID_PARAMETER); 154 155 /* If opened by path, break exclusive oplock */ 156 if (sr->fid_ofile == NULL) 157 (void) smb_oplock_break(sr, node, 158 SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE); 159 160 bzero(attr, sizeof (*attr)); 161 attr->sa_mask = SMB_AT_ALLOCSZ; 162 attr->sa_allocsz = (u_offset_t)allocsz; 163 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr); 164 if (rc != 0) 165 return (smb_errno2status(rc)); 166 167 smb_oplock_break_levelII(node); 168 return (0); 169 } 170 171 /* 172 * smb_set_disposition_info 173 * See: 174 * FileDispositionInformation 175 * SMB_SET_FILE_DISPOSITION_INFO 176 * SMB_FILE_DISPOSITION_INFORMATION 177 * 178 * Set/Clear DELETE_ON_CLOSE flag for an open file. 179 * File should have been opened with DELETE access otherwise 180 * the operation is not permitted. 181 * 182 * NOTE: The node should be marked delete-on-close upon the receipt 183 * of the Trans2SetFileInfo(SetDispositionInfo) if mark_delete is set. 184 * It is different than both SmbNtCreateAndX and SmbNtTransact, which 185 * set delete-on-close on the ofile and defer setting the flag on the 186 * node until the file is closed. 187 * 188 * Observation of Windows 2000 indicates the following: 189 * 190 * 1) If a file is not opened with delete-on-close create options and 191 * the delete-on-close is set via Trans2SetFileInfo(SetDispositionInfo) 192 * using that open file handle, any subsequent open requests will fail 193 * with DELETE_PENDING. 194 * 195 * 2) If a file is opened with delete-on-close create options and the 196 * client attempts to unset delete-on-close via Trans2SetFileInfo 197 * (SetDispositionInfo) prior to the file close, any subsequent open 198 * requests will still fail with DELETE_PENDING after the file is closed. 199 * 200 * 3) If a file is opened with delete-on-close create options and that 201 * file handle (not the last open handle and the only file handle 202 * with delete-on-close set) is closed. Any subsequent open requests 203 * will fail with DELETE_PENDING. Unsetting delete-on-close via 204 * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the 205 * node delete-on-close flag, which will result in the file not being 206 * removed even after the last file handle is closed. 207 */ 208 uint32_t 209 smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *si) 210 { 211 smb_node_t *node = si->si_node; 212 smb_ofile_t *of = sr->fid_ofile; 213 uint8_t mark_delete; 214 uint32_t flags = 0; 215 216 if (smb_mbc_decodef(&si->si_data, "b", &mark_delete) != 0) 217 return (NT_STATUS_INFO_LENGTH_MISMATCH); 218 219 if ((of == NULL) || !(smb_ofile_granted_access(of) & DELETE)) 220 return (NT_STATUS_ACCESS_DENIED); 221 222 if (mark_delete) { 223 if (SMB_TREE_SUPPORTS_CATIA(sr)) 224 flags |= SMB_CATIA; 225 return (smb_node_set_delete_on_close(node, of->f_cr, flags)); 226 } else { 227 smb_node_reset_delete_on_close(node); 228 } 229 230 return (NT_STATUS_SUCCESS); 231 } 232