smbd: Fix cached dos attributes
[Samba.git] / source3 / smbd / close.c
blob5cb2bb6f17c2dcba5147fdb42187f1edefaffce8
1 /*
2 Unix SMB/CIFS implementation.
3 file closing
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1992-2007.
6 Copyright (C) Volker Lendecke 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/filesys.h"
24 #include "lib/util/server_id.h"
25 #include "printing.h"
26 #include "locking/share_mode_lock.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "smbd/smbXsrv_open.h"
30 #include "smbd/scavenger.h"
31 #include "fake_file.h"
32 #include "transfer_file.h"
33 #include "auth.h"
34 #include "messages.h"
35 #include "librpc/gen_ndr/ndr_open_files.h"
36 #include "lib/util/tevent_ntstatus.h"
37 #include "source3/smbd/dir.h"
39 /****************************************************************************
40 Run a file if it is a magic script.
41 ****************************************************************************/
43 static NTSTATUS check_magic(struct files_struct *fsp)
45 int ret;
46 const struct loadparm_substitution *lp_sub =
47 loadparm_s3_global_substitution();
48 const char *magic_output = NULL;
49 SMB_STRUCT_STAT st;
50 int tmp_fd, outfd;
51 TALLOC_CTX *ctx = NULL;
52 const char *p;
53 struct connection_struct *conn = fsp->conn;
54 char *fname = NULL;
55 NTSTATUS status;
57 if (!*lp_magic_script(talloc_tos(), lp_sub, SNUM(conn))) {
58 return NT_STATUS_OK;
61 DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));
63 ctx = talloc_stackframe();
65 fname = fsp->fsp_name->base_name;
67 if (!(p = strrchr_m(fname,'/'))) {
68 p = fname;
69 } else {
70 p++;
73 if (!strequal(lp_magic_script(talloc_tos(), lp_sub, SNUM(conn)),p)) {
74 status = NT_STATUS_OK;
75 goto out;
78 if (*lp_magic_output(talloc_tos(), lp_sub, SNUM(conn))) {
79 magic_output = lp_magic_output(talloc_tos(), lp_sub, SNUM(conn));
80 } else {
81 magic_output = talloc_asprintf(ctx,
82 "%s.out",
83 fname);
85 if (!magic_output) {
86 status = NT_STATUS_NO_MEMORY;
87 goto out;
90 /* Ensure we don't depend on user's PATH. */
91 p = talloc_asprintf(ctx, "./%s", fname);
92 if (!p) {
93 status = NT_STATUS_NO_MEMORY;
94 goto out;
97 if (chmod(fname, 0755) == -1) {
98 status = map_nt_error_from_unix(errno);
99 goto out;
101 ret = smbrun(p, &tmp_fd, NULL);
102 DEBUG(3,("Invoking magic command %s gave %d\n",
103 p,ret));
105 unlink(fname);
106 if (ret != 0 || tmp_fd == -1) {
107 if (tmp_fd != -1) {
108 close(tmp_fd);
110 status = NT_STATUS_UNSUCCESSFUL;
111 goto out;
113 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
114 if (outfd == -1) {
115 int err = errno;
116 close(tmp_fd);
117 status = map_nt_error_from_unix(err);
118 goto out;
121 if (sys_fstat(tmp_fd, &st, false) == -1) {
122 int err = errno;
123 close(tmp_fd);
124 close(outfd);
125 status = map_nt_error_from_unix(err);
126 goto out;
129 if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) {
130 int err = errno;
131 close(tmp_fd);
132 close(outfd);
133 status = map_nt_error_from_unix(err);
134 goto out;
136 close(tmp_fd);
137 if (close(outfd) == -1) {
138 status = map_nt_error_from_unix(errno);
139 goto out;
142 status = NT_STATUS_OK;
144 out:
145 TALLOC_FREE(ctx);
146 return status;
149 /****************************************************************************
150 Delete all streams
151 ****************************************************************************/
153 NTSTATUS delete_all_streams(connection_struct *conn,
154 const struct smb_filename *smb_fname)
156 struct stream_struct *stream_info = NULL;
157 unsigned int i;
158 unsigned int num_streams = 0;
159 TALLOC_CTX *frame = talloc_stackframe();
160 NTSTATUS status;
162 status = vfs_fstreaminfo(smb_fname->fsp, talloc_tos(),
163 &num_streams, &stream_info);
165 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
166 DEBUG(10, ("no streams around\n"));
167 TALLOC_FREE(frame);
168 return NT_STATUS_OK;
171 if (!NT_STATUS_IS_OK(status)) {
172 DEBUG(10, ("vfs_fstreaminfo failed: %s\n",
173 nt_errstr(status)));
174 goto fail;
177 DEBUG(10, ("delete_all_streams found %d streams\n",
178 num_streams));
180 if (num_streams == 0) {
181 TALLOC_FREE(frame);
182 return NT_STATUS_OK;
185 for (i=0; i<num_streams; i++) {
186 int res;
187 struct smb_filename *smb_fname_stream;
189 if (strequal(stream_info[i].name, "::$DATA")) {
190 continue;
193 status = synthetic_pathref(talloc_tos(),
194 conn->cwd_fsp,
195 smb_fname->base_name,
196 stream_info[i].name,
197 NULL,
198 smb_fname->twrp,
199 (smb_fname->flags &
200 ~SMB_FILENAME_POSIX_PATH),
201 &smb_fname_stream);
202 if (!NT_STATUS_IS_OK(status)) {
203 DEBUG(0, ("talloc_aprintf failed\n"));
204 status = NT_STATUS_NO_MEMORY;
205 goto fail;
208 res = SMB_VFS_UNLINKAT(conn,
209 conn->cwd_fsp,
210 smb_fname_stream,
213 if (res == -1) {
214 status = map_nt_error_from_unix(errno);
215 DEBUG(10, ("Could not delete stream %s: %s\n",
216 smb_fname_str_dbg(smb_fname_stream),
217 strerror(errno)));
218 TALLOC_FREE(smb_fname_stream);
219 break;
221 TALLOC_FREE(smb_fname_stream);
224 fail:
225 TALLOC_FREE(frame);
226 return status;
229 struct has_other_nonposix_opens_state {
230 files_struct *fsp;
231 bool found_another;
234 static bool has_other_nonposix_opens_fn(
235 struct share_mode_entry *e,
236 bool *modified,
237 void *private_data)
239 struct has_other_nonposix_opens_state *state = private_data;
240 struct files_struct *fsp = state->fsp;
242 if (e->name_hash != fsp->name_hash) {
243 return false;
245 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
246 return false;
248 if (e->share_file_id == fh_get_gen_id(fsp->fh)) {
249 struct server_id self = messaging_server_id(
250 fsp->conn->sconn->msg_ctx);
251 if (server_id_equal(&self, &e->pid)) {
252 return false;
255 if (share_entry_stale_pid(e)) {
256 return false;
259 state->found_another = true;
260 return true;
263 bool has_other_nonposix_opens(struct share_mode_lock *lck,
264 struct files_struct *fsp)
266 struct has_other_nonposix_opens_state state = { .fsp = fsp };
267 bool ok;
269 ok = share_mode_forall_entries(
270 lck, has_other_nonposix_opens_fn, &state);
271 if (!ok) {
272 return false;
274 return state.found_another;
277 struct close_share_mode_lock_state {
278 struct share_mode_entry_prepare_state prepare_state;
279 const char *object_type;
280 struct files_struct *fsp;
281 enum file_close_type close_type;
282 bool delete_object;
283 bool got_tokens;
284 const struct security_unix_token *del_token;
285 const struct security_token *del_nt_token;
286 bool reset_delete_on_close;
287 share_mode_entry_prepare_unlock_fn_t cleanup_fn;
290 static void close_share_mode_lock_prepare(struct share_mode_lock *lck,
291 bool *keep_locked,
292 void *private_data)
294 struct close_share_mode_lock_state *state =
295 (struct close_share_mode_lock_state *)private_data;
296 struct files_struct *fsp = state->fsp;
297 bool normal_close;
298 bool ok;
301 * By default drop the g_lock again if we leave the
302 * tdb chainlock.
304 *keep_locked = false;
306 if (fsp->oplock_type != NO_OPLOCK) {
307 ok = remove_share_oplock(lck, fsp);
308 if (!ok) {
309 struct file_id_buf buf;
311 DBG_ERR("failed to remove share oplock for "
312 "%s %s, %s, %s\n",
313 state->object_type,
314 fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
315 file_id_str_buf(fsp->file_id, &buf));
319 if (fsp->fsp_flags.write_time_forced) {
320 NTTIME mtime = share_mode_changed_write_time(lck);
321 struct timespec ts = nt_time_to_full_timespec(mtime);
323 DBG_DEBUG("write time forced for %s %s\n",
324 state->object_type, fsp_str_dbg(fsp));
325 set_close_write_time(fsp, ts);
326 } else if (fsp->fsp_flags.update_write_time_on_close) {
327 /* Someone had a pending write. */
328 if (is_omit_timespec(&fsp->close_write_time)) {
329 DBG_DEBUG("update to current time for %s %s\n",
330 state->object_type, fsp_str_dbg(fsp));
331 /* Update to current time due to "normal" write. */
332 set_close_write_time(fsp, timespec_current());
333 } else {
334 DBG_DEBUG("write time pending for %s %s\n",
335 state->object_type, fsp_str_dbg(fsp));
336 /* Update to time set on close call. */
337 set_close_write_time(fsp, fsp->close_write_time);
341 if (fsp->fsp_flags.initial_delete_on_close &&
342 !is_delete_on_close_set(lck, fsp->name_hash)) {
343 /* Initial delete on close was set and no one else
344 * wrote a real delete on close. */
346 fsp->fsp_flags.delete_on_close = true;
347 set_delete_on_close_lck(fsp, lck,
348 fsp->conn->session_info->security_token,
349 fsp->conn->session_info->unix_token);
352 state->delete_object = is_delete_on_close_set(lck, fsp->name_hash) &&
353 !has_other_nonposix_opens(lck, fsp);
356 * NT can set delete_on_close of the last open
357 * reference to a file.
360 normal_close = (state->close_type == NORMAL_CLOSE || state->close_type == SHUTDOWN_CLOSE);
361 if (!normal_close) {
363 * Never try to delete the file/directory for ERROR_CLOSE
365 state->delete_object = false;
368 if (!state->delete_object) {
369 ok = del_share_mode(lck, fsp);
370 if (!ok) {
371 DBG_ERR("Could not delete share entry for %s %s\n",
372 state->object_type, fsp_str_dbg(fsp));
374 return;
378 * We're going to remove the file/directory
379 * so keep the g_lock after the tdb chainlock
380 * is left, so we hold the share_mode_lock
381 * also during the deletion
383 *keep_locked = true;
385 state->got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
386 &state->del_nt_token, &state->del_token);
387 if (state->close_type != ERROR_CLOSE) {
388 SMB_ASSERT(state->got_tokens);
392 static void close_share_mode_lock_cleanup(struct share_mode_lock *lck,
393 void *private_data)
395 struct close_share_mode_lock_state *state =
396 (struct close_share_mode_lock_state *)private_data;
397 struct files_struct *fsp = state->fsp;
398 bool ok;
400 if (state->reset_delete_on_close) {
401 reset_delete_on_close_lck(fsp, lck);
404 ok = del_share_mode(lck, fsp);
405 if (!ok) {
406 DBG_ERR("Could not delete share entry for %s %s\n",
407 state->object_type, fsp_str_dbg(fsp));
411 /****************************************************************************
412 Deal with removing a share mode on last close.
413 ****************************************************************************/
415 static NTSTATUS close_remove_share_mode(files_struct *fsp,
416 enum file_close_type close_type)
418 connection_struct *conn = fsp->conn;
419 struct close_share_mode_lock_state lck_state = {};
420 bool changed_user = false;
421 NTSTATUS status = NT_STATUS_OK;
422 NTSTATUS tmp_status;
423 NTSTATUS ulstatus;
424 struct file_id id;
425 struct smb_filename *parent_fname = NULL;
426 struct smb_filename *base_fname = NULL;
427 int ret;
429 /* Ensure any pending write time updates are done. */
430 if (fsp->update_write_time_event) {
431 fsp_flush_write_time_update(fsp);
435 * Lock the share entries, and determine if we should delete
436 * on close. If so delete whilst the lock is still in effect.
437 * This prevents race conditions with the file being created. JRA.
440 lck_state = (struct close_share_mode_lock_state) {
441 .fsp = fsp,
442 .object_type = "file",
443 .close_type = close_type,
446 status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
447 fsp->file_id,
448 close_share_mode_lock_prepare,
449 &lck_state);
450 if (!NT_STATUS_IS_OK(status)) {
451 DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
452 fsp_str_dbg(fsp), nt_errstr(status));
453 return status;
456 /* Remove the oplock before potentially deleting the file. */
457 if (fsp->oplock_type != NO_OPLOCK) {
458 release_file_oplock(fsp);
462 * NT can set delete_on_close of the last open
463 * reference to a file.
466 if (!lck_state.delete_object) {
467 status = NT_STATUS_OK;
468 goto done;
472 * Ok, we have to delete the file
474 lck_state.cleanup_fn = close_share_mode_lock_cleanup;
476 DBG_INFO("%s. Delete on close was set - deleting file.\n",
477 fsp_str_dbg(fsp));
480 * Don't try to update the write time when we delete the file
482 fsp->fsp_flags.update_write_time_on_close = false;
484 if (lck_state.got_tokens &&
485 !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
487 /* Become the user who requested the delete. */
489 DBG_INFO("file %s. Change user to uid %u\n",
490 fsp_str_dbg(fsp),
491 (unsigned int)lck_state.del_token->uid);
493 if (!push_sec_ctx()) {
494 smb_panic("close_remove_share_mode: file %s. failed to push "
495 "sec_ctx.\n");
498 set_sec_ctx(lck_state.del_token->uid,
499 lck_state.del_token->gid,
500 lck_state.del_token->ngroups,
501 lck_state.del_token->groups,
502 lck_state.del_nt_token);
504 changed_user = true;
507 /* We can only delete the file if the name we have is still valid and
508 hasn't been renamed. */
510 tmp_status = vfs_stat_fsp(fsp);
511 if (!NT_STATUS_IS_OK(tmp_status)) {
512 DBG_INFO("file %s. Delete on close "
513 "was set and stat failed with error %s\n",
514 fsp_str_dbg(fsp),
515 nt_errstr(tmp_status));
517 * Don't save the errno here, we ignore this error
519 goto done;
522 id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
524 if (!file_id_equal(&fsp->file_id, &id)) {
525 struct file_id_buf ftmp1, ftmp2;
526 DBG_INFO("file %s. Delete on close "
527 "was set and dev and/or inode does not match\n",
528 fsp_str_dbg(fsp));
529 DBG_INFO("file %s. stored file_id %s, stat file_id %s\n",
530 fsp_str_dbg(fsp),
531 file_id_str_buf(fsp->file_id, &ftmp1),
532 file_id_str_buf(id, &ftmp2));
534 * Don't save the errno here, we ignore this error
536 goto done;
539 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
540 && !fsp_is_alternate_stream(fsp)) {
542 status = delete_all_streams(conn, fsp->fsp_name);
544 if (!NT_STATUS_IS_OK(status)) {
545 DEBUG(5, ("delete_all_streams failed: %s\n",
546 nt_errstr(status)));
547 goto done;
551 if (fsp->fsp_flags.kernel_share_modes_taken) {
553 * A file system sharemode could block the unlink;
554 * remove filesystem sharemodes first.
556 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
557 if (ret == -1) {
558 DBG_INFO("Removing file system sharemode for %s "
559 "failed: %s\n",
560 fsp_str_dbg(fsp), strerror(errno));
563 fsp->fsp_flags.kernel_share_modes_taken = false;
566 status = parent_pathref(talloc_tos(),
567 conn->cwd_fsp,
568 fsp->fsp_name,
569 &parent_fname,
570 &base_fname);
571 if (!NT_STATUS_IS_OK(status)) {
572 goto done;
575 ret = SMB_VFS_UNLINKAT(conn,
576 parent_fname->fsp,
577 base_fname,
579 TALLOC_FREE(parent_fname);
580 base_fname = NULL;
581 if (ret != 0) {
583 * This call can potentially fail as another smbd may
584 * have had the file open with delete on close set and
585 * deleted it when its last reference to this file
586 * went away. Hence we log this but not at debug level
587 * zero.
590 DBG_INFO("file %s. Delete on close "
591 "was set and unlink failed with error %s\n",
592 fsp_str_dbg(fsp),
593 strerror(errno));
595 status = map_nt_error_from_unix(errno);
598 /* As we now have POSIX opens which can unlink
599 * with other open files we may have taken
600 * this code path with more than one share mode
601 * entry - ensure we only delete once by resetting
602 * the delete on close flag. JRA.
605 fsp->fsp_flags.delete_on_close = false;
606 fsp->fsp_flags.fstat_before_close = false;
607 lck_state.reset_delete_on_close = true;
609 done:
611 if (changed_user) {
612 /* unbecome user. */
613 pop_sec_ctx();
616 if (fsp->fsp_flags.kernel_share_modes_taken) {
617 /* remove filesystem sharemodes */
618 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
619 if (ret == -1) {
620 DBG_INFO("Removing file system sharemode for "
621 "%s failed: %s\n",
622 fsp_str_dbg(fsp), strerror(errno));
626 ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
627 lck_state.cleanup_fn,
628 &lck_state);
629 if (!NT_STATUS_IS_OK(ulstatus)) {
630 DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
631 fsp_str_dbg(fsp), nt_errstr(ulstatus));
632 smb_panic("share_mode_entry_prepare_unlock() failed!");
635 if (lck_state.delete_object) {
636 notify_fname(conn, NOTIFY_ACTION_REMOVED,
637 FILE_NOTIFY_CHANGE_FILE_NAME,
638 fsp->fsp_name->base_name);
641 return status;
644 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
646 DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
648 if (is_omit_timespec(&ts)) {
649 return;
651 fsp->fsp_flags.write_time_forced = false;
652 fsp->fsp_flags.update_write_time_on_close = true;
653 fsp->close_write_time = ts;
656 static void update_write_time_on_close_share_mode_fn(struct share_mode_lock *lck,
657 void *private_data)
659 struct files_struct *fsp =
660 talloc_get_type_abort(private_data,
661 struct files_struct);
662 NTTIME share_mtime = share_mode_changed_write_time(lck);
665 * On close if we're changing the real file time we
666 * must update it in the open file db too.
668 share_mode_set_old_write_time(lck, fsp->close_write_time);
671 * Close write times overwrite sticky write times
672 * so we must replace any sticky write time here.
674 if (!null_nttime(share_mtime)) {
675 share_mode_set_changed_write_time(lck, fsp->close_write_time);
679 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
681 struct smb_file_time ft;
682 NTSTATUS status;
684 init_smb_file_time(&ft);
686 if (!(fsp->fsp_flags.update_write_time_on_close)) {
687 return NT_STATUS_OK;
690 if (is_omit_timespec(&fsp->close_write_time)) {
691 fsp->close_write_time = timespec_current();
694 /* Ensure we have a valid stat struct for the source. */
695 status = vfs_stat_fsp(fsp);
696 if (!NT_STATUS_IS_OK(status)) {
697 return status;
700 if (!VALID_STAT(fsp->fsp_name->st)) {
701 /* if it doesn't seem to be a real file */
702 return NT_STATUS_OK;
706 * We're being called after close_remove_share_mode() inside
707 * close_normal_file() so it's quite normal to not have an
708 * existing share. So just ignore the result of
709 * share_mode_do_locked_vfs_denied()...
711 share_mode_do_locked_vfs_denied(fsp->file_id,
712 update_write_time_on_close_share_mode_fn,
713 fsp);
715 ft.mtime = fsp->close_write_time;
716 /* As this is a close based update, we are not directly changing the
717 file attributes from a client call, but indirectly from a write. */
718 status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
719 if (!NT_STATUS_IS_OK(status)) {
720 DEBUG(10,("update_write_time_on_close: smb_set_file_time "
721 "on file %s returned %s\n",
722 fsp_str_dbg(fsp),
723 nt_errstr(status)));
724 return status;
727 return status;
730 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
732 if (!NT_STATUS_IS_OK(s1)) {
733 return s1;
735 return s2;
738 static void assert_no_pending_aio(struct files_struct *fsp,
739 enum file_close_type close_type)
741 struct smbXsrv_client *client = global_smbXsrv_client;
742 size_t num_connections_alive;
743 unsigned num_requests = fsp->num_aio_requests;
745 if (num_requests == 0) {
746 return;
749 num_connections_alive = smbXsrv_client_valid_connections(client);
751 if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
753 * fsp->aio_requests and the contents (fsp->aio_requests[x])
754 * are both independently owned by fsp and are not in a
755 * talloc hierarchy. This allows the fsp->aio_requests array to
756 * be reallocated independently of the array contents so it can
757 * grow on demand.
759 * This means we must ensure order of deallocation
760 * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
761 * contents first, as their destructors access the
762 * fsp->aio_request array. If we don't deallocate them
763 * first, when fsp is deallocated fsp->aio_requests
764 * could have been deallocated *before* its contents
765 * fsp->aio_requests[x], causing a crash.
767 while (fsp->num_aio_requests != 0) {
769 * NB. We *MUST* use
770 * talloc_free(fsp->aio_requests[0]),
771 * and *NOT* TALLOC_FREE() here, as
772 * TALLOC_FREE(fsp->aio_requests[0])
773 * will overwrite any new contents of
774 * fsp->aio_requests[0] that were
775 * copied into it via the destructor
776 * aio_del_req_from_fsp().
778 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
780 talloc_free(fsp->aio_requests[0]);
782 return;
785 DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
786 smb_panic("can not close with outstanding aio requests");
787 return;
790 /****************************************************************************
791 Close a file.
793 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
794 printing and magic scripts are only run on normal close.
795 delete on close is done on normal and shutdown close.
796 ****************************************************************************/
798 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
799 enum file_close_type close_type)
801 NTSTATUS status = NT_STATUS_OK;
802 NTSTATUS tmp;
803 connection_struct *conn = fsp->conn;
804 bool is_durable = false;
806 SMB_ASSERT(fsp->fsp_flags.is_fsa);
808 assert_no_pending_aio(fsp, close_type);
810 while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
811 smbd_smb1_brl_finish_by_req(
812 fsp->blocked_smb1_lock_reqs[0],
813 NT_STATUS_RANGE_NOT_LOCKED);
817 * If we're flushing on a close we can get a write
818 * error here, we must remember this.
821 if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
822 is_durable = fsp->op->global->durable;
825 if (close_type != SHUTDOWN_CLOSE) {
826 is_durable = false;
829 if (is_durable) {
830 DATA_BLOB new_cookie = data_blob_null;
832 tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
833 fsp->op->global->backend_cookie,
834 fsp->op,
835 &new_cookie);
836 if (NT_STATUS_IS_OK(tmp)) {
837 struct timeval tv;
838 NTTIME now;
840 if (req != NULL) {
841 tv = req->request_time;
842 } else {
843 tv = timeval_current();
845 now = timeval_to_nttime(&tv);
847 data_blob_free(&fsp->op->global->backend_cookie);
848 fsp->op->global->backend_cookie = new_cookie;
850 fsp->op->compat = NULL;
851 tmp = smbXsrv_open_close(fsp->op, now);
852 if (!NT_STATUS_IS_OK(tmp)) {
853 DEBUG(1, ("Failed to update smbXsrv_open "
854 "record when disconnecting durable "
855 "handle for file %s: %s - "
856 "proceeding with normal close\n",
857 fsp_str_dbg(fsp), nt_errstr(tmp)));
859 scavenger_schedule_disconnected(fsp);
860 } else {
861 DEBUG(1, ("Failed to disconnect durable handle for "
862 "file %s: %s - proceeding with normal "
863 "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
865 if (!NT_STATUS_IS_OK(tmp)) {
866 is_durable = false;
870 if (is_durable) {
872 * This is the case where we successfully disconnected
873 * a durable handle and closed the underlying file.
874 * In all other cases, we proceed with a genuine close.
876 DEBUG(10, ("%s disconnected durable handle for file %s\n",
877 conn->session_info->unix_info->unix_name,
878 fsp_str_dbg(fsp)));
879 return NT_STATUS_OK;
882 if (fsp->op != NULL) {
884 * Make sure the handle is not marked as durable anymore
886 fsp->op->global->durable = false;
889 /* If this is an old DOS or FCB open and we have multiple opens on
890 the same handle we only have one share mode. Ensure we only remove
891 the share mode on the last close. */
893 if (fh_get_refcount(fsp->fh) == 1) {
894 /* Should we return on error here... ? */
895 tmp = close_remove_share_mode(fsp, close_type);
896 status = ntstatus_keeperror(status, tmp);
899 locking_close_file(fsp, close_type);
902 * Ensure pending modtime is set before closing underlying fd.
905 tmp = update_write_time_on_close(fsp);
906 if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
908 * Someone renamed the file or a parent directory containing
909 * this file. We can't do anything about this, eat the error.
911 tmp = NT_STATUS_OK;
913 status = ntstatus_keeperror(status, tmp);
915 tmp = fd_close(fsp);
916 status = ntstatus_keeperror(status, tmp);
918 /* check for magic scripts */
919 if (close_type == NORMAL_CLOSE) {
920 tmp = check_magic(fsp);
921 status = ntstatus_keeperror(status, tmp);
924 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
925 conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
926 conn->num_files_open - 1,
927 nt_errstr(status) ));
929 return status;
931 /****************************************************************************
932 Function used by reply_rmdir to delete an entire directory
933 tree recursively. Return True on ok, False on fail.
934 ****************************************************************************/
936 NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
937 connection_struct *conn,
938 struct smb_filename *smb_dname)
940 const char *dname = NULL;
941 char *talloced = NULL;
942 struct smb_Dir *dir_hnd = NULL;
943 struct files_struct *dirfsp = NULL;
944 int retval;
945 NTSTATUS status = NT_STATUS_OK;
947 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
949 status = OpenDir(talloc_tos(),
950 conn,
951 smb_dname,
952 NULL,
954 &dir_hnd);
955 if (!NT_STATUS_IS_OK(status)) {
956 return status;
959 dirfsp = dir_hnd_fetch_fsp(dir_hnd);
961 while ((dname = ReadDirName(dir_hnd, &talloced))) {
962 struct smb_filename *atname = NULL;
963 struct smb_filename *smb_dname_full = NULL;
964 char *fullname = NULL;
965 bool do_break = true;
966 int unlink_flags = 0;
968 if (ISDOT(dname) || ISDOTDOT(dname)) {
969 TALLOC_FREE(talloced);
970 continue;
973 /* Construct the full name. */
974 fullname = talloc_asprintf(ctx,
975 "%s/%s",
976 smb_dname->base_name,
977 dname);
978 if (!fullname) {
979 status = NT_STATUS_NO_MEMORY;
980 goto err_break;
983 smb_dname_full = synthetic_smb_fname(talloc_tos(),
984 fullname,
985 NULL,
986 NULL,
987 smb_dname->twrp,
988 smb_dname->flags);
989 if (smb_dname_full == NULL) {
990 status = NT_STATUS_NO_MEMORY;
991 goto err_break;
994 if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
995 status = map_nt_error_from_unix(errno);
996 goto err_break;
999 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1000 status = recursive_rmdir(ctx, conn, smb_dname_full);
1001 if (!NT_STATUS_IS_OK(status)) {
1002 goto err_break;
1004 unlink_flags = AT_REMOVEDIR;
1007 status = synthetic_pathref(talloc_tos(),
1008 dirfsp,
1009 dname,
1010 NULL,
1011 &smb_dname_full->st,
1012 smb_dname_full->twrp,
1013 smb_dname_full->flags,
1014 &atname);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 goto err_break;
1019 if (!is_visible_fsp(atname->fsp)) {
1020 TALLOC_FREE(smb_dname_full);
1021 TALLOC_FREE(fullname);
1022 TALLOC_FREE(talloced);
1023 TALLOC_FREE(atname);
1024 continue;
1027 retval = SMB_VFS_UNLINKAT(conn,
1028 dirfsp,
1029 atname,
1030 unlink_flags);
1031 if (retval != 0) {
1032 status = map_nt_error_from_unix(errno);
1033 goto err_break;
1036 /* Successful iteration. */
1037 do_break = false;
1039 err_break:
1040 TALLOC_FREE(smb_dname_full);
1041 TALLOC_FREE(fullname);
1042 TALLOC_FREE(talloced);
1043 TALLOC_FREE(atname);
1044 if (do_break) {
1045 break;
1048 TALLOC_FREE(dir_hnd);
1049 return status;
1052 /****************************************************************************
1053 The internals of the rmdir code - called elsewhere.
1054 ****************************************************************************/
1056 static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
1058 struct connection_struct *conn = fsp->conn;
1059 struct smb_filename *smb_dname = fsp->fsp_name;
1060 struct smb_filename *parent_fname = NULL;
1061 struct smb_filename *at_fname = NULL;
1062 const char *dname = NULL;
1063 char *talloced = NULL;
1064 struct smb_Dir *dir_hnd = NULL;
1065 struct files_struct *dirfsp = NULL;
1066 int unlink_flags = 0;
1067 NTSTATUS status;
1068 int ret;
1070 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
1072 status = parent_pathref(talloc_tos(),
1073 conn->cwd_fsp,
1074 fsp->fsp_name,
1075 &parent_fname,
1076 &at_fname);
1077 if (!NT_STATUS_IS_OK(status)) {
1078 return status;
1082 * Todo: use SMB_VFS_STATX() once it's available.
1085 /* Might be a symlink. */
1086 ret = SMB_VFS_LSTAT(conn, smb_dname);
1087 if (ret != 0) {
1088 TALLOC_FREE(parent_fname);
1089 return map_nt_error_from_unix(errno);
1092 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
1093 /* Is what it points to a directory ? */
1094 ret = SMB_VFS_STAT(conn, smb_dname);
1095 if (ret != 0) {
1096 TALLOC_FREE(parent_fname);
1097 return map_nt_error_from_unix(errno);
1099 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
1100 TALLOC_FREE(parent_fname);
1101 return NT_STATUS_NOT_A_DIRECTORY;
1103 } else {
1104 unlink_flags = AT_REMOVEDIR;
1107 ret = SMB_VFS_UNLINKAT(conn,
1108 parent_fname->fsp,
1109 at_fname,
1110 unlink_flags);
1111 if (ret == 0) {
1112 TALLOC_FREE(parent_fname);
1113 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1114 FILE_NOTIFY_CHANGE_DIR_NAME,
1115 smb_dname->base_name);
1116 return NT_STATUS_OK;
1119 if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1120 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1121 "%s\n", smb_fname_str_dbg(smb_dname),
1122 strerror(errno)));
1123 TALLOC_FREE(parent_fname);
1124 return map_nt_error_from_unix(errno);
1128 * Here we know the initial directory unlink failed with
1129 * ENOTEMPTY or EEXIST so we know there are objects within.
1130 * If we don't have permission to delete files non
1131 * visible to the client just fail the directory delete.
1134 if (!lp_delete_veto_files(SNUM(conn))) {
1135 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1136 goto err;
1140 * Check to see if the only thing in this directory are
1141 * files non-visible to the client. If not, fail the delete.
1144 status = OpenDir(talloc_tos(),
1145 conn,
1146 smb_dname,
1147 NULL,
1149 &dir_hnd);
1150 if (!NT_STATUS_IS_OK(status)) {
1152 * Note, we deliberately squash the error here
1153 * to avoid leaking information about what we
1154 * can't delete.
1156 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1157 goto err;
1160 dirfsp = dir_hnd_fetch_fsp(dir_hnd);
1162 while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
1163 struct smb_filename *smb_dname_full = NULL;
1164 struct smb_filename *direntry_fname = NULL;
1165 char *fullname = NULL;
1166 int retval;
1168 if (ISDOT(dname) || ISDOTDOT(dname)) {
1169 TALLOC_FREE(talloced);
1170 continue;
1172 if (IS_VETO_PATH(conn, dname)) {
1173 TALLOC_FREE(talloced);
1174 continue;
1177 fullname = talloc_asprintf(talloc_tos(),
1178 "%s/%s",
1179 smb_dname->base_name,
1180 dname);
1182 if (fullname == NULL) {
1183 TALLOC_FREE(talloced);
1184 status = NT_STATUS_NO_MEMORY;
1185 goto err;
1188 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1189 fullname,
1190 NULL,
1191 NULL,
1192 smb_dname->twrp,
1193 smb_dname->flags);
1194 if (smb_dname_full == NULL) {
1195 TALLOC_FREE(talloced);
1196 TALLOC_FREE(fullname);
1197 status = NT_STATUS_NO_MEMORY;
1198 goto err;
1201 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1202 if (retval != 0) {
1203 status = map_nt_error_from_unix(errno);
1204 TALLOC_FREE(talloced);
1205 TALLOC_FREE(fullname);
1206 TALLOC_FREE(smb_dname_full);
1207 goto err;
1210 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1211 /* Could it be an msdfs link ? */
1212 if (lp_host_msdfs() &&
1213 lp_msdfs_root(SNUM(conn))) {
1214 struct smb_filename *smb_atname;
1215 smb_atname = synthetic_smb_fname(talloc_tos(),
1216 dname,
1217 NULL,
1218 &smb_dname_full->st,
1219 fsp->fsp_name->twrp,
1220 fsp->fsp_name->flags);
1221 if (smb_atname == NULL) {
1222 TALLOC_FREE(talloced);
1223 TALLOC_FREE(fullname);
1224 TALLOC_FREE(smb_dname_full);
1225 status = NT_STATUS_NO_MEMORY;
1226 goto err;
1228 if (is_msdfs_link(fsp, smb_atname)) {
1229 TALLOC_FREE(talloced);
1230 TALLOC_FREE(fullname);
1231 TALLOC_FREE(smb_dname_full);
1232 TALLOC_FREE(smb_atname);
1233 DBG_DEBUG("got msdfs link name %s "
1234 "- can't delete directory %s\n",
1235 dname,
1236 fsp_str_dbg(fsp));
1237 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1238 goto err;
1240 TALLOC_FREE(smb_atname);
1243 /* Not a DFS link - could it be a dangling symlink ? */
1244 retval = SMB_VFS_STAT(conn, smb_dname_full);
1245 if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
1247 * Dangling symlink.
1248 * Allow delete as "delete veto files = yes"
1250 TALLOC_FREE(talloced);
1251 TALLOC_FREE(fullname);
1252 TALLOC_FREE(smb_dname_full);
1253 continue;
1256 DBG_DEBUG("got symlink name %s - "
1257 "can't delete directory %s\n",
1258 dname,
1259 fsp_str_dbg(fsp));
1260 TALLOC_FREE(talloced);
1261 TALLOC_FREE(fullname);
1262 TALLOC_FREE(smb_dname_full);
1263 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1264 goto err;
1267 /* Not a symlink, get a pathref. */
1268 status = synthetic_pathref(talloc_tos(),
1269 dirfsp,
1270 dname,
1271 NULL,
1272 &smb_dname_full->st,
1273 smb_dname->twrp,
1274 smb_dname->flags,
1275 &direntry_fname);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 TALLOC_FREE(talloced);
1278 TALLOC_FREE(fullname);
1279 TALLOC_FREE(smb_dname_full);
1280 goto err;
1283 if (!is_visible_fsp(direntry_fname->fsp)) {
1284 TALLOC_FREE(talloced);
1285 TALLOC_FREE(fullname);
1286 TALLOC_FREE(smb_dname_full);
1287 TALLOC_FREE(direntry_fname);
1288 continue;
1292 * We found a client visible name.
1293 * We cannot delete this directory.
1295 DBG_DEBUG("got name %s - "
1296 "can't delete directory %s\n",
1297 dname,
1298 fsp_str_dbg(fsp));
1299 TALLOC_FREE(talloced);
1300 TALLOC_FREE(fullname);
1301 TALLOC_FREE(smb_dname_full);
1302 TALLOC_FREE(direntry_fname);
1303 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1304 goto err;
1307 /* Do a recursive delete. */
1308 RewindDir(dir_hnd);
1310 while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
1311 struct smb_filename *direntry_fname = NULL;
1312 struct smb_filename *smb_dname_full = NULL;
1313 char *fullname = NULL;
1314 bool do_break = true;
1315 int retval;
1317 if (ISDOT(dname) || ISDOTDOT(dname)) {
1318 TALLOC_FREE(talloced);
1319 continue;
1322 fullname = talloc_asprintf(ctx,
1323 "%s/%s",
1324 smb_dname->base_name,
1325 dname);
1327 if (fullname == NULL) {
1328 status = NT_STATUS_NO_MEMORY;
1329 goto err_break;
1332 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1333 fullname,
1334 NULL,
1335 NULL,
1336 smb_dname->twrp,
1337 smb_dname->flags);
1338 if (smb_dname_full == NULL) {
1339 status = NT_STATUS_NO_MEMORY;
1340 goto err_break;
1344 * Todo: use SMB_VFS_STATX() once that's available.
1347 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1348 if (retval != 0) {
1349 status = map_nt_error_from_unix(errno);
1350 goto err_break;
1354 * We are only dealing with VETO'ed objects
1355 * here. If it's a symlink, just delete the
1356 * link without caring what it is pointing
1357 * to.
1359 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1360 direntry_fname = synthetic_smb_fname(talloc_tos(),
1361 dname,
1362 NULL,
1363 &smb_dname_full->st,
1364 smb_dname->twrp,
1365 smb_dname->flags);
1366 if (direntry_fname == NULL) {
1367 status = NT_STATUS_NO_MEMORY;
1368 goto err_break;
1370 } else {
1371 status = synthetic_pathref(talloc_tos(),
1372 dirfsp,
1373 dname,
1374 NULL,
1375 &smb_dname_full->st,
1376 smb_dname->twrp,
1377 smb_dname->flags,
1378 &direntry_fname);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 goto err_break;
1383 if (!is_visible_fsp(direntry_fname->fsp)) {
1384 TALLOC_FREE(fullname);
1385 TALLOC_FREE(smb_dname_full);
1386 TALLOC_FREE(talloced);
1387 TALLOC_FREE(direntry_fname);
1388 continue;
1392 unlink_flags = 0;
1394 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1395 status = recursive_rmdir(ctx, conn, smb_dname_full);
1396 if (!NT_STATUS_IS_OK(status)) {
1397 goto err_break;
1399 unlink_flags = AT_REMOVEDIR;
1402 retval = SMB_VFS_UNLINKAT(conn,
1403 dirfsp,
1404 direntry_fname,
1405 unlink_flags);
1406 if (retval != 0) {
1407 status = map_nt_error_from_unix(errno);
1408 goto err_break;
1411 /* Successful iteration. */
1412 do_break = false;
1414 err_break:
1415 TALLOC_FREE(fullname);
1416 TALLOC_FREE(smb_dname_full);
1417 TALLOC_FREE(talloced);
1418 TALLOC_FREE(direntry_fname);
1419 if (do_break) {
1420 break;
1424 /* If we get here, we know NT_STATUS_IS_OK(status) */
1425 SMB_ASSERT(NT_STATUS_IS_OK(status));
1427 /* Retry the rmdir */
1428 ret = SMB_VFS_UNLINKAT(conn,
1429 parent_fname->fsp,
1430 at_fname,
1431 AT_REMOVEDIR);
1432 if (ret != 0) {
1433 status = map_nt_error_from_unix(errno);
1436 err:
1438 TALLOC_FREE(dir_hnd);
1439 TALLOC_FREE(parent_fname);
1441 if (!NT_STATUS_IS_OK(status)) {
1442 DBG_NOTICE("couldn't remove directory %s : "
1443 "%s\n", smb_fname_str_dbg(smb_dname),
1444 nt_errstr(status));
1445 return status;
1448 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1449 FILE_NOTIFY_CHANGE_DIR_NAME,
1450 smb_dname->base_name);
1452 return status;
1455 /****************************************************************************
1456 Close a directory opened by an NT SMB call.
1457 ****************************************************************************/
1459 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1460 enum file_close_type close_type)
1462 connection_struct *conn = fsp->conn;
1463 struct close_share_mode_lock_state lck_state = {};
1464 bool changed_user = false;
1465 NTSTATUS status = NT_STATUS_OK;
1466 NTSTATUS status1 = NT_STATUS_OK;
1467 NTSTATUS notify_status;
1468 NTSTATUS ulstatus;
1470 SMB_ASSERT(fsp->fsp_flags.is_fsa);
1472 if (conn_using_smb2(fsp->conn->sconn)) {
1473 notify_status = NT_STATUS_NOTIFY_CLEANUP;
1474 } else {
1475 notify_status = NT_STATUS_OK;
1478 assert_no_pending_aio(fsp, close_type);
1481 * NT can set delete_on_close of the last open
1482 * reference to a directory also.
1485 lck_state = (struct close_share_mode_lock_state) {
1486 .fsp = fsp,
1487 .object_type = "directory",
1488 .close_type = close_type,
1491 status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
1492 fsp->file_id,
1493 close_share_mode_lock_prepare,
1494 &lck_state);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
1497 fsp_str_dbg(fsp), nt_errstr(status));
1498 return status;
1502 * We don't have directory leases yet, so assert it in order
1503 * to skip release_file_oplock().
1505 SMB_ASSERT(fsp->oplock_type == NO_OPLOCK);
1508 * NT can set delete_on_close of the last open
1509 * reference to a file.
1512 if (!lck_state.delete_object) {
1513 status = NT_STATUS_OK;
1514 goto done;
1518 * Ok, we have to delete the directory
1520 lck_state.cleanup_fn = close_share_mode_lock_cleanup;
1522 if (lck_state.got_tokens &&
1523 !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
1525 /* Become the user who requested the delete. */
1527 DBG_INFO("dir %s. Change user to uid %u\n",
1528 fsp_str_dbg(fsp),
1529 (unsigned int)lck_state.del_token->uid);
1531 if (!push_sec_ctx()) {
1532 smb_panic("close_directory: failed to push sec_ctx.\n");
1535 set_sec_ctx(lck_state.del_token->uid,
1536 lck_state.del_token->gid,
1537 lck_state.del_token->ngroups,
1538 lck_state.del_token->groups,
1539 lck_state.del_nt_token);
1541 changed_user = true;
1544 if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1545 && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1547 status = delete_all_streams(fsp->conn, fsp->fsp_name);
1548 if (!NT_STATUS_IS_OK(status)) {
1549 DEBUG(5, ("delete_all_streams failed: %s\n",
1550 nt_errstr(status)));
1551 goto done;
1555 status = rmdir_internals(talloc_tos(), fsp);
1557 DEBUG(5,("close_directory: %s. Delete on close was set - "
1558 "deleting directory returned %s.\n",
1559 fsp_str_dbg(fsp), nt_errstr(status)));
1562 * Ensure we remove any change notify requests that would
1563 * now fail as the directory has been deleted.
1566 if (NT_STATUS_IS_OK(status)) {
1567 notify_status = NT_STATUS_DELETE_PENDING;
1570 done:
1571 if (changed_user) {
1572 /* unbecome user. */
1573 pop_sec_ctx();
1576 ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
1577 lck_state.cleanup_fn,
1578 &lck_state);
1579 if (!NT_STATUS_IS_OK(ulstatus)) {
1580 DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
1581 fsp_str_dbg(fsp), nt_errstr(ulstatus));
1582 smb_panic("share_mode_entry_prepare_unlock() failed!");
1585 remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1587 status1 = fd_close(fsp);
1589 if (!NT_STATUS_IS_OK(status1)) {
1590 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1591 fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1592 strerror(errno)));
1595 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1596 status = status1;
1598 return status;
1601 /****************************************************************************
1602 Rundown all SMB-related dependencies of a files struct
1603 ****************************************************************************/
1605 NTSTATUS close_file_smb(struct smb_request *req,
1606 struct files_struct *fsp,
1607 enum file_close_type close_type)
1609 NTSTATUS status;
1612 * This fsp can never be an internal dirfsp. They must
1613 * be explicitly closed by TALLOC_FREE of the dir handle.
1615 SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1618 * Never call directly on a base fsp
1620 SMB_ASSERT(fsp->stream_fsp == NULL);
1622 if (fsp->fake_file_handle != NULL) {
1624 * Named pipes are opened as fake files and
1625 * can have pending aio requests. Ensure
1626 * we clear out all pending aio on force
1627 * shutdown of named pipes also.
1628 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15423
1630 assert_no_pending_aio(fsp, close_type);
1631 status = close_fake_file(req, fsp);
1632 } else if (fsp->print_file != NULL) {
1633 /* FIXME: return spool errors */
1634 print_spool_end(fsp, close_type);
1635 fd_close(fsp);
1636 status = NT_STATUS_OK;
1637 } else if (!fsp->fsp_flags.is_fsa) {
1638 if (close_type == NORMAL_CLOSE) {
1639 DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1640 "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1641 fsp_str_dbg(fsp),
1642 fsp->fsp_flags.is_fsa,
1643 fsp->fsp_flags.is_pathref,
1644 fsp->fsp_flags.is_directory);
1646 SMB_ASSERT(close_type != NORMAL_CLOSE);
1647 fd_close(fsp);
1648 status = NT_STATUS_OK;
1649 } else if (fsp->fsp_flags.is_directory) {
1650 status = close_directory(req, fsp, close_type);
1651 } else {
1652 status = close_normal_file(req, fsp, close_type);
1655 if (fsp_is_alternate_stream(fsp)) {
1657 * fsp was a stream, its base_fsp can't be a stream
1658 * as well
1660 SMB_ASSERT(!fsp_is_alternate_stream(fsp->base_fsp));
1663 * There's a 1:1 relationship between fsp and a base_fsp
1665 SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1668 * Make base_fsp look standalone now
1670 fsp->base_fsp->stream_fsp = NULL;
1672 close_file_free(req, &fsp->base_fsp, close_type);
1675 fsp_unbind_smb(req, fsp);
1677 return status;
1680 NTSTATUS close_file_free(struct smb_request *req,
1681 struct files_struct **_fsp,
1682 enum file_close_type close_type)
1684 struct files_struct *fsp = *_fsp;
1685 NTSTATUS status;
1687 status = close_file_smb(req, fsp, close_type);
1689 file_free(req, fsp);
1690 *_fsp = NULL;
1692 return status;
1695 /****************************************************************************
1696 Deal with an (authorized) message to close a file given the share mode
1697 entry.
1698 ****************************************************************************/
1700 void msg_close_file(struct messaging_context *msg_ctx,
1701 void *private_data,
1702 uint32_t msg_type,
1703 struct server_id server_id,
1704 DATA_BLOB *data)
1706 struct oplock_break_message msg;
1707 enum ndr_err_code ndr_err;
1708 files_struct *fsp = NULL;
1709 struct smbd_server_connection *sconn =
1710 talloc_get_type_abort(private_data,
1711 struct smbd_server_connection);
1713 ndr_err = ndr_pull_struct_blob_all_noalloc(
1714 data,
1715 &msg,
1716 (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
1717 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1718 DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
1719 ndr_errstr(ndr_err));
1720 return;
1723 fsp = file_find_dif(sconn, msg.id, msg.share_file_id);
1724 if (!fsp) {
1725 DEBUG(10,("msg_close_file: failed to find file.\n"));
1726 return;
1728 close_file_free(NULL, &fsp, NORMAL_CLOSE);