2 Unix SMB/CIFS implementation.
3 Durable Handle default VFS implementation
5 Copyright (C) Stefan Metzmacher 2012
6 Copyright (C) Michael Adam 2012
7 Copyright (C) Volker Lendecke 2012
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/filesys.h"
25 #include "smbd/smbd.h"
26 #include "smbd/globals.h"
27 #include "libcli/security/security.h"
29 #include "librpc/gen_ndr/ndr_open_files.h"
31 #include "fake_file.h"
33 NTSTATUS vfs_default_durable_cookie(struct files_struct *fsp,
35 DATA_BLOB *cookie_blob)
37 struct connection_struct *conn = fsp->conn;
38 enum ndr_err_code ndr_err;
39 struct vfs_default_durable_cookie cookie;
41 if (!lp_durable_handles(SNUM(conn))) {
42 return NT_STATUS_NOT_SUPPORTED;
45 if (lp_kernel_share_modes(SNUM(conn))) {
47 * We do not support durable handles
48 * if kernel share modes (flocks) are used
50 return NT_STATUS_NOT_SUPPORTED;
53 if (lp_kernel_oplocks(SNUM(conn))) {
55 * We do not support durable handles
56 * if kernel oplocks are used
58 return NT_STATUS_NOT_SUPPORTED;
61 if ((fsp->current_lock_count > 0) &&
62 lp_posix_locking(fsp->conn->params))
65 * We do not support durable handles
66 * if the handle has posix locks.
68 return NT_STATUS_NOT_SUPPORTED;
71 if (fsp->is_directory) {
72 return NT_STATUS_NOT_SUPPORTED;
75 if (fsp->fh->fd == -1) {
76 return NT_STATUS_NOT_SUPPORTED;
79 if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
81 * We do not support durable handles
84 return NT_STATUS_NOT_SUPPORTED;
87 if (is_fake_file(fsp->fsp_name)) {
89 * We do not support durable handles
92 return NT_STATUS_NOT_SUPPORTED;
96 cookie.allow_reconnect = false;
97 cookie.id = fsp->file_id;
98 cookie.servicepath = conn->connectpath;
99 cookie.base_name = fsp->fsp_name->base_name;
100 cookie.initial_allocation_size = fsp->initial_allocation_size;
101 cookie.position_information = fsp->fh->position_information;
102 cookie.update_write_time_triggered = fsp->update_write_time_triggered;
103 cookie.update_write_time_on_close = fsp->update_write_time_on_close;
104 cookie.write_time_forced = fsp->write_time_forced;
105 cookie.close_write_time = fsp->close_write_time;
107 cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev;
108 cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino;
109 cookie.stat_info.st_ex_mode = fsp->fsp_name->st.st_ex_mode;
110 cookie.stat_info.st_ex_nlink = fsp->fsp_name->st.st_ex_nlink;
111 cookie.stat_info.st_ex_uid = fsp->fsp_name->st.st_ex_uid;
112 cookie.stat_info.st_ex_gid = fsp->fsp_name->st.st_ex_gid;
113 cookie.stat_info.st_ex_rdev = fsp->fsp_name->st.st_ex_rdev;
114 cookie.stat_info.st_ex_size = fsp->fsp_name->st.st_ex_size;
115 cookie.stat_info.st_ex_atime = fsp->fsp_name->st.st_ex_atime;
116 cookie.stat_info.st_ex_mtime = fsp->fsp_name->st.st_ex_mtime;
117 cookie.stat_info.st_ex_ctime = fsp->fsp_name->st.st_ex_ctime;
118 cookie.stat_info.st_ex_btime = fsp->fsp_name->st.st_ex_btime;
119 cookie.stat_info.st_ex_calculated_birthtime = fsp->fsp_name->st.st_ex_calculated_birthtime;
120 cookie.stat_info.st_ex_blksize = fsp->fsp_name->st.st_ex_blksize;
121 cookie.stat_info.st_ex_blocks = fsp->fsp_name->st.st_ex_blocks;
122 cookie.stat_info.st_ex_flags = fsp->fsp_name->st.st_ex_flags;
123 cookie.stat_info.st_ex_mask = fsp->fsp_name->st.st_ex_mask;
124 cookie.stat_info.vfs_private = fsp->fsp_name->st.vfs_private;
126 ndr_err = ndr_push_struct_blob(cookie_blob, mem_ctx, &cookie,
127 (ndr_push_flags_fn_t)ndr_push_vfs_default_durable_cookie);
128 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
129 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
136 NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
137 const DATA_BLOB old_cookie,
139 DATA_BLOB *new_cookie)
141 struct connection_struct *conn = fsp->conn;
143 enum ndr_err_code ndr_err;
144 struct vfs_default_durable_cookie cookie;
145 DATA_BLOB new_cookie_blob = data_blob_null;
146 struct share_mode_lock *lck;
149 *new_cookie = data_blob_null;
153 ndr_err = ndr_pull_struct_blob(&old_cookie, talloc_tos(), &cookie,
154 (ndr_pull_flags_fn_t)ndr_pull_vfs_default_durable_cookie);
155 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
156 status = ndr_map_error2ntstatus(ndr_err);
160 if (strcmp(cookie.magic, VFS_DEFAULT_DURABLE_COOKIE_MAGIC) != 0) {
161 return NT_STATUS_INVALID_PARAMETER;
164 if (cookie.version != VFS_DEFAULT_DURABLE_COOKIE_VERSION) {
165 return NT_STATUS_INVALID_PARAMETER;
168 if (!file_id_equal(&fsp->file_id, &cookie.id)) {
169 return NT_STATUS_INVALID_PARAMETER;
172 if (!BATCH_OPLOCK_TYPE(fsp->oplock_type)) {
173 return NT_STATUS_NOT_SUPPORTED;
176 if (fsp->num_pending_break_messages > 0) {
177 return NT_STATUS_NOT_SUPPORTED;
181 * For now let it be simple and do not keep
182 * delete on close files durable open
184 if (fsp->initial_delete_on_close) {
185 return NT_STATUS_NOT_SUPPORTED;
187 if (fsp->delete_on_close) {
188 return NT_STATUS_NOT_SUPPORTED;
191 if (!VALID_STAT(fsp->fsp_name->st)) {
192 return NT_STATUS_NOT_SUPPORTED;
195 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode)) {
196 return NT_STATUS_NOT_SUPPORTED;
199 /* Ensure any pending write time updates are done. */
200 if (fsp->update_write_time_event) {
201 update_write_time_handler(fsp->conn->sconn->ev_ctx,
202 fsp->update_write_time_event,
208 * The above checks are done in mark_share_mode_disconnected() too
209 * but we want to avoid getting the lock if possible
211 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
213 struct smb_file_time ft;
217 if (fsp->write_time_forced) {
218 ft.mtime = lck->data->changed_write_time;
219 } else if (fsp->update_write_time_on_close) {
220 if (null_timespec(fsp->close_write_time)) {
221 ft.mtime = timespec_current();
223 ft.mtime = fsp->close_write_time;
227 if (!null_timespec(ft.mtime)) {
228 round_timespec(conn->ts_res, &ft.mtime);
229 file_ntimes(conn, fsp->fsp_name, &ft);
232 ok = mark_share_mode_disconnected(lck, fsp);
238 ok = brl_mark_disconnected(fsp);
244 return NT_STATUS_NOT_SUPPORTED;
248 status = vfs_stat_fsp(fsp);
249 if (!NT_STATUS_IS_OK(status)) {
254 cookie.allow_reconnect = true;
255 cookie.id = fsp->file_id;
256 cookie.servicepath = conn->connectpath;
257 cookie.base_name = fsp->fsp_name->base_name;
258 cookie.initial_allocation_size = fsp->initial_allocation_size;
259 cookie.position_information = fsp->fh->position_information;
260 cookie.update_write_time_triggered = fsp->update_write_time_triggered;
261 cookie.update_write_time_on_close = fsp->update_write_time_on_close;
262 cookie.write_time_forced = fsp->write_time_forced;
263 cookie.close_write_time = fsp->close_write_time;
265 cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev;
266 cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino;
267 cookie.stat_info.st_ex_mode = fsp->fsp_name->st.st_ex_mode;
268 cookie.stat_info.st_ex_nlink = fsp->fsp_name->st.st_ex_nlink;
269 cookie.stat_info.st_ex_uid = fsp->fsp_name->st.st_ex_uid;
270 cookie.stat_info.st_ex_gid = fsp->fsp_name->st.st_ex_gid;
271 cookie.stat_info.st_ex_rdev = fsp->fsp_name->st.st_ex_rdev;
272 cookie.stat_info.st_ex_size = fsp->fsp_name->st.st_ex_size;
273 cookie.stat_info.st_ex_atime = fsp->fsp_name->st.st_ex_atime;
274 cookie.stat_info.st_ex_mtime = fsp->fsp_name->st.st_ex_mtime;
275 cookie.stat_info.st_ex_ctime = fsp->fsp_name->st.st_ex_ctime;
276 cookie.stat_info.st_ex_btime = fsp->fsp_name->st.st_ex_btime;
277 cookie.stat_info.st_ex_calculated_birthtime = fsp->fsp_name->st.st_ex_calculated_birthtime;
278 cookie.stat_info.st_ex_blksize = fsp->fsp_name->st.st_ex_blksize;
279 cookie.stat_info.st_ex_blocks = fsp->fsp_name->st.st_ex_blocks;
280 cookie.stat_info.st_ex_flags = fsp->fsp_name->st.st_ex_flags;
281 cookie.stat_info.st_ex_mask = fsp->fsp_name->st.st_ex_mask;
282 cookie.stat_info.vfs_private = fsp->fsp_name->st.vfs_private;
284 ndr_err = ndr_push_struct_blob(&new_cookie_blob, mem_ctx, &cookie,
285 (ndr_push_flags_fn_t)ndr_push_vfs_default_durable_cookie);
286 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
287 status = ndr_map_error2ntstatus(ndr_err);
291 status = fd_close(fsp);
292 if (!NT_STATUS_IS_OK(status)) {
293 data_blob_free(&new_cookie_blob);
297 *new_cookie = new_cookie_blob;
301 NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
302 struct smb_request *smb1req,
303 struct smbXsrv_open *op,
304 const DATA_BLOB old_cookie,
306 files_struct **result,
307 DATA_BLOB *new_cookie)
309 struct share_mode_lock *lck;
310 struct share_mode_entry *e;
311 struct files_struct *fsp = NULL;
316 struct file_id file_id;
317 struct smb_filename *smb_fname = NULL;
318 enum ndr_err_code ndr_err;
319 struct vfs_default_durable_cookie cookie;
320 DATA_BLOB new_cookie_blob = data_blob_null;
323 *new_cookie = data_blob_null;
325 if (!lp_durable_handles(SNUM(conn))) {
326 return NT_STATUS_NOT_SUPPORTED;
330 * the checks for kernel oplocks
331 * and similar things are done
332 * in the vfs_default_durable_cookie()
338 ndr_err = ndr_pull_struct_blob(&old_cookie, talloc_tos(), &cookie,
339 (ndr_pull_flags_fn_t)ndr_pull_vfs_default_durable_cookie);
340 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341 status = ndr_map_error2ntstatus(ndr_err);
345 if (strcmp(cookie.magic, VFS_DEFAULT_DURABLE_COOKIE_MAGIC) != 0) {
346 return NT_STATUS_INVALID_PARAMETER;
349 if (cookie.version != VFS_DEFAULT_DURABLE_COOKIE_VERSION) {
350 return NT_STATUS_INVALID_PARAMETER;
353 if (!cookie.allow_reconnect) {
354 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
357 if (strcmp(cookie.servicepath, conn->connectpath) != 0) {
358 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
361 /* Create an smb_filename with stream_name == NULL. */
362 status = create_synthetic_smb_fname(talloc_tos(),
366 if (!NT_STATUS_IS_OK(status)) {
370 ret = SMB_VFS_LSTAT(conn, smb_fname);
372 status = map_nt_error_from_unix_common(errno);
373 DEBUG(1, ("Unable to lstat stream: %s => %s\n",
374 smb_fname_str_dbg(smb_fname),
379 if (!S_ISREG(smb_fname->st.st_ex_mode)) {
380 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
383 file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
384 if (!file_id_equal(&cookie.id, &file_id)) {
385 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
389 * 1. check entry in locking.tdb
392 lck = get_existing_share_mode_lock(mem_ctx, file_id);
394 DEBUG(5, ("vfs_default_durable_reconnect: share-mode lock "
395 "not obtained from db\n"));
396 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
399 if (lck->data->num_share_modes == 0) {
400 DEBUG(1, ("vfs_default_durable_reconnect: Error: no share-mode "
401 "entry in existing share mode lock\n"));
403 return NT_STATUS_INTERNAL_DB_ERROR;
406 if (lck->data->num_share_modes > 1) {
408 * It can't be durable if there is more than one handle
411 DEBUG(5, ("vfs_default_durable_reconnect: more than one "
412 "share-mode entry - can not be durable\n"));
414 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
417 e = &lck->data->share_modes[0];
419 if (!server_id_is_disconnected(&e->pid)) {
420 DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
421 "reconnect for handle that was not marked "
422 "disconnected (e.g. smbd or cluster node died)\n"));
424 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
427 if (e->share_file_id != op->global->open_persistent_id) {
428 DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
429 "share_file_id changed %llu != %llu"
430 "(e.g. another client had opened the file)\n",
431 (unsigned long long)e->share_file_id,
432 (unsigned long long)op->global->open_persistent_id));
434 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
437 if ((e->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) &&
440 DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
441 "share[%s] is not writeable anymore\n",
442 lp_servicename(talloc_tos(), SNUM(conn))));
444 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
449 * add scavenger timer functionality
451 * For now we always allow the reconnect
454 expire_time = op->global->disconnect_time;
455 expire_time += NTTIME_MAGIC(op->global->durable_timeout_msec);
457 //TODO reopen and close before telling the client...
462 * 2. proceed with opening file
465 status = fsp_new(conn, conn, &fsp);
466 if (!NT_STATUS_IS_OK(status)) {
467 DEBUG(0, ("vfs_default_durable_reconnect: failed to create "
468 "new fsp: %s\n", nt_errstr(status)));
473 fsp->fh->private_options = e->private_options;
474 fsp->fh->gen_id = smbXsrv_open_hash(op);
475 fsp->file_id = file_id;
476 fsp->file_pid = smb1req->smbpid;
477 fsp->vuid = smb1req->vuid;
478 fsp->open_time = e->time;
479 fsp->access_mask = e->access_mask;
480 fsp->share_access = e->share_access;
481 fsp->can_read = ((fsp->access_mask & (FILE_READ_DATA)) != 0);
482 fsp->can_write = ((fsp->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) != 0);
486 * Do we need to store the modified flag in the DB?
487 * How to handle update_write_time and friends
488 * during a disconnected client on a durable handle?
490 fsp->modified = false;
492 * no durables for directories
494 fsp->is_directory = false;
496 * For normal files, can_lock == !is_directory
498 fsp->can_lock = true;
500 * We do not support aio write behind for smb2
502 fsp->aio_write_behind = false;
503 fsp->oplock_type = e->op_type;
505 fsp->initial_allocation_size = cookie.initial_allocation_size;
506 fsp->fh->position_information = cookie.position_information;
507 fsp->update_write_time_triggered = cookie.update_write_time_triggered;
508 fsp->update_write_time_on_close = cookie.update_write_time_on_close;
509 fsp->write_time_forced = cookie.write_time_forced;
510 fsp->close_write_time = cookie.close_write_time;
512 status = fsp_set_smb_fname(fsp, smb_fname);
513 if (!NT_STATUS_IS_OK(status)) {
516 DEBUG(0, ("vfs_default_durable_reconnect: "
517 "fsp_set_smb_fname failed: %s\n",
525 e->pid = messaging_server_id(conn->sconn->msg_ctx);
526 e->op_mid = smb1req->mid;
527 e->share_file_id = fsp->fh->gen_id;
529 ok = brl_reconnect_disconnected(fsp);
531 status = NT_STATUS_INTERNAL_ERROR;
532 DEBUG(1, ("vfs_default_durable_reconnect: "
533 "failed to reopen brlocks: %s\n",
542 * TODO: properly calculate open flags
544 if (fsp->can_write && fsp->can_read) {
546 } else if (fsp->can_write) {
548 } else if (fsp->can_read) {
552 status = fd_open(conn, fsp, flags, 0 /* mode */);
553 if (!NT_STATUS_IS_OK(status)) {
555 DEBUG(1, ("vfs_default_durable_reconnect: failed to open "
556 "file: %s\n", nt_errstr(status)));
563 * We now check the stat info stored in the cookie against
564 * the current stat data from the file we just opened.
565 * If any detail differs, we deny the durable reconnect,
566 * because in that case it is very likely that someone
567 * opened the file while the handle was disconnected,
568 * which has to be interpreted as an oplock break.
571 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
573 status = map_nt_error_from_unix_common(errno);
574 DEBUG(1, ("Unable to fstat stream: %s => %s\n",
575 smb_fname_str_dbg(smb_fname),
577 ret = SMB_VFS_CLOSE(fsp);
579 DEBUG(0, ("vfs_default_durable_reconnect: "
580 "SMB_VFS_CLOSE failed (%s) - leaking file "
581 "descriptor\n", strerror(errno)));
589 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode)) {
590 ret = SMB_VFS_CLOSE(fsp);
592 DEBUG(0, ("vfs_default_durable_reconnect: "
593 "SMB_VFS_CLOSE failed (%s) - leaking file "
594 "descriptor\n", strerror(errno)));
599 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
602 file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
603 if (!file_id_equal(&cookie.id, &file_id)) {
604 ret = SMB_VFS_CLOSE(fsp);
606 DEBUG(0, ("vfs_default_durable_reconnect: "
607 "SMB_VFS_CLOSE failed (%s) - leaking file "
608 "descriptor\n", strerror(errno)));
613 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
616 if (cookie.stat_info.st_ex_dev != fsp->fsp_name->st.st_ex_dev) {
617 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
618 "stat_ex.%s differs: "
619 "cookie:%llu != stat:%llu, "
620 "denying durable reconnect\n",
623 (unsigned long long)cookie.stat_info.st_ex_dev,
624 (unsigned long long)fsp->fsp_name->st.st_ex_dev));
625 ret = SMB_VFS_CLOSE(fsp);
627 DEBUG(0, ("vfs_default_durable_reconnect: "
628 "SMB_VFS_CLOSE failed (%s) - leaking file "
629 "descriptor\n", strerror(errno)));
634 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
637 if (cookie.stat_info.st_ex_ino != fsp->fsp_name->st.st_ex_ino) {
638 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
639 "stat_ex.%s differs: "
640 "cookie:%llu != stat:%llu, "
641 "denying durable reconnect\n",
644 (unsigned long long)cookie.stat_info.st_ex_ino,
645 (unsigned long long)fsp->fsp_name->st.st_ex_ino));
646 ret = SMB_VFS_CLOSE(fsp);
648 DEBUG(0, ("vfs_default_durable_reconnect: "
649 "SMB_VFS_CLOSE failed (%s) - leaking file "
650 "descriptor\n", strerror(errno)));
655 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
658 if (cookie.stat_info.st_ex_mode != fsp->fsp_name->st.st_ex_mode) {
659 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
660 "stat_ex.%s differs: "
661 "cookie:%llu != stat:%llu, "
662 "denying durable reconnect\n",
665 (unsigned long long)cookie.stat_info.st_ex_mode,
666 (unsigned long long)fsp->fsp_name->st.st_ex_mode));
667 ret = SMB_VFS_CLOSE(fsp);
669 DEBUG(0, ("vfs_default_durable_reconnect: "
670 "SMB_VFS_CLOSE failed (%s) - leaking file "
671 "descriptor\n", strerror(errno)));
676 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
679 if (cookie.stat_info.st_ex_nlink != fsp->fsp_name->st.st_ex_nlink) {
680 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
681 "stat_ex.%s differs: "
682 "cookie:%llu != stat:%llu, "
683 "denying durable reconnect\n",
686 (unsigned long long)cookie.stat_info.st_ex_nlink,
687 (unsigned long long)fsp->fsp_name->st.st_ex_nlink));
688 ret = SMB_VFS_CLOSE(fsp);
690 DEBUG(0, ("vfs_default_durable_reconnect: "
691 "SMB_VFS_CLOSE failed (%s) - leaking file "
692 "descriptor\n", strerror(errno)));
697 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
700 if (cookie.stat_info.st_ex_uid != fsp->fsp_name->st.st_ex_uid) {
701 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
702 "stat_ex.%s differs: "
703 "cookie:%llu != stat:%llu, "
704 "denying durable reconnect\n",
707 (unsigned long long)cookie.stat_info.st_ex_uid,
708 (unsigned long long)fsp->fsp_name->st.st_ex_uid));
709 ret = SMB_VFS_CLOSE(fsp);
711 DEBUG(0, ("vfs_default_durable_reconnect: "
712 "SMB_VFS_CLOSE failed (%s) - leaking file "
713 "descriptor\n", strerror(errno)));
718 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
721 if (cookie.stat_info.st_ex_gid != fsp->fsp_name->st.st_ex_gid) {
722 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
723 "stat_ex.%s differs: "
724 "cookie:%llu != stat:%llu, "
725 "denying durable reconnect\n",
728 (unsigned long long)cookie.stat_info.st_ex_gid,
729 (unsigned long long)fsp->fsp_name->st.st_ex_gid));
730 ret = SMB_VFS_CLOSE(fsp);
732 DEBUG(0, ("vfs_default_durable_reconnect: "
733 "SMB_VFS_CLOSE failed (%s) - leaking file "
734 "descriptor\n", strerror(errno)));
739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
742 if (cookie.stat_info.st_ex_rdev != fsp->fsp_name->st.st_ex_rdev) {
743 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
744 "stat_ex.%s differs: "
745 "cookie:%llu != stat:%llu, "
746 "denying durable reconnect\n",
749 (unsigned long long)cookie.stat_info.st_ex_rdev,
750 (unsigned long long)fsp->fsp_name->st.st_ex_rdev));
751 ret = SMB_VFS_CLOSE(fsp);
753 DEBUG(0, ("vfs_default_durable_reconnect: "
754 "SMB_VFS_CLOSE failed (%s) - leaking file "
755 "descriptor\n", strerror(errno)));
760 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
763 if (cookie.stat_info.st_ex_size != fsp->fsp_name->st.st_ex_size) {
764 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
765 "stat_ex.%s differs: "
766 "cookie:%llu != stat:%llu, "
767 "denying durable reconnect\n",
770 (unsigned long long)cookie.stat_info.st_ex_size,
771 (unsigned long long)fsp->fsp_name->st.st_ex_size));
772 ret = SMB_VFS_CLOSE(fsp);
774 DEBUG(0, ("vfs_default_durable_reconnect: "
775 "SMB_VFS_CLOSE failed (%s) - leaking file "
776 "descriptor\n", strerror(errno)));
781 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
784 ret = timespec_compare(&cookie.stat_info.st_ex_atime,
785 &fsp->fsp_name->st.st_ex_atime);
787 struct timeval tc, ts;
788 tc = convert_timespec_to_timeval(cookie.stat_info.st_ex_atime);
789 ts = convert_timespec_to_timeval(fsp->fsp_name->st.st_ex_atime);
791 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
792 "stat_ex.%s differs: "
793 "cookie:'%s' != stat:'%s', "
794 "denying durable reconnect\n",
797 timeval_string(talloc_tos(), &tc, true),
798 timeval_string(talloc_tos(), &ts, true)));
799 ret = SMB_VFS_CLOSE(fsp);
801 DEBUG(0, ("vfs_default_durable_reconnect: "
802 "SMB_VFS_CLOSE failed (%s) - leaking file "
803 "descriptor\n", strerror(errno)));
808 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
811 ret = timespec_compare(&cookie.stat_info.st_ex_mtime,
812 &fsp->fsp_name->st.st_ex_mtime);
814 struct timeval tc, ts;
815 tc = convert_timespec_to_timeval(cookie.stat_info.st_ex_mtime);
816 ts = convert_timespec_to_timeval(fsp->fsp_name->st.st_ex_mtime);
818 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
819 "stat_ex.%s differs: "
820 "cookie:'%s' != stat:'%s', "
821 "denying durable reconnect\n",
824 timeval_string(talloc_tos(), &tc, true),
825 timeval_string(talloc_tos(), &ts, true)));
826 ret = SMB_VFS_CLOSE(fsp);
828 DEBUG(0, ("vfs_default_durable_reconnect: "
829 "SMB_VFS_CLOSE failed (%s) - leaking file "
830 "descriptor\n", strerror(errno)));
835 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
838 ret = timespec_compare(&cookie.stat_info.st_ex_ctime,
839 &fsp->fsp_name->st.st_ex_ctime);
841 struct timeval tc, ts;
842 tc = convert_timespec_to_timeval(cookie.stat_info.st_ex_ctime);
843 ts = convert_timespec_to_timeval(fsp->fsp_name->st.st_ex_ctime);
845 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
846 "stat_ex.%s differs: "
847 "cookie:'%s' != stat:'%s', "
848 "denying durable reconnect\n",
851 timeval_string(talloc_tos(), &tc, true),
852 timeval_string(talloc_tos(), &ts, true)));
853 ret = SMB_VFS_CLOSE(fsp);
855 DEBUG(0, ("vfs_default_durable_reconnect: "
856 "SMB_VFS_CLOSE failed (%s) - leaking file "
857 "descriptor\n", strerror(errno)));
862 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
865 ret = timespec_compare(&cookie.stat_info.st_ex_btime,
866 &fsp->fsp_name->st.st_ex_btime);
868 struct timeval tc, ts;
869 tc = convert_timespec_to_timeval(cookie.stat_info.st_ex_btime);
870 ts = convert_timespec_to_timeval(fsp->fsp_name->st.st_ex_btime);
872 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
873 "stat_ex.%s differs: "
874 "cookie:'%s' != stat:'%s', "
875 "denying durable reconnect\n",
878 timeval_string(talloc_tos(), &tc, true),
879 timeval_string(talloc_tos(), &ts, true)));
880 ret = SMB_VFS_CLOSE(fsp);
882 DEBUG(0, ("vfs_default_durable_reconnect: "
883 "SMB_VFS_CLOSE failed (%s) - leaking file "
884 "descriptor\n", strerror(errno)));
889 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
892 if (cookie.stat_info.st_ex_calculated_birthtime !=
893 fsp->fsp_name->st.st_ex_calculated_birthtime)
895 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
896 "stat_ex.%s differs: "
897 "cookie:%llu != stat:%llu, "
898 "denying durable reconnect\n",
900 "st_ex_calculated_birthtime",
901 (unsigned long long)cookie.stat_info.st_ex_calculated_birthtime,
902 (unsigned long long)fsp->fsp_name->st.st_ex_calculated_birthtime));
903 ret = SMB_VFS_CLOSE(fsp);
905 DEBUG(0, ("vfs_default_durable_reconnect: "
906 "SMB_VFS_CLOSE failed (%s) - leaking file "
907 "descriptor\n", strerror(errno)));
912 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
915 if (cookie.stat_info.st_ex_blksize != fsp->fsp_name->st.st_ex_blksize) {
916 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
917 "stat_ex.%s differs: "
918 "cookie:%llu != stat:%llu, "
919 "denying durable reconnect\n",
922 (unsigned long long)cookie.stat_info.st_ex_blksize,
923 (unsigned long long)fsp->fsp_name->st.st_ex_blksize));
924 ret = SMB_VFS_CLOSE(fsp);
926 DEBUG(0, ("vfs_default_durable_reconnect: "
927 "SMB_VFS_CLOSE failed (%s) - leaking file "
928 "descriptor\n", strerror(errno)));
933 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
936 if (cookie.stat_info.st_ex_blocks != fsp->fsp_name->st.st_ex_blocks) {
937 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
938 "stat_ex.%s differs: "
939 "cookie:%llu != stat:%llu, "
940 "denying durable reconnect\n",
943 (unsigned long long)cookie.stat_info.st_ex_blocks,
944 (unsigned long long)fsp->fsp_name->st.st_ex_blocks));
945 ret = SMB_VFS_CLOSE(fsp);
947 DEBUG(0, ("vfs_default_durable_reconnect: "
948 "SMB_VFS_CLOSE failed (%s) - leaking file "
949 "descriptor\n", strerror(errno)));
954 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
957 if (cookie.stat_info.st_ex_flags != fsp->fsp_name->st.st_ex_flags) {
958 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
959 "stat_ex.%s differs: "
960 "cookie:%llu != stat:%llu, "
961 "denying durable reconnect\n",
964 (unsigned long long)cookie.stat_info.st_ex_flags,
965 (unsigned long long)fsp->fsp_name->st.st_ex_flags));
966 ret = SMB_VFS_CLOSE(fsp);
968 DEBUG(0, ("vfs_default_durable_reconnect: "
969 "SMB_VFS_CLOSE failed (%s) - leaking file "
970 "descriptor\n", strerror(errno)));
975 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
978 if (cookie.stat_info.st_ex_mask != fsp->fsp_name->st.st_ex_mask) {
979 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
980 "stat_ex.%s differs: "
981 "cookie:%llu != stat:%llu, "
982 "denying durable reconnect\n",
985 (unsigned long long)cookie.stat_info.st_ex_mask,
986 (unsigned long long)fsp->fsp_name->st.st_ex_mask));
987 ret = SMB_VFS_CLOSE(fsp);
989 DEBUG(0, ("vfs_default_durable_reconnect: "
990 "SMB_VFS_CLOSE failed (%s) - leaking file "
991 "descriptor\n", strerror(errno)));
996 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
999 if (cookie.stat_info.vfs_private != fsp->fsp_name->st.vfs_private) {
1000 DEBUG(1, ("vfs_default_durable_reconnect (%s): "
1001 "stat_ex.%s differs: "
1002 "cookie:%llu != stat:%llu, "
1003 "denying durable reconnect\n",
1006 (unsigned long long)cookie.stat_info.vfs_private,
1007 (unsigned long long)fsp->fsp_name->st.vfs_private));
1008 ret = SMB_VFS_CLOSE(fsp);
1010 DEBUG(0, ("vfs_default_durable_reconnect: "
1011 "SMB_VFS_CLOSE failed (%s) - leaking file "
1012 "descriptor\n", strerror(errno)));
1017 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1020 status = set_file_oplock(fsp, e->op_type);
1021 if (!NT_STATUS_IS_OK(status)) {
1022 DEBUG(1, ("vfs_default_durable_reconnect failed to set oplock "
1023 "after opening file: %s\n", nt_errstr(status)));
1024 ret = SMB_VFS_CLOSE(fsp);
1026 DEBUG(0, ("vfs_default_durable_reconnect: "
1027 "SMB_VFS_CLOSE failed (%s) - leaking file "
1028 "descriptor\n", strerror(errno)));
1036 status = vfs_default_durable_cookie(fsp, mem_ctx, &new_cookie_blob);
1037 if (!NT_STATUS_IS_OK(status)) {
1039 DEBUG(1, ("vfs_default_durable_reconnect: "
1040 "vfs_default_durable_cookie - %s\n",
1041 nt_errstr(status)));
1047 smb1req->chain_fsp = fsp;
1048 smb1req->smb2req->compat_chain_fsp = fsp;
1050 DEBUG(10, ("vfs_default_durable_reconnect: opened file '%s'\n",
1054 * release the sharemode lock: this writes the changes
1056 lck->data->modified = true;
1060 *new_cookie = new_cookie_blob;
1062 return NT_STATUS_OK;