s3: include smbd/smbd.h where needed.
[nivanova/samba-autobuild/.git] / source3 / smbd / smb2_close.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "smbd/smbd.h"
23 #include "smbd/globals.h"
24 #include "../libcli/smb/smb_common.h"
25
26 static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
27                                 uint16_t in_flags,
28                                 uint64_t in_file_id_volatile,
29                                 DATA_BLOB *outbody);
30
31 NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
32 {
33         const uint8_t *inhdr;
34         const uint8_t *inbody;
35         int i = req->current_idx;
36         uint8_t *outhdr;
37         DATA_BLOB outbody;
38         size_t expected_body_size = 0x18;
39         size_t body_size;
40         uint16_t in_flags;
41         uint64_t in_file_id_persistent;
42         uint64_t in_file_id_volatile;
43         NTSTATUS status;
44
45         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
46         if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
47                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
48         }
49
50         inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
51
52         body_size = SVAL(inbody, 0x00);
53         if (body_size != expected_body_size) {
54                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
55         }
56
57         outbody = data_blob_talloc(req->out.vector, NULL, 0x3C);
58         if (outbody.data == NULL) {
59                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
60         }
61
62         in_flags                = SVAL(inbody, 0x02);
63         in_file_id_persistent   = BVAL(inbody, 0x08);
64         in_file_id_volatile     = BVAL(inbody, 0x10);
65
66         if (req->compat_chain_fsp) {
67                 /* skip check */
68         } else if (in_file_id_persistent != in_file_id_volatile) {
69                 return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
70         }
71
72         status = smbd_smb2_close(req,
73                                 in_flags,
74                                 in_file_id_volatile,
75                                 &outbody);
76         if (!NT_STATUS_IS_OK(status)) {
77                 return smbd_smb2_request_error(req, status);
78         }
79
80         outhdr = (uint8_t *)req->out.vector[i].iov_base;
81         return smbd_smb2_request_done(req, outbody, NULL);
82 }
83
84 static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
85                                 uint16_t in_flags,
86                                 uint64_t in_file_id_volatile,
87                                 DATA_BLOB *outbody)
88 {
89         NTSTATUS status;
90         struct smb_request *smbreq;
91         connection_struct *conn = req->tcon->compat_conn;
92         files_struct *fsp;
93         struct smb_filename *smb_fname = NULL;
94         struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
95         uint64_t allocation_size = 0;
96         uint64_t file_size = 0;
97         uint32_t dos_attrs = 0;
98         uint16_t out_flags = 0;
99         bool posix_open = false;
100
101         ZERO_STRUCT(create_date_ts);
102         ZERO_STRUCT(adate_ts);
103         ZERO_STRUCT(mdate_ts);
104         ZERO_STRUCT(cdate_ts);
105
106         DEBUG(10,("smbd_smb2_close: file_id[0x%016llX]\n",
107                   (unsigned long long)in_file_id_volatile));
108
109         smbreq = smbd_smb2_fake_smb_request(req);
110         if (smbreq == NULL) {
111                 return NT_STATUS_NO_MEMORY;
112         }
113
114         fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
115         if (fsp == NULL) {
116                 return NT_STATUS_FILE_CLOSED;
117         }
118         if (conn != fsp->conn) {
119                 return NT_STATUS_FILE_CLOSED;
120         }
121         if (req->session->vuid != fsp->vuid) {
122                 return NT_STATUS_FILE_CLOSED;
123         }
124
125         posix_open = fsp->posix_open;
126         status = copy_smb_filename(talloc_tos(),
127                                 fsp->fsp_name,
128                                 &smb_fname);
129         if (!NT_STATUS_IS_OK(status)) {
130                 return status;
131         }
132
133         status = close_file(smbreq, fsp, NORMAL_CLOSE);
134         if (!NT_STATUS_IS_OK(status)) {
135                 DEBUG(5,("smbd_smb2_close: close_file[%s]: %s\n",
136                          fsp_str_dbg(fsp), nt_errstr(status)));
137                 return status;
138         }
139
140         if (in_flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) {
141                 int ret;
142                 if (posix_open) {
143                         ret = SMB_VFS_LSTAT(conn, smb_fname);
144                 } else {
145                         ret = SMB_VFS_STAT(conn, smb_fname);
146                 }
147                 if (ret == 0) {
148                         out_flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
149                         dos_attrs = dos_mode(conn, smb_fname);
150                         mdate_ts = smb_fname->st.st_ex_mtime;
151                         adate_ts = smb_fname->st.st_ex_atime;
152                         create_date_ts = get_create_timespec(conn, NULL, smb_fname);
153                         cdate_ts = get_change_timespec(conn, NULL, smb_fname);
154
155                         if (lp_dos_filetime_resolution(SNUM(conn))) {
156                                 dos_filetime_timespec(&create_date_ts);
157                                 dos_filetime_timespec(&mdate_ts);
158                                 dos_filetime_timespec(&adate_ts);
159                                 dos_filetime_timespec(&cdate_ts);
160                         }
161                         if (!(dos_attrs & FILE_ATTRIBUTE_DIRECTORY)) {
162                                 file_size = get_file_size_stat(&smb_fname->st);
163                         }
164
165                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
166                 }
167         }
168
169         SSVAL(outbody->data, 0x00, 0x3C);       /* struct size */
170         SSVAL(outbody->data, 0x02, out_flags);  /* flags */
171         SIVAL(outbody->data, 0x04, 0);          /* reserved */
172         put_long_date_timespec(conn->ts_res,
173                 (char *)&outbody->data[0x8],create_date_ts); /* creation time */
174         put_long_date_timespec(conn->ts_res,
175                 (char *)&outbody->data[0x10],adate_ts); /* last access time */
176         put_long_date_timespec(conn->ts_res,
177                 (char *)&outbody->data[0x18],mdate_ts); /* last write time */
178         put_long_date_timespec(conn->ts_res,
179                 (char *)&outbody->data[0x20],cdate_ts); /* change time */
180         SBVAL(outbody->data, 0x28, allocation_size);/* allocation size */
181         SBVAL(outbody->data, 0x30, file_size);  /* end of file */
182         SIVAL(outbody->data, 0x38, dos_attrs);  /* file attributes */
183
184         return NT_STATUS_OK;
185 }