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 2020 Tintri by DDN, 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/smb2_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 uint32_t status; 112 int rc; 113 114 if (smb_mbc_decodef(&si->si_data, "q", &eof) != 0) 115 return (NT_STATUS_INFO_LENGTH_MISMATCH); 116 117 if (smb_node_is_dir(node)) 118 return (NT_STATUS_INVALID_PARAMETER); 119 120 status = smb_oplock_break_SETINFO(node, sr->fid_ofile, 121 FileEndOfFileInformation); 122 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 123 if (sr->session->dialect >= SMB_VERS_2_BASE) 124 (void) smb2sr_go_async(sr); 125 (void) smb_oplock_wait_break(sr, node, 0); 126 status = 0; 127 } 128 if (status != 0) 129 return (status); 130 131 bzero(attr, sizeof (*attr)); 132 attr->sa_mask = SMB_AT_SIZE; 133 attr->sa_vattr.va_size = (u_offset_t)eof; 134 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr); 135 if (rc != 0) 136 return (smb_errno2status(rc)); 137 138 return (0); 139 } 140 141 /* 142 * smb_set_alloc_info 143 * FileAllocationInformation 144 * SMB_SET_FILE_ALLOCATION_INFO 145 * SMB_FILE_ALLOCATION_INFORMATION 146 */ 147 uint32_t 148 smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *si) 149 { 150 smb_attr_t *attr = &si->si_attr; 151 smb_node_t *node = si->si_node; 152 uint64_t allocsz; 153 uint32_t status; 154 int rc; 155 156 if (smb_mbc_decodef(&si->si_data, "q", &allocsz) != 0) 157 return (NT_STATUS_INFO_LENGTH_MISMATCH); 158 159 if (smb_node_is_dir(node)) 160 return (NT_STATUS_INVALID_PARAMETER); 161 162 status = smb_oplock_break_SETINFO(node, sr->fid_ofile, 163 FileAllocationInformation); 164 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 165 if (sr->session->dialect >= SMB_VERS_2_BASE) 166 (void) smb2sr_go_async(sr); 167 (void) smb_oplock_wait_break(sr, node, 0); 168 status = 0; 169 } 170 if (status != 0) 171 return (status); 172 173 bzero(attr, sizeof (*attr)); 174 attr->sa_mask = SMB_AT_ALLOCSZ; 175 attr->sa_allocsz = (u_offset_t)allocsz; 176 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr); 177 if (rc != 0) 178 return (smb_errno2status(rc)); 179 180 return (0); 181 } 182 183 /* 184 * smb_set_disposition_info 185 * See: 186 * FileDispositionInformation 187 * SMB_SET_FILE_DISPOSITION_INFO 188 * SMB_FILE_DISPOSITION_INFORMATION 189 * 190 * Set/Clear DELETE_ON_CLOSE flag for an open file. 191 * File should have been opened with DELETE access otherwise 192 * the operation is not permitted. 193 * 194 * NOTE: The node should be marked delete-on-close upon the receipt 195 * of the Trans2SetFileInfo(SetDispositionInfo) if mark_delete is set. 196 * It is different than both SmbNtCreateAndX and SmbNtTransact, which 197 * set delete-on-close on the ofile and defer setting the flag on the 198 * node until the file is closed. 199 * 200 * Observation of Windows 2000 indicates the following: 201 * 202 * 1) If a file is not opened with delete-on-close create options and 203 * the delete-on-close is set via Trans2SetFileInfo(SetDispositionInfo) 204 * using that open file handle, any subsequent open requests will fail 205 * with DELETE_PENDING. 206 * 207 * 2) If a file is opened with delete-on-close create options and the 208 * client attempts to unset delete-on-close via Trans2SetFileInfo 209 * (SetDispositionInfo) prior to the file close, any subsequent open 210 * requests will still fail with DELETE_PENDING after the file is closed. 211 * 212 * 3) If a file is opened with delete-on-close create options and that 213 * file handle (not the last open handle and the only file handle 214 * with delete-on-close set) is closed. Any subsequent open requests 215 * will fail with DELETE_PENDING. Unsetting delete-on-close via 216 * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the 217 * node delete-on-close flag, which will result in the file not being 218 * removed even after the last file handle is closed. 219 */ 220 uint32_t 221 smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *si) 222 { 223 smb_node_t *node = si->si_node; 224 smb_ofile_t *of = sr->fid_ofile; 225 uint8_t mark_delete; 226 uint32_t status; 227 uint32_t flags = 0; 228 229 if (smb_mbc_decodef(&si->si_data, "b", &mark_delete) != 0) 230 return (NT_STATUS_INFO_LENGTH_MISMATCH); 231 232 if ((of == NULL) || !(smb_ofile_granted_access(of) & DELETE)) 233 return (NT_STATUS_ACCESS_DENIED); 234 235 if (mark_delete == 0) { 236 smb_node_reset_delete_on_close(node); 237 return (NT_STATUS_SUCCESS); 238 } 239 240 /* 241 * Break any oplock handle caching. 242 */ 243 status = smb_oplock_break_SETINFO(node, of, 244 FileDispositionInformation); 245 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 246 if (sr->session->dialect >= SMB_VERS_2_BASE) 247 (void) smb2sr_go_async(sr); 248 (void) smb_oplock_wait_break(sr, node, 0); 249 status = 0; 250 } 251 if (status != 0) 252 return (status); 253 254 if (SMB_TREE_SUPPORTS_CATIA(sr)) 255 flags |= SMB_CATIA; 256 257 return (smb_node_set_delete_on_close(node, of->f_cr, flags)); 258 } 259