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
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 *
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 }
|
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 2017 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/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
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(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(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 *
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(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 }
|