smbXsrv_session: Remove a "can't happen" NULL check
[Samba.git] / source3 / smbd / close.c
blobbbca474a28a06113ba7f269f9eb5465154a16b2a
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/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 DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
477 "- deleting file.\n", 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 DEBUG(5,("close_remove_share_mode: file %s. "
490 "Change user to uid %u\n",
491 fsp_str_dbg(fsp),
492 (unsigned int)lck_state.del_token->uid));
494 if (!push_sec_ctx()) {
495 smb_panic("close_remove_share_mode: file %s. failed to push "
496 "sec_ctx.\n");
499 set_sec_ctx(lck_state.del_token->uid,
500 lck_state.del_token->gid,
501 lck_state.del_token->ngroups,
502 lck_state.del_token->groups,
503 lck_state.del_nt_token);
505 changed_user = true;
508 /* We can only delete the file if the name we have is still valid and
509 hasn't been renamed. */
511 tmp_status = vfs_stat_fsp(fsp);
512 if (!NT_STATUS_IS_OK(tmp_status)) {
513 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
514 "was set and stat failed with error %s\n",
515 fsp_str_dbg(fsp), 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 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
527 "was set and dev and/or inode does not match\n",
528 fsp_str_dbg(fsp)));
529 DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
530 "stat file_id %s\n",
531 fsp_str_dbg(fsp),
532 file_id_str_buf(fsp->file_id, &ftmp1),
533 file_id_str_buf(id, &ftmp2)));
535 * Don't save the errno here, we ignore this error
537 goto done;
540 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
541 && !fsp_is_alternate_stream(fsp)) {
543 status = delete_all_streams(conn, fsp->fsp_name);
545 if (!NT_STATUS_IS_OK(status)) {
546 DEBUG(5, ("delete_all_streams failed: %s\n",
547 nt_errstr(status)));
548 goto done;
552 if (fsp->fsp_flags.kernel_share_modes_taken) {
554 * A file system sharemode could block the unlink;
555 * remove filesystem sharemodes first.
557 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
558 if (ret == -1) {
559 DBG_INFO("Removing file system sharemode for %s "
560 "failed: %s\n",
561 fsp_str_dbg(fsp), strerror(errno));
564 fsp->fsp_flags.kernel_share_modes_taken = false;
567 status = parent_pathref(talloc_tos(),
568 conn->cwd_fsp,
569 fsp->fsp_name,
570 &parent_fname,
571 &base_fname);
572 if (!NT_STATUS_IS_OK(status)) {
573 goto done;
576 ret = SMB_VFS_UNLINKAT(conn,
577 parent_fname->fsp,
578 base_fname,
580 TALLOC_FREE(parent_fname);
581 base_fname = NULL;
582 if (ret != 0) {
584 * This call can potentially fail as another smbd may
585 * have had the file open with delete on close set and
586 * deleted it when its last reference to this file
587 * went away. Hence we log this but not at debug level
588 * zero.
591 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
592 "was set and unlink failed with error %s\n",
593 fsp_str_dbg(fsp), 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) {
637 * Do the notification after we released the share
638 * mode lock. Inside notify_fname we take out another
639 * tdb lock. With ctdb also accessing our databases,
640 * this can lead to deadlocks. Putting this notify
641 * after the TALLOC_FREE(lck) above we avoid locking
642 * two records simultaneously. Notifies are async and
643 * informational only, so calling the notify_fname
644 * without holding the share mode lock should not do
645 * any harm.
647 notify_fname(conn, NOTIFY_ACTION_REMOVED,
648 FILE_NOTIFY_CHANGE_FILE_NAME,
649 fsp->fsp_name->base_name);
652 return status;
655 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
657 DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
659 if (is_omit_timespec(&ts)) {
660 return;
662 fsp->fsp_flags.write_time_forced = false;
663 fsp->fsp_flags.update_write_time_on_close = true;
664 fsp->close_write_time = ts;
667 static void update_write_time_on_close_share_mode_fn(struct share_mode_lock *lck,
668 void *private_data)
670 struct files_struct *fsp =
671 talloc_get_type_abort(private_data,
672 struct files_struct);
673 NTTIME share_mtime = share_mode_changed_write_time(lck);
676 * On close if we're changing the real file time we
677 * must update it in the open file db too.
679 share_mode_set_old_write_time(lck, fsp->close_write_time);
682 * Close write times overwrite sticky write times
683 * so we must replace any sticky write time here.
685 if (!null_nttime(share_mtime)) {
686 share_mode_set_changed_write_time(lck, fsp->close_write_time);
690 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
692 struct smb_file_time ft;
693 NTSTATUS status;
695 init_smb_file_time(&ft);
697 if (!(fsp->fsp_flags.update_write_time_on_close)) {
698 return NT_STATUS_OK;
701 if (is_omit_timespec(&fsp->close_write_time)) {
702 fsp->close_write_time = timespec_current();
705 /* Ensure we have a valid stat struct for the source. */
706 status = vfs_stat_fsp(fsp);
707 if (!NT_STATUS_IS_OK(status)) {
708 return status;
711 if (!VALID_STAT(fsp->fsp_name->st)) {
712 /* if it doesn't seem to be a real file */
713 return NT_STATUS_OK;
717 * We're being called after close_remove_share_mode() inside
718 * close_normal_file() so it's quite normal to not have an
719 * existing share. So just ignore the result of
720 * share_mode_do_locked_vfs_denied()...
722 share_mode_do_locked_vfs_denied(fsp->file_id,
723 update_write_time_on_close_share_mode_fn,
724 fsp);
726 ft.mtime = fsp->close_write_time;
727 /* As this is a close based update, we are not directly changing the
728 file attributes from a client call, but indirectly from a write. */
729 status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
730 if (!NT_STATUS_IS_OK(status)) {
731 DEBUG(10,("update_write_time_on_close: smb_set_file_time "
732 "on file %s returned %s\n",
733 fsp_str_dbg(fsp),
734 nt_errstr(status)));
735 return status;
738 return status;
741 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
743 if (!NT_STATUS_IS_OK(s1)) {
744 return s1;
746 return s2;
749 static void assert_no_pending_aio(struct files_struct *fsp,
750 enum file_close_type close_type)
752 struct smbXsrv_client *client = global_smbXsrv_client;
753 size_t num_connections_alive;
754 unsigned num_requests = fsp->num_aio_requests;
756 if (num_requests == 0) {
757 return;
760 num_connections_alive = smbXsrv_client_valid_connections(client);
762 if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
764 * fsp->aio_requests and the contents (fsp->aio_requests[x])
765 * are both independently owned by fsp and are not in a
766 * talloc hierarchy. This allows the fsp->aio_requests array to
767 * be reallocated independently of the array contents so it can
768 * grow on demand.
770 * This means we must ensure order of deallocation
771 * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
772 * contents first, as their destructors access the
773 * fsp->aio_request array. If we don't deallocate them
774 * first, when fsp is deallocated fsp->aio_requests
775 * could have been deallocated *before* its contents
776 * fsp->aio_requests[x], causing a crash.
778 while (fsp->num_aio_requests != 0) {
780 * NB. We *MUST* use
781 * talloc_free(fsp->aio_requests[0]),
782 * and *NOT* TALLOC_FREE() here, as
783 * TALLOC_FREE(fsp->aio_requests[0])
784 * will overwrite any new contents of
785 * fsp->aio_requests[0] that were
786 * copied into it via the destructor
787 * aio_del_req_from_fsp().
789 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
791 talloc_free(fsp->aio_requests[0]);
793 return;
796 DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
797 smb_panic("can not close with outstanding aio requests");
798 return;
801 /****************************************************************************
802 Close a file.
804 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
805 printing and magic scripts are only run on normal close.
806 delete on close is done on normal and shutdown close.
807 ****************************************************************************/
809 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
810 enum file_close_type close_type)
812 NTSTATUS status = NT_STATUS_OK;
813 NTSTATUS tmp;
814 connection_struct *conn = fsp->conn;
815 bool is_durable = false;
817 SMB_ASSERT(fsp->fsp_flags.is_fsa);
819 assert_no_pending_aio(fsp, close_type);
821 while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
822 smbd_smb1_brl_finish_by_req(
823 fsp->blocked_smb1_lock_reqs[0],
824 NT_STATUS_RANGE_NOT_LOCKED);
828 * If we're flushing on a close we can get a write
829 * error here, we must remember this.
832 if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
833 is_durable = fsp->op->global->durable;
836 if (close_type != SHUTDOWN_CLOSE) {
837 is_durable = false;
840 if (is_durable) {
841 DATA_BLOB new_cookie = data_blob_null;
843 tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
844 fsp->op->global->backend_cookie,
845 fsp->op,
846 &new_cookie);
847 if (NT_STATUS_IS_OK(tmp)) {
848 struct timeval tv;
849 NTTIME now;
851 if (req != NULL) {
852 tv = req->request_time;
853 } else {
854 tv = timeval_current();
856 now = timeval_to_nttime(&tv);
858 data_blob_free(&fsp->op->global->backend_cookie);
859 fsp->op->global->backend_cookie = new_cookie;
861 fsp->op->compat = NULL;
862 tmp = smbXsrv_open_close(fsp->op, now);
863 if (!NT_STATUS_IS_OK(tmp)) {
864 DEBUG(1, ("Failed to update smbXsrv_open "
865 "record when disconnecting durable "
866 "handle for file %s: %s - "
867 "proceeding with normal close\n",
868 fsp_str_dbg(fsp), nt_errstr(tmp)));
870 scavenger_schedule_disconnected(fsp);
871 } else {
872 DEBUG(1, ("Failed to disconnect durable handle for "
873 "file %s: %s - proceeding with normal "
874 "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
876 if (!NT_STATUS_IS_OK(tmp)) {
877 is_durable = false;
881 if (is_durable) {
883 * This is the case where we successfully disconnected
884 * a durable handle and closed the underlying file.
885 * In all other cases, we proceed with a genuine close.
887 DEBUG(10, ("%s disconnected durable handle for file %s\n",
888 conn->session_info->unix_info->unix_name,
889 fsp_str_dbg(fsp)));
890 return NT_STATUS_OK;
893 if (fsp->op != NULL) {
895 * Make sure the handle is not marked as durable anymore
897 fsp->op->global->durable = false;
900 /* If this is an old DOS or FCB open and we have multiple opens on
901 the same handle we only have one share mode. Ensure we only remove
902 the share mode on the last close. */
904 if (fh_get_refcount(fsp->fh) == 1) {
905 /* Should we return on error here... ? */
906 tmp = close_remove_share_mode(fsp, close_type);
907 status = ntstatus_keeperror(status, tmp);
910 locking_close_file(fsp, close_type);
913 * Ensure pending modtime is set before closing underlying fd.
916 tmp = update_write_time_on_close(fsp);
917 if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
919 * Someone renamed the file or a parent directory containing
920 * this file. We can't do anything about this, eat the error.
922 tmp = NT_STATUS_OK;
924 status = ntstatus_keeperror(status, tmp);
926 tmp = fd_close(fsp);
927 status = ntstatus_keeperror(status, tmp);
929 /* check for magic scripts */
930 if (close_type == NORMAL_CLOSE) {
931 tmp = check_magic(fsp);
932 status = ntstatus_keeperror(status, tmp);
935 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
936 conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
937 conn->num_files_open - 1,
938 nt_errstr(status) ));
940 return status;
942 /****************************************************************************
943 Function used by reply_rmdir to delete an entire directory
944 tree recursively. Return True on ok, False on fail.
945 ****************************************************************************/
947 NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
948 connection_struct *conn,
949 struct smb_filename *smb_dname)
951 const char *dname = NULL;
952 char *talloced = NULL;
953 struct smb_Dir *dir_hnd = NULL;
954 struct files_struct *dirfsp = NULL;
955 int retval;
956 NTSTATUS status = NT_STATUS_OK;
958 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
960 status = OpenDir(talloc_tos(),
961 conn,
962 smb_dname,
963 NULL,
965 &dir_hnd);
966 if (!NT_STATUS_IS_OK(status)) {
967 return status;
970 dirfsp = dir_hnd_fetch_fsp(dir_hnd);
972 while ((dname = ReadDirName(dir_hnd, &talloced))) {
973 struct smb_filename *atname = NULL;
974 struct smb_filename *smb_dname_full = NULL;
975 char *fullname = NULL;
976 bool do_break = true;
977 int unlink_flags = 0;
979 if (ISDOT(dname) || ISDOTDOT(dname)) {
980 TALLOC_FREE(talloced);
981 continue;
984 /* Construct the full name. */
985 fullname = talloc_asprintf(ctx,
986 "%s/%s",
987 smb_dname->base_name,
988 dname);
989 if (!fullname) {
990 status = NT_STATUS_NO_MEMORY;
991 goto err_break;
994 smb_dname_full = synthetic_smb_fname(talloc_tos(),
995 fullname,
996 NULL,
997 NULL,
998 smb_dname->twrp,
999 smb_dname->flags);
1000 if (smb_dname_full == NULL) {
1001 status = NT_STATUS_NO_MEMORY;
1002 goto err_break;
1005 if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
1006 status = map_nt_error_from_unix(errno);
1007 goto err_break;
1010 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1011 status = recursive_rmdir(ctx, conn, smb_dname_full);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 goto err_break;
1015 unlink_flags = AT_REMOVEDIR;
1018 status = synthetic_pathref(talloc_tos(),
1019 dirfsp,
1020 dname,
1021 NULL,
1022 &smb_dname_full->st,
1023 smb_dname_full->twrp,
1024 smb_dname_full->flags,
1025 &atname);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 goto err_break;
1030 if (!is_visible_fsp(atname->fsp)) {
1031 TALLOC_FREE(smb_dname_full);
1032 TALLOC_FREE(fullname);
1033 TALLOC_FREE(talloced);
1034 TALLOC_FREE(atname);
1035 continue;
1038 retval = SMB_VFS_UNLINKAT(conn,
1039 dirfsp,
1040 atname,
1041 unlink_flags);
1042 if (retval != 0) {
1043 status = map_nt_error_from_unix(errno);
1044 goto err_break;
1047 /* Successful iteration. */
1048 do_break = false;
1050 err_break:
1051 TALLOC_FREE(smb_dname_full);
1052 TALLOC_FREE(fullname);
1053 TALLOC_FREE(talloced);
1054 TALLOC_FREE(atname);
1055 if (do_break) {
1056 break;
1059 TALLOC_FREE(dir_hnd);
1060 return status;
1063 /****************************************************************************
1064 The internals of the rmdir code - called elsewhere.
1065 ****************************************************************************/
1067 static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
1069 struct connection_struct *conn = fsp->conn;
1070 struct smb_filename *smb_dname = fsp->fsp_name;
1071 struct smb_filename *parent_fname = NULL;
1072 struct smb_filename *at_fname = NULL;
1073 const char *dname = NULL;
1074 char *talloced = NULL;
1075 struct smb_Dir *dir_hnd = NULL;
1076 struct files_struct *dirfsp = NULL;
1077 int unlink_flags = 0;
1078 NTSTATUS status;
1079 int ret;
1081 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
1083 status = parent_pathref(talloc_tos(),
1084 conn->cwd_fsp,
1085 fsp->fsp_name,
1086 &parent_fname,
1087 &at_fname);
1088 if (!NT_STATUS_IS_OK(status)) {
1089 return status;
1093 * Todo: use SMB_VFS_STATX() once it's available.
1096 /* Might be a symlink. */
1097 ret = SMB_VFS_LSTAT(conn, smb_dname);
1098 if (ret != 0) {
1099 TALLOC_FREE(parent_fname);
1100 return map_nt_error_from_unix(errno);
1103 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
1104 /* Is what it points to a directory ? */
1105 ret = SMB_VFS_STAT(conn, smb_dname);
1106 if (ret != 0) {
1107 TALLOC_FREE(parent_fname);
1108 return map_nt_error_from_unix(errno);
1110 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
1111 TALLOC_FREE(parent_fname);
1112 return NT_STATUS_NOT_A_DIRECTORY;
1114 } else {
1115 unlink_flags = AT_REMOVEDIR;
1118 ret = SMB_VFS_UNLINKAT(conn,
1119 parent_fname->fsp,
1120 at_fname,
1121 unlink_flags);
1122 if (ret == 0) {
1123 TALLOC_FREE(parent_fname);
1124 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1125 FILE_NOTIFY_CHANGE_DIR_NAME,
1126 smb_dname->base_name);
1127 return NT_STATUS_OK;
1130 if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1131 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1132 "%s\n", smb_fname_str_dbg(smb_dname),
1133 strerror(errno)));
1134 TALLOC_FREE(parent_fname);
1135 return map_nt_error_from_unix(errno);
1139 * Here we know the initial directory unlink failed with
1140 * ENOTEMPTY or EEXIST so we know there are objects within.
1141 * If we don't have permission to delete files non
1142 * visible to the client just fail the directory delete.
1145 if (!lp_delete_veto_files(SNUM(conn))) {
1146 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1147 goto err;
1151 * Check to see if the only thing in this directory are
1152 * files non-visible to the client. If not, fail the delete.
1155 status = OpenDir(talloc_tos(),
1156 conn,
1157 smb_dname,
1158 NULL,
1160 &dir_hnd);
1161 if (!NT_STATUS_IS_OK(status)) {
1163 * Note, we deliberately squash the error here
1164 * to avoid leaking information about what we
1165 * can't delete.
1167 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1168 goto err;
1171 dirfsp = dir_hnd_fetch_fsp(dir_hnd);
1173 while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
1174 struct smb_filename *smb_dname_full = NULL;
1175 struct smb_filename *direntry_fname = NULL;
1176 char *fullname = NULL;
1177 int retval;
1179 if (ISDOT(dname) || ISDOTDOT(dname)) {
1180 TALLOC_FREE(talloced);
1181 continue;
1183 if (IS_VETO_PATH(conn, dname)) {
1184 TALLOC_FREE(talloced);
1185 continue;
1188 fullname = talloc_asprintf(talloc_tos(),
1189 "%s/%s",
1190 smb_dname->base_name,
1191 dname);
1193 if (fullname == NULL) {
1194 TALLOC_FREE(talloced);
1195 status = NT_STATUS_NO_MEMORY;
1196 goto err;
1199 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1200 fullname,
1201 NULL,
1202 NULL,
1203 smb_dname->twrp,
1204 smb_dname->flags);
1205 if (smb_dname_full == NULL) {
1206 TALLOC_FREE(talloced);
1207 TALLOC_FREE(fullname);
1208 status = NT_STATUS_NO_MEMORY;
1209 goto err;
1212 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1213 if (retval != 0) {
1214 status = map_nt_error_from_unix(errno);
1215 TALLOC_FREE(talloced);
1216 TALLOC_FREE(fullname);
1217 TALLOC_FREE(smb_dname_full);
1218 goto err;
1221 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1222 /* Could it be an msdfs link ? */
1223 if (lp_host_msdfs() &&
1224 lp_msdfs_root(SNUM(conn))) {
1225 struct smb_filename *smb_atname;
1226 smb_atname = synthetic_smb_fname(talloc_tos(),
1227 dname,
1228 NULL,
1229 &smb_dname_full->st,
1230 fsp->fsp_name->twrp,
1231 fsp->fsp_name->flags);
1232 if (smb_atname == NULL) {
1233 TALLOC_FREE(talloced);
1234 TALLOC_FREE(fullname);
1235 TALLOC_FREE(smb_dname_full);
1236 status = NT_STATUS_NO_MEMORY;
1237 goto err;
1239 if (is_msdfs_link(fsp, smb_atname)) {
1240 TALLOC_FREE(talloced);
1241 TALLOC_FREE(fullname);
1242 TALLOC_FREE(smb_dname_full);
1243 TALLOC_FREE(smb_atname);
1244 DBG_DEBUG("got msdfs link name %s "
1245 "- can't delete directory %s\n",
1246 dname,
1247 fsp_str_dbg(fsp));
1248 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1249 goto err;
1251 TALLOC_FREE(smb_atname);
1254 /* Not a DFS link - could it be a dangling symlink ? */
1255 retval = SMB_VFS_STAT(conn, smb_dname_full);
1256 if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
1258 * Dangling symlink.
1259 * Allow delete as "delete veto files = yes"
1261 TALLOC_FREE(talloced);
1262 TALLOC_FREE(fullname);
1263 TALLOC_FREE(smb_dname_full);
1264 continue;
1267 DBG_DEBUG("got symlink name %s - "
1268 "can't delete directory %s\n",
1269 dname,
1270 fsp_str_dbg(fsp));
1271 TALLOC_FREE(talloced);
1272 TALLOC_FREE(fullname);
1273 TALLOC_FREE(smb_dname_full);
1274 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1275 goto err;
1278 /* Not a symlink, get a pathref. */
1279 status = synthetic_pathref(talloc_tos(),
1280 dirfsp,
1281 dname,
1282 NULL,
1283 &smb_dname_full->st,
1284 smb_dname->twrp,
1285 smb_dname->flags,
1286 &direntry_fname);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 TALLOC_FREE(talloced);
1289 TALLOC_FREE(fullname);
1290 TALLOC_FREE(smb_dname_full);
1291 goto err;
1294 if (!is_visible_fsp(direntry_fname->fsp)) {
1295 TALLOC_FREE(talloced);
1296 TALLOC_FREE(fullname);
1297 TALLOC_FREE(smb_dname_full);
1298 TALLOC_FREE(direntry_fname);
1299 continue;
1303 * We found a client visible name.
1304 * We cannot delete this directory.
1306 DBG_DEBUG("got name %s - "
1307 "can't delete directory %s\n",
1308 dname,
1309 fsp_str_dbg(fsp));
1310 TALLOC_FREE(talloced);
1311 TALLOC_FREE(fullname);
1312 TALLOC_FREE(smb_dname_full);
1313 TALLOC_FREE(direntry_fname);
1314 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1315 goto err;
1318 /* Do a recursive delete. */
1319 RewindDir(dir_hnd);
1321 while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
1322 struct smb_filename *direntry_fname = NULL;
1323 struct smb_filename *smb_dname_full = NULL;
1324 char *fullname = NULL;
1325 bool do_break = true;
1326 int retval;
1328 if (ISDOT(dname) || ISDOTDOT(dname)) {
1329 TALLOC_FREE(talloced);
1330 continue;
1333 fullname = talloc_asprintf(ctx,
1334 "%s/%s",
1335 smb_dname->base_name,
1336 dname);
1338 if (fullname == NULL) {
1339 status = NT_STATUS_NO_MEMORY;
1340 goto err_break;
1343 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1344 fullname,
1345 NULL,
1346 NULL,
1347 smb_dname->twrp,
1348 smb_dname->flags);
1349 if (smb_dname_full == NULL) {
1350 status = NT_STATUS_NO_MEMORY;
1351 goto err_break;
1355 * Todo: use SMB_VFS_STATX() once that's available.
1358 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1359 if (retval != 0) {
1360 status = map_nt_error_from_unix(errno);
1361 goto err_break;
1365 * We are only dealing with VETO'ed objects
1366 * here. If it's a symlink, just delete the
1367 * link without caring what it is pointing
1368 * to.
1370 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1371 direntry_fname = synthetic_smb_fname(talloc_tos(),
1372 dname,
1373 NULL,
1374 &smb_dname_full->st,
1375 smb_dname->twrp,
1376 smb_dname->flags);
1377 if (direntry_fname == NULL) {
1378 status = NT_STATUS_NO_MEMORY;
1379 goto err_break;
1381 } else {
1382 status = synthetic_pathref(talloc_tos(),
1383 dirfsp,
1384 dname,
1385 NULL,
1386 &smb_dname_full->st,
1387 smb_dname->twrp,
1388 smb_dname->flags,
1389 &direntry_fname);
1390 if (!NT_STATUS_IS_OK(status)) {
1391 goto err_break;
1394 if (!is_visible_fsp(direntry_fname->fsp)) {
1395 TALLOC_FREE(fullname);
1396 TALLOC_FREE(smb_dname_full);
1397 TALLOC_FREE(talloced);
1398 TALLOC_FREE(direntry_fname);
1399 continue;
1403 unlink_flags = 0;
1405 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1406 status = recursive_rmdir(ctx, conn, smb_dname_full);
1407 if (!NT_STATUS_IS_OK(status)) {
1408 goto err_break;
1410 unlink_flags = AT_REMOVEDIR;
1413 retval = SMB_VFS_UNLINKAT(conn,
1414 dirfsp,
1415 direntry_fname,
1416 unlink_flags);
1417 if (retval != 0) {
1418 status = map_nt_error_from_unix(errno);
1419 goto err_break;
1422 /* Successful iteration. */
1423 do_break = false;
1425 err_break:
1426 TALLOC_FREE(fullname);
1427 TALLOC_FREE(smb_dname_full);
1428 TALLOC_FREE(talloced);
1429 TALLOC_FREE(direntry_fname);
1430 if (do_break) {
1431 break;
1435 /* If we get here, we know NT_STATUS_IS_OK(status) */
1436 SMB_ASSERT(NT_STATUS_IS_OK(status));
1438 /* Retry the rmdir */
1439 ret = SMB_VFS_UNLINKAT(conn,
1440 parent_fname->fsp,
1441 at_fname,
1442 AT_REMOVEDIR);
1443 if (ret != 0) {
1444 status = map_nt_error_from_unix(errno);
1447 err:
1449 TALLOC_FREE(dir_hnd);
1450 TALLOC_FREE(parent_fname);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 DBG_NOTICE("couldn't remove directory %s : "
1454 "%s\n", smb_fname_str_dbg(smb_dname),
1455 nt_errstr(status));
1456 return status;
1459 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1460 FILE_NOTIFY_CHANGE_DIR_NAME,
1461 smb_dname->base_name);
1463 return status;
1466 /****************************************************************************
1467 Close a directory opened by an NT SMB call.
1468 ****************************************************************************/
1470 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1471 enum file_close_type close_type)
1473 connection_struct *conn = fsp->conn;
1474 struct close_share_mode_lock_state lck_state = {};
1475 bool changed_user = false;
1476 NTSTATUS status = NT_STATUS_OK;
1477 NTSTATUS status1 = NT_STATUS_OK;
1478 NTSTATUS notify_status;
1479 NTSTATUS ulstatus;
1481 SMB_ASSERT(fsp->fsp_flags.is_fsa);
1483 if (fsp->conn->sconn->using_smb2) {
1484 notify_status = NT_STATUS_NOTIFY_CLEANUP;
1485 } else {
1486 notify_status = NT_STATUS_OK;
1489 assert_no_pending_aio(fsp, close_type);
1492 * NT can set delete_on_close of the last open
1493 * reference to a directory also.
1496 lck_state = (struct close_share_mode_lock_state) {
1497 .fsp = fsp,
1498 .object_type = "directory",
1499 .close_type = close_type,
1502 status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
1503 fsp->file_id,
1504 close_share_mode_lock_prepare,
1505 &lck_state);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
1508 fsp_str_dbg(fsp), nt_errstr(status));
1509 return status;
1513 * We don't have directory leases yet, so assert it in order
1514 * to skip release_file_oplock().
1516 SMB_ASSERT(fsp->oplock_type == NO_OPLOCK);
1519 * NT can set delete_on_close of the last open
1520 * reference to a file.
1523 if (!lck_state.delete_object) {
1524 status = NT_STATUS_OK;
1525 goto done;
1529 * Ok, we have to delete the directory
1531 lck_state.cleanup_fn = close_share_mode_lock_cleanup;
1533 if (lck_state.got_tokens &&
1534 !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
1536 /* Become the user who requested the delete. */
1538 DBG_INFO("dir %s. Change user to uid %u\n",
1539 fsp_str_dbg(fsp),
1540 (unsigned int)lck_state.del_token->uid);
1542 if (!push_sec_ctx()) {
1543 smb_panic("close_directory: failed to push sec_ctx.\n");
1546 set_sec_ctx(lck_state.del_token->uid,
1547 lck_state.del_token->gid,
1548 lck_state.del_token->ngroups,
1549 lck_state.del_token->groups,
1550 lck_state.del_nt_token);
1552 changed_user = true;
1555 if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1556 && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1558 status = delete_all_streams(fsp->conn, fsp->fsp_name);
1559 if (!NT_STATUS_IS_OK(status)) {
1560 DEBUG(5, ("delete_all_streams failed: %s\n",
1561 nt_errstr(status)));
1562 goto done;
1566 status = rmdir_internals(talloc_tos(), fsp);
1568 DEBUG(5,("close_directory: %s. Delete on close was set - "
1569 "deleting directory returned %s.\n",
1570 fsp_str_dbg(fsp), nt_errstr(status)));
1573 * Ensure we remove any change notify requests that would
1574 * now fail as the directory has been deleted.
1577 if (NT_STATUS_IS_OK(status)) {
1578 notify_status = NT_STATUS_DELETE_PENDING;
1581 done:
1582 if (changed_user) {
1583 /* unbecome user. */
1584 pop_sec_ctx();
1587 ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
1588 lck_state.cleanup_fn,
1589 &lck_state);
1590 if (!NT_STATUS_IS_OK(ulstatus)) {
1591 DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
1592 fsp_str_dbg(fsp), nt_errstr(ulstatus));
1593 smb_panic("share_mode_entry_prepare_unlock() failed!");
1596 remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1598 status1 = fd_close(fsp);
1600 if (!NT_STATUS_IS_OK(status1)) {
1601 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1602 fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1603 strerror(errno)));
1606 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1607 status = status1;
1609 return status;
1612 /****************************************************************************
1613 Rundown all SMB-related dependencies of a files struct
1614 ****************************************************************************/
1616 NTSTATUS close_file_smb(struct smb_request *req,
1617 struct files_struct *fsp,
1618 enum file_close_type close_type)
1620 NTSTATUS status;
1623 * This fsp can never be an internal dirfsp. They must
1624 * be explicitly closed by TALLOC_FREE of the dir handle.
1626 SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1629 * Never call directly on a base fsp
1631 SMB_ASSERT(fsp->stream_fsp == NULL);
1633 if (fsp->fake_file_handle != NULL) {
1635 * Named pipes are opened as fake files and
1636 * can have pending aio requests. Ensure
1637 * we clear out all pending aio on force
1638 * shutdown of named pipes also.
1639 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15423
1641 assert_no_pending_aio(fsp, close_type);
1642 status = close_fake_file(req, fsp);
1643 } else if (fsp->print_file != NULL) {
1644 /* FIXME: return spool errors */
1645 print_spool_end(fsp, close_type);
1646 fd_close(fsp);
1647 status = NT_STATUS_OK;
1648 } else if (!fsp->fsp_flags.is_fsa) {
1649 if (close_type == NORMAL_CLOSE) {
1650 DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1651 "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1652 fsp_str_dbg(fsp),
1653 fsp->fsp_flags.is_fsa,
1654 fsp->fsp_flags.is_pathref,
1655 fsp->fsp_flags.is_directory);
1657 SMB_ASSERT(close_type != NORMAL_CLOSE);
1658 fd_close(fsp);
1659 status = NT_STATUS_OK;
1660 } else if (fsp->fsp_flags.is_directory) {
1661 status = close_directory(req, fsp, close_type);
1662 } else {
1663 status = close_normal_file(req, fsp, close_type);
1666 if (fsp_is_alternate_stream(fsp)) {
1668 * fsp was a stream, its base_fsp can't be a stream
1669 * as well
1671 SMB_ASSERT(!fsp_is_alternate_stream(fsp->base_fsp));
1674 * There's a 1:1 relationship between fsp and a base_fsp
1676 SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1679 * Make base_fsp look standalone now
1681 fsp->base_fsp->stream_fsp = NULL;
1683 close_file_free(req, &fsp->base_fsp, close_type);
1686 fsp_unbind_smb(req, fsp);
1688 return status;
1691 NTSTATUS close_file_free(struct smb_request *req,
1692 struct files_struct **_fsp,
1693 enum file_close_type close_type)
1695 struct files_struct *fsp = *_fsp;
1696 NTSTATUS status;
1698 status = close_file_smb(req, fsp, close_type);
1700 file_free(req, fsp);
1701 *_fsp = NULL;
1703 return status;
1706 /****************************************************************************
1707 Deal with an (authorized) message to close a file given the share mode
1708 entry.
1709 ****************************************************************************/
1711 void msg_close_file(struct messaging_context *msg_ctx,
1712 void *private_data,
1713 uint32_t msg_type,
1714 struct server_id server_id,
1715 DATA_BLOB *data)
1717 files_struct *fsp = NULL;
1718 struct file_id id;
1719 struct share_mode_entry e;
1720 struct smbd_server_connection *sconn =
1721 talloc_get_type_abort(private_data,
1722 struct smbd_server_connection);
1724 message_to_share_mode_entry(&id, &e, (char *)data->data);
1726 if(DEBUGLVL(10)) {
1727 char *sm_str = share_mode_str(NULL, 0, &id, &e);
1728 if (!sm_str) {
1729 smb_panic("talloc failed");
1731 DEBUG(10,("msg_close_file: got request to close share mode "
1732 "entry %s\n", sm_str));
1733 TALLOC_FREE(sm_str);
1736 fsp = file_find_dif(sconn, id, e.share_file_id);
1737 if (!fsp) {
1738 DEBUG(10,("msg_close_file: failed to find file.\n"));
1739 return;
1741 close_file_free(NULL, &fsp, NORMAL_CLOSE);