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	"@(#)smb_close.c	1.6	08/08/08 SMI"
27 
28 #include <smbsrv/smb_incl.h>
29 
30 
31 /*
32  * Close a file by fid.  All locks or other resources held by the
33  * requesting process on the file should be released by the server.
34  * The requesting process can no longer use the fid for further
35  * file access requests.
36  *
37  * If LastWriteTime is non-zero, it should be used to set the file
38  * timestamp.  Otherwise, file system should set the timestamp.
39  * Failure to set the timestamp, even if requested by the client,
40  * should not result in an error response from the server.
41  */
42 smb_sdrc_t
43 smb_pre_close(smb_request_t *sr)
44 {
45 	int rc;
46 
47 	rc = smbsr_decode_vwv(sr, "wl", &sr->smb_fid, &sr->arg.timestamp);
48 
49 	DTRACE_SMB_1(op__Close__start, smb_request_t *, sr);
50 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
51 }
52 
53 void
54 smb_post_close(smb_request_t *sr)
55 {
56 	DTRACE_SMB_1(op__Close__done, smb_request_t *, sr);
57 }
58 
59 smb_sdrc_t
60 smb_com_close(smb_request_t *sr)
61 {
62 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
63 	if (sr->fid_ofile == NULL) {
64 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
65 		return (SDRC_ERROR);
66 	}
67 
68 	smb_ofile_close(sr->fid_ofile, sr->arg.timestamp);
69 
70 	if (smbsr_encode_empty_result(sr) != 0)
71 		return (SDRC_ERROR);
72 
73 	return (SDRC_SUCCESS);
74 }
75 
76 /*
77  * Close the file represented by fid and then disconnect the
78  * associated tree.
79  */
80 smb_sdrc_t
81 smb_pre_close_and_tree_disconnect(smb_request_t *sr)
82 {
83 	int rc;
84 
85 	rc = smbsr_decode_vwv(sr, "wl", &sr->smb_fid, &sr->arg.timestamp);
86 
87 	DTRACE_SMB_1(op__CloseAndTreeDisconnect__start, smb_request_t *, sr);
88 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
89 }
90 
91 void
92 smb_post_close_and_tree_disconnect(smb_request_t *sr)
93 {
94 	DTRACE_SMB_1(op__CloseAndTreeDisconnect__done, smb_request_t *, sr);
95 }
96 
97 smb_sdrc_t
98 smb_com_close_and_tree_disconnect(smb_request_t *sr)
99 {
100 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
101 	if (sr->fid_ofile == NULL) {
102 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
103 		return (SDRC_ERROR);
104 	}
105 
106 	smb_ofile_close(sr->fid_ofile, sr->arg.timestamp);
107 	smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
108 	smb_tree_disconnect(sr->tid_tree);
109 
110 	if (smbsr_encode_empty_result(sr) != 0)
111 		return (SDRC_ERROR);
112 
113 	return (SDRC_SUCCESS);
114 }
115 
116 /*
117  * smb_commit_delete_on_close()
118  *
119  * Check for the DeleteOnClose flag on the smb file and set it on the
120  * smb node if it is not already set. This will inhibit subsequent
121  * open requests. The delete-on-close credentials should be set to the
122  * user credentials of the current open file instance.
123  *
124  * When DeleteOnClose is set on an smb_node, the common open code will
125  * reject subsequent open requests for the file. Observation of Windows
126  * 2000 indicates that subsequent opens should be allowed (assuming
127  * there would be no sharing violation) until the file is closed using
128  * the fid on which the DeleteOnClose was requested.
129  *
130  * If there are multiple opens with delete-on-close create options,
131  * whichever the first file handle is closed will trigger the node to be
132  * marked as delete-on-close. The credentials of that ofile will be used
133  * as the delete-on-close credentials of the node.
134  */
135 void
136 smb_commit_delete_on_close(struct smb_ofile *ofile)
137 {
138 	struct smb_node *node = ofile->f_node;
139 
140 	if (!(node->flags & NODE_FLAGS_DELETE_ON_CLOSE) &&
141 	    (ofile->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE))	{
142 		node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
143 		crhold(node->delete_on_close_cred = ofile->f_cr);
144 	}
145 }
146