nsswitch: Fix getting data out of pam_get_data()
[Samba.git] / source3 / smbd / close.c
blobd1e893257809e8a0bb95a05cec7b5c08a57684ff
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"
38 /****************************************************************************
39 Run a file if it is a magic script.
40 ****************************************************************************/
42 static NTSTATUS check_magic(struct files_struct *fsp)
44 int ret;
45 const struct loadparm_substitution *lp_sub =
46 loadparm_s3_global_substitution();
47 const char *magic_output = NULL;
48 SMB_STRUCT_STAT st;
49 int tmp_fd, outfd;
50 TALLOC_CTX *ctx = NULL;
51 const char *p;
52 struct connection_struct *conn = fsp->conn;
53 char *fname = NULL;
54 NTSTATUS status;
56 if (!*lp_magic_script(talloc_tos(), lp_sub, SNUM(conn))) {
57 return NT_STATUS_OK;
60 DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));
62 ctx = talloc_stackframe();
64 fname = fsp->fsp_name->base_name;
66 if (!(p = strrchr_m(fname,'/'))) {
67 p = fname;
68 } else {
69 p++;
72 if (!strequal(lp_magic_script(talloc_tos(), lp_sub, SNUM(conn)),p)) {
73 status = NT_STATUS_OK;
74 goto out;
77 if (*lp_magic_output(talloc_tos(), lp_sub, SNUM(conn))) {
78 magic_output = lp_magic_output(talloc_tos(), lp_sub, SNUM(conn));
79 } else {
80 magic_output = talloc_asprintf(ctx,
81 "%s.out",
82 fname);
84 if (!magic_output) {
85 status = NT_STATUS_NO_MEMORY;
86 goto out;
89 /* Ensure we don't depend on user's PATH. */
90 p = talloc_asprintf(ctx, "./%s", fname);
91 if (!p) {
92 status = NT_STATUS_NO_MEMORY;
93 goto out;
96 if (chmod(fname, 0755) == -1) {
97 status = map_nt_error_from_unix(errno);
98 goto out;
100 ret = smbrun(p, &tmp_fd, NULL);
101 DEBUG(3,("Invoking magic command %s gave %d\n",
102 p,ret));
104 unlink(fname);
105 if (ret != 0 || tmp_fd == -1) {
106 if (tmp_fd != -1) {
107 close(tmp_fd);
109 status = NT_STATUS_UNSUCCESSFUL;
110 goto out;
112 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
113 if (outfd == -1) {
114 int err = errno;
115 close(tmp_fd);
116 status = map_nt_error_from_unix(err);
117 goto out;
120 if (sys_fstat(tmp_fd, &st, false) == -1) {
121 int err = errno;
122 close(tmp_fd);
123 close(outfd);
124 status = map_nt_error_from_unix(err);
125 goto out;
128 if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) {
129 int err = errno;
130 close(tmp_fd);
131 close(outfd);
132 status = map_nt_error_from_unix(err);
133 goto out;
135 close(tmp_fd);
136 if (close(outfd) == -1) {
137 status = map_nt_error_from_unix(errno);
138 goto out;
141 status = NT_STATUS_OK;
143 out:
144 TALLOC_FREE(ctx);
145 return status;
148 /****************************************************************************
149 Delete all streams
150 ****************************************************************************/
152 NTSTATUS delete_all_streams(connection_struct *conn,
153 const struct smb_filename *smb_fname)
155 struct stream_struct *stream_info = NULL;
156 unsigned int i;
157 unsigned int num_streams = 0;
158 TALLOC_CTX *frame = talloc_stackframe();
159 NTSTATUS status;
161 status = vfs_fstreaminfo(smb_fname->fsp, talloc_tos(),
162 &num_streams, &stream_info);
164 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
165 DEBUG(10, ("no streams around\n"));
166 TALLOC_FREE(frame);
167 return NT_STATUS_OK;
170 if (!NT_STATUS_IS_OK(status)) {
171 DEBUG(10, ("vfs_fstreaminfo failed: %s\n",
172 nt_errstr(status)));
173 goto fail;
176 DEBUG(10, ("delete_all_streams found %d streams\n",
177 num_streams));
179 if (num_streams == 0) {
180 TALLOC_FREE(frame);
181 return NT_STATUS_OK;
184 for (i=0; i<num_streams; i++) {
185 int res;
186 struct smb_filename *smb_fname_stream;
188 if (strequal(stream_info[i].name, "::$DATA")) {
189 continue;
192 status = synthetic_pathref(talloc_tos(),
193 conn->cwd_fsp,
194 smb_fname->base_name,
195 stream_info[i].name,
196 NULL,
197 smb_fname->twrp,
198 (smb_fname->flags &
199 ~SMB_FILENAME_POSIX_PATH),
200 &smb_fname_stream);
201 if (!NT_STATUS_IS_OK(status)) {
202 DEBUG(0, ("talloc_aprintf failed\n"));
203 status = NT_STATUS_NO_MEMORY;
204 goto fail;
207 res = SMB_VFS_UNLINKAT(conn,
208 conn->cwd_fsp,
209 smb_fname_stream,
212 if (res == -1) {
213 status = map_nt_error_from_unix(errno);
214 DEBUG(10, ("Could not delete stream %s: %s\n",
215 smb_fname_str_dbg(smb_fname_stream),
216 strerror(errno)));
217 TALLOC_FREE(smb_fname_stream);
218 break;
220 TALLOC_FREE(smb_fname_stream);
223 fail:
224 TALLOC_FREE(frame);
225 return status;
228 struct has_other_nonposix_opens_state {
229 files_struct *fsp;
230 bool found_another;
233 static bool has_other_nonposix_opens_fn(
234 struct share_mode_entry *e,
235 bool *modified,
236 void *private_data)
238 struct has_other_nonposix_opens_state *state = private_data;
239 struct files_struct *fsp = state->fsp;
241 if (e->name_hash != fsp->name_hash) {
242 return false;
244 if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) &&
245 (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 lck_state.reset_delete_on_close = true;
608 done:
610 if (changed_user) {
611 /* unbecome user. */
612 pop_sec_ctx();
615 if (fsp->fsp_flags.kernel_share_modes_taken) {
616 /* remove filesystem sharemodes */
617 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
618 if (ret == -1) {
619 DBG_INFO("Removing file system sharemode for "
620 "%s failed: %s\n",
621 fsp_str_dbg(fsp), strerror(errno));
625 ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
626 lck_state.cleanup_fn,
627 &lck_state);
628 if (!NT_STATUS_IS_OK(ulstatus)) {
629 DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
630 fsp_str_dbg(fsp), nt_errstr(ulstatus));
631 smb_panic("share_mode_entry_prepare_unlock() failed!");
634 if (lck_state.delete_object) {
636 * Do the notification after we released the share
637 * mode lock. Inside notify_fname we take out another
638 * tdb lock. With ctdb also accessing our databases,
639 * this can lead to deadlocks. Putting this notify
640 * after the TALLOC_FREE(lck) above we avoid locking
641 * two records simultaneously. Notifies are async and
642 * informational only, so calling the notify_fname
643 * without holding the share mode lock should not do
644 * any harm.
646 notify_fname(conn, NOTIFY_ACTION_REMOVED,
647 FILE_NOTIFY_CHANGE_FILE_NAME,
648 fsp->fsp_name->base_name);
651 return status;
654 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
656 DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
658 if (is_omit_timespec(&ts)) {
659 return;
661 fsp->fsp_flags.write_time_forced = false;
662 fsp->fsp_flags.update_write_time_on_close = true;
663 fsp->close_write_time = ts;
666 static void update_write_time_on_close_share_mode_fn(struct share_mode_lock *lck,
667 void *private_data)
669 struct files_struct *fsp =
670 talloc_get_type_abort(private_data,
671 struct files_struct);
672 NTTIME share_mtime = share_mode_changed_write_time(lck);
675 * On close if we're changing the real file time we
676 * must update it in the open file db too.
678 share_mode_set_old_write_time(lck, fsp->close_write_time);
681 * Close write times overwrite sticky write times
682 * so we must replace any sticky write time here.
684 if (!null_nttime(share_mtime)) {
685 share_mode_set_changed_write_time(lck, fsp->close_write_time);
689 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
691 struct smb_file_time ft;
692 NTSTATUS status;
694 init_smb_file_time(&ft);
696 if (!(fsp->fsp_flags.update_write_time_on_close)) {
697 return NT_STATUS_OK;
700 if (is_omit_timespec(&fsp->close_write_time)) {
701 fsp->close_write_time = timespec_current();
704 /* Ensure we have a valid stat struct for the source. */
705 status = vfs_stat_fsp(fsp);
706 if (!NT_STATUS_IS_OK(status)) {
707 return status;
710 if (!VALID_STAT(fsp->fsp_name->st)) {
711 /* if it doesn't seem to be a real file */
712 return NT_STATUS_OK;
716 * We're being called after close_remove_share_mode() inside
717 * close_normal_file() so it's quite normal to not have an
718 * existing share. So just ignore the result of
719 * share_mode_do_locked_vfs_denied()...
721 share_mode_do_locked_vfs_denied(fsp->file_id,
722 update_write_time_on_close_share_mode_fn,
723 fsp);
725 ft.mtime = fsp->close_write_time;
726 /* As this is a close based update, we are not directly changing the
727 file attributes from a client call, but indirectly from a write. */
728 status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
729 if (!NT_STATUS_IS_OK(status)) {
730 DEBUG(10,("update_write_time_on_close: smb_set_file_time "
731 "on file %s returned %s\n",
732 fsp_str_dbg(fsp),
733 nt_errstr(status)));
734 return status;
737 return status;
740 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
742 if (!NT_STATUS_IS_OK(s1)) {
743 return s1;
745 return s2;
748 static void assert_no_pending_aio(struct files_struct *fsp,
749 enum file_close_type close_type)
751 struct smbXsrv_client *client = global_smbXsrv_client;
752 size_t num_connections_alive;
753 unsigned num_requests = fsp->num_aio_requests;
755 if (num_requests == 0) {
756 return;
759 num_connections_alive = smbXsrv_client_valid_connections(client);
761 if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
763 * fsp->aio_requests and the contents (fsp->aio_requests[x])
764 * are both independently owned by fsp and are not in a
765 * talloc heirarchy. This allows the fsp->aio_requests array to
766 * be reallocated independently of the array contents so it can
767 * grow on demand.
769 * This means we must ensure order of deallocation
770 * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
771 * contents first, as their destructors access the
772 * fsp->aio_request array. If we don't deallocate them
773 * first, when fsp is deallocated fsp->aio_requests
774 * could have been deallocated *before* its contents
775 * fsp->aio_requests[x], causing a crash.
777 while (fsp->num_aio_requests != 0) {
779 * NB. We *MUST* use
780 * talloc_free(fsp->aio_requests[0]),
781 * and *NOT* TALLOC_FREE() here, as
782 * TALLOC_FREE(fsp->aio_requests[0])
783 * will overwrite any new contents of
784 * fsp->aio_requests[0] that were
785 * copied into it via the destructor
786 * aio_del_req_from_fsp().
788 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
790 talloc_free(fsp->aio_requests[0]);
792 return;
795 DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
796 smb_panic("can not close with outstanding aio requests");
797 return;
800 /****************************************************************************
801 Close a file.
803 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
804 printing and magic scripts are only run on normal close.
805 delete on close is done on normal and shutdown close.
806 ****************************************************************************/
808 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
809 enum file_close_type close_type)
811 NTSTATUS status = NT_STATUS_OK;
812 NTSTATUS tmp;
813 connection_struct *conn = fsp->conn;
814 bool is_durable = false;
816 SMB_ASSERT(fsp->fsp_flags.is_fsa);
818 assert_no_pending_aio(fsp, close_type);
820 while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
821 smbd_smb1_brl_finish_by_req(
822 fsp->blocked_smb1_lock_reqs[0],
823 NT_STATUS_RANGE_NOT_LOCKED);
827 * If we're flushing on a close we can get a write
828 * error here, we must remember this.
831 if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
832 is_durable = fsp->op->global->durable;
835 if (close_type != SHUTDOWN_CLOSE) {
836 is_durable = false;
839 if (is_durable) {
840 DATA_BLOB new_cookie = data_blob_null;
842 tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
843 fsp->op->global->backend_cookie,
844 fsp->op,
845 &new_cookie);
846 if (NT_STATUS_IS_OK(tmp)) {
847 struct timeval tv;
848 NTTIME now;
850 if (req != NULL) {
851 tv = req->request_time;
852 } else {
853 tv = timeval_current();
855 now = timeval_to_nttime(&tv);
857 data_blob_free(&fsp->op->global->backend_cookie);
858 fsp->op->global->backend_cookie = new_cookie;
860 fsp->op->compat = NULL;
861 tmp = smbXsrv_open_close(fsp->op, now);
862 if (!NT_STATUS_IS_OK(tmp)) {
863 DEBUG(1, ("Failed to update smbXsrv_open "
864 "record when disconnecting durable "
865 "handle for file %s: %s - "
866 "proceeding with normal close\n",
867 fsp_str_dbg(fsp), nt_errstr(tmp)));
869 scavenger_schedule_disconnected(fsp);
870 } else {
871 DEBUG(1, ("Failed to disconnect durable handle for "
872 "file %s: %s - proceeding with normal "
873 "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
875 if (!NT_STATUS_IS_OK(tmp)) {
876 is_durable = false;
880 if (is_durable) {
882 * This is the case where we successfully disconnected
883 * a durable handle and closed the underlying file.
884 * In all other cases, we proceed with a genuine close.
886 DEBUG(10, ("%s disconnected durable handle for file %s\n",
887 conn->session_info->unix_info->unix_name,
888 fsp_str_dbg(fsp)));
889 return NT_STATUS_OK;
892 if (fsp->op != NULL) {
894 * Make sure the handle is not marked as durable anymore
896 fsp->op->global->durable = false;
899 /* If this is an old DOS or FCB open and we have multiple opens on
900 the same handle we only have one share mode. Ensure we only remove
901 the share mode on the last close. */
903 if (fh_get_refcount(fsp->fh) == 1) {
904 /* Should we return on error here... ? */
905 tmp = close_remove_share_mode(fsp, close_type);
906 status = ntstatus_keeperror(status, tmp);
909 locking_close_file(fsp, close_type);
912 * Ensure pending modtime is set before closing underlying fd.
915 tmp = update_write_time_on_close(fsp);
916 if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
918 * Someone renamed the file or a parent directory containing
919 * this file. We can't do anything about this, eat the error.
921 tmp = NT_STATUS_OK;
923 status = ntstatus_keeperror(status, tmp);
925 tmp = fd_close(fsp);
926 status = ntstatus_keeperror(status, tmp);
928 /* check for magic scripts */
929 if (close_type == NORMAL_CLOSE) {
930 tmp = check_magic(fsp);
931 status = ntstatus_keeperror(status, tmp);
934 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
935 conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
936 conn->num_files_open - 1,
937 nt_errstr(status) ));
939 return status;
941 /****************************************************************************
942 Function used by reply_rmdir to delete an entire directory
943 tree recursively. Return True on ok, False on fail.
944 ****************************************************************************/
946 NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
947 connection_struct *conn,
948 struct smb_filename *smb_dname)
950 const char *dname = NULL;
951 char *talloced = NULL;
952 long offset = 0;
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, &offset, NULL, &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 long dirpos = 0;
1076 struct smb_Dir *dir_hnd = NULL;
1077 struct files_struct *dirfsp = NULL;
1078 int unlink_flags = 0;
1079 NTSTATUS status;
1080 int ret;
1082 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
1084 status = parent_pathref(talloc_tos(),
1085 conn->cwd_fsp,
1086 fsp->fsp_name,
1087 &parent_fname,
1088 &at_fname);
1089 if (!NT_STATUS_IS_OK(status)) {
1090 return status;
1094 * Todo: use SMB_VFS_STATX() once it's available.
1097 /* Might be a symlink. */
1098 ret = SMB_VFS_LSTAT(conn, smb_dname);
1099 if (ret != 0) {
1100 TALLOC_FREE(parent_fname);
1101 return map_nt_error_from_unix(errno);
1104 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
1105 /* Is what it points to a directory ? */
1106 ret = SMB_VFS_STAT(conn, smb_dname);
1107 if (ret != 0) {
1108 TALLOC_FREE(parent_fname);
1109 return map_nt_error_from_unix(errno);
1111 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
1112 TALLOC_FREE(parent_fname);
1113 return NT_STATUS_NOT_A_DIRECTORY;
1115 } else {
1116 unlink_flags = AT_REMOVEDIR;
1119 ret = SMB_VFS_UNLINKAT(conn,
1120 parent_fname->fsp,
1121 at_fname,
1122 unlink_flags);
1123 if (ret == 0) {
1124 TALLOC_FREE(parent_fname);
1125 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1126 FILE_NOTIFY_CHANGE_DIR_NAME,
1127 smb_dname->base_name);
1128 return NT_STATUS_OK;
1131 if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1132 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1133 "%s\n", smb_fname_str_dbg(smb_dname),
1134 strerror(errno)));
1135 TALLOC_FREE(parent_fname);
1136 return map_nt_error_from_unix(errno);
1140 * Here we know the initial directory unlink failed with
1141 * ENOTEMPTY or EEXIST so we know there are objects within.
1142 * If we don't have permission to delete files non
1143 * visible to the client just fail the directory delete.
1146 if (!lp_delete_veto_files(SNUM(conn))) {
1147 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1148 goto err;
1152 * Check to see if the only thing in this directory are
1153 * files non-visible to the client. If not, fail the delete.
1156 status = OpenDir(talloc_tos(),
1157 conn,
1158 smb_dname,
1159 NULL,
1161 &dir_hnd);
1162 if (!NT_STATUS_IS_OK(status)) {
1164 * Note, we deliberately squash the error here
1165 * to avoid leaking information about what we
1166 * can't delete.
1168 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1169 goto err;
1172 dirfsp = dir_hnd_fetch_fsp(dir_hnd);
1174 while ((dname = ReadDirName(
1175 dir_hnd, &dirpos, NULL, &talloced)) != NULL) {
1176 struct smb_filename *smb_dname_full = NULL;
1177 struct smb_filename *direntry_fname = NULL;
1178 char *fullname = NULL;
1179 int retval;
1181 if (ISDOT(dname) || ISDOTDOT(dname)) {
1182 TALLOC_FREE(talloced);
1183 continue;
1185 if (IS_VETO_PATH(conn, dname)) {
1186 TALLOC_FREE(talloced);
1187 continue;
1190 fullname = talloc_asprintf(talloc_tos(),
1191 "%s/%s",
1192 smb_dname->base_name,
1193 dname);
1195 if (fullname == NULL) {
1196 TALLOC_FREE(talloced);
1197 status = NT_STATUS_NO_MEMORY;
1198 goto err;
1201 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1202 fullname,
1203 NULL,
1204 NULL,
1205 smb_dname->twrp,
1206 smb_dname->flags);
1207 if (smb_dname_full == NULL) {
1208 TALLOC_FREE(talloced);
1209 TALLOC_FREE(fullname);
1210 status = NT_STATUS_NO_MEMORY;
1211 goto err;
1214 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1215 if (retval != 0) {
1216 status = map_nt_error_from_unix(errno);
1217 TALLOC_FREE(talloced);
1218 TALLOC_FREE(fullname);
1219 TALLOC_FREE(smb_dname_full);
1220 goto err;
1223 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1224 /* Could it be an msdfs link ? */
1225 if (lp_host_msdfs() &&
1226 lp_msdfs_root(SNUM(conn))) {
1227 struct smb_filename *smb_atname;
1228 smb_atname = synthetic_smb_fname(talloc_tos(),
1229 dname,
1230 NULL,
1231 &smb_dname_full->st,
1232 fsp->fsp_name->twrp,
1233 fsp->fsp_name->flags);
1234 if (smb_atname == NULL) {
1235 TALLOC_FREE(talloced);
1236 TALLOC_FREE(fullname);
1237 TALLOC_FREE(smb_dname_full);
1238 status = NT_STATUS_NO_MEMORY;
1239 goto err;
1241 if (is_msdfs_link(fsp, smb_atname)) {
1242 TALLOC_FREE(talloced);
1243 TALLOC_FREE(fullname);
1244 TALLOC_FREE(smb_dname_full);
1245 TALLOC_FREE(smb_atname);
1246 DBG_DEBUG("got msdfs link name %s "
1247 "- can't delete directory %s\n",
1248 dname,
1249 fsp_str_dbg(fsp));
1250 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1251 goto err;
1253 TALLOC_FREE(smb_atname);
1256 /* Not a DFS link - could it be a dangling symlink ? */
1257 retval = SMB_VFS_STAT(conn, smb_dname_full);
1258 if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
1260 * Dangling symlink.
1261 * Allow delete as "delete veto files = yes"
1263 TALLOC_FREE(talloced);
1264 TALLOC_FREE(fullname);
1265 TALLOC_FREE(smb_dname_full);
1266 continue;
1269 DBG_DEBUG("got symlink name %s - "
1270 "can't delete directory %s\n",
1271 dname,
1272 fsp_str_dbg(fsp));
1273 TALLOC_FREE(talloced);
1274 TALLOC_FREE(fullname);
1275 TALLOC_FREE(smb_dname_full);
1276 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1277 goto err;
1280 /* Not a symlink, get a pathref. */
1281 status = synthetic_pathref(talloc_tos(),
1282 dirfsp,
1283 dname,
1284 NULL,
1285 &smb_dname_full->st,
1286 smb_dname->twrp,
1287 smb_dname->flags,
1288 &direntry_fname);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 TALLOC_FREE(talloced);
1291 TALLOC_FREE(fullname);
1292 TALLOC_FREE(smb_dname_full);
1293 goto err;
1296 if (!is_visible_fsp(direntry_fname->fsp)) {
1297 TALLOC_FREE(talloced);
1298 TALLOC_FREE(fullname);
1299 TALLOC_FREE(smb_dname_full);
1300 TALLOC_FREE(direntry_fname);
1301 continue;
1305 * We found a client visible name.
1306 * We cannot delete this directory.
1308 DBG_DEBUG("got name %s - "
1309 "can't delete directory %s\n",
1310 dname,
1311 fsp_str_dbg(fsp));
1312 TALLOC_FREE(talloced);
1313 TALLOC_FREE(fullname);
1314 TALLOC_FREE(smb_dname_full);
1315 TALLOC_FREE(direntry_fname);
1316 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1317 goto err;
1320 /* Do a recursive delete. */
1321 RewindDir(dir_hnd,&dirpos);
1323 while ((dname = ReadDirName(
1324 dir_hnd, &dirpos, NULL, &talloced)) != NULL) {
1325 struct smb_filename *direntry_fname = NULL;
1326 struct smb_filename *smb_dname_full = NULL;
1327 char *fullname = NULL;
1328 bool do_break = true;
1329 int retval;
1331 if (ISDOT(dname) || ISDOTDOT(dname)) {
1332 TALLOC_FREE(talloced);
1333 continue;
1336 fullname = talloc_asprintf(ctx,
1337 "%s/%s",
1338 smb_dname->base_name,
1339 dname);
1341 if (fullname == NULL) {
1342 status = NT_STATUS_NO_MEMORY;
1343 goto err_break;
1346 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1347 fullname,
1348 NULL,
1349 NULL,
1350 smb_dname->twrp,
1351 smb_dname->flags);
1352 if (smb_dname_full == NULL) {
1353 status = NT_STATUS_NO_MEMORY;
1354 goto err_break;
1358 * Todo: use SMB_VFS_STATX() once that's available.
1361 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1362 if (retval != 0) {
1363 status = map_nt_error_from_unix(errno);
1364 goto err_break;
1368 * We are only dealing with VETO'ed objects
1369 * here. If it's a symlink, just delete the
1370 * link without caring what it is pointing
1371 * to.
1373 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1374 direntry_fname = synthetic_smb_fname(talloc_tos(),
1375 dname,
1376 NULL,
1377 &smb_dname_full->st,
1378 smb_dname->twrp,
1379 smb_dname->flags);
1380 if (direntry_fname == NULL) {
1381 status = NT_STATUS_NO_MEMORY;
1382 goto err_break;
1384 } else {
1385 status = synthetic_pathref(talloc_tos(),
1386 dirfsp,
1387 dname,
1388 NULL,
1389 &smb_dname_full->st,
1390 smb_dname->twrp,
1391 smb_dname->flags,
1392 &direntry_fname);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 goto err_break;
1397 if (!is_visible_fsp(direntry_fname->fsp)) {
1398 TALLOC_FREE(fullname);
1399 TALLOC_FREE(smb_dname_full);
1400 TALLOC_FREE(talloced);
1401 TALLOC_FREE(direntry_fname);
1402 continue;
1406 unlink_flags = 0;
1408 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1409 status = recursive_rmdir(ctx, conn, smb_dname_full);
1410 if (!NT_STATUS_IS_OK(status)) {
1411 goto err_break;
1413 unlink_flags = AT_REMOVEDIR;
1416 retval = SMB_VFS_UNLINKAT(conn,
1417 dirfsp,
1418 direntry_fname,
1419 unlink_flags);
1420 if (retval != 0) {
1421 status = map_nt_error_from_unix(errno);
1422 goto err_break;
1425 /* Successful iteration. */
1426 do_break = false;
1428 err_break:
1429 TALLOC_FREE(fullname);
1430 TALLOC_FREE(smb_dname_full);
1431 TALLOC_FREE(talloced);
1432 TALLOC_FREE(direntry_fname);
1433 if (do_break) {
1434 break;
1438 /* If we get here, we know NT_STATUS_IS_OK(status) */
1439 SMB_ASSERT(NT_STATUS_IS_OK(status));
1441 /* Retry the rmdir */
1442 ret = SMB_VFS_UNLINKAT(conn,
1443 parent_fname->fsp,
1444 at_fname,
1445 AT_REMOVEDIR);
1446 if (ret != 0) {
1447 status = map_nt_error_from_unix(errno);
1450 err:
1452 TALLOC_FREE(dir_hnd);
1453 TALLOC_FREE(parent_fname);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 DBG_NOTICE("couldn't remove directory %s : "
1457 "%s\n", smb_fname_str_dbg(smb_dname),
1458 nt_errstr(status));
1459 return status;
1462 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1463 FILE_NOTIFY_CHANGE_DIR_NAME,
1464 smb_dname->base_name);
1466 return status;
1469 /****************************************************************************
1470 Close a directory opened by an NT SMB call.
1471 ****************************************************************************/
1473 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1474 enum file_close_type close_type)
1476 connection_struct *conn = fsp->conn;
1477 struct close_share_mode_lock_state lck_state = {};
1478 bool changed_user = false;
1479 NTSTATUS status = NT_STATUS_OK;
1480 NTSTATUS status1 = NT_STATUS_OK;
1481 NTSTATUS notify_status;
1482 NTSTATUS ulstatus;
1484 SMB_ASSERT(fsp->fsp_flags.is_fsa);
1486 if (fsp->conn->sconn->using_smb2) {
1487 notify_status = NT_STATUS_NOTIFY_CLEANUP;
1488 } else {
1489 notify_status = NT_STATUS_OK;
1492 assert_no_pending_aio(fsp, close_type);
1495 * NT can set delete_on_close of the last open
1496 * reference to a directory also.
1499 lck_state = (struct close_share_mode_lock_state) {
1500 .fsp = fsp,
1501 .object_type = "directory",
1502 .close_type = close_type,
1505 status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
1506 fsp->file_id,
1507 close_share_mode_lock_prepare,
1508 &lck_state);
1509 if (!NT_STATUS_IS_OK(status)) {
1510 DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
1511 fsp_str_dbg(fsp), nt_errstr(status));
1512 return status;
1516 * We don't have directory leases yet, so assert it in order
1517 * to skip release_file_oplock().
1519 SMB_ASSERT(fsp->oplock_type == NO_OPLOCK);
1522 * NT can set delete_on_close of the last open
1523 * reference to a file.
1526 if (!lck_state.delete_object) {
1527 status = NT_STATUS_OK;
1528 goto done;
1532 * Ok, we have to delete the directory
1534 lck_state.cleanup_fn = close_share_mode_lock_cleanup;
1536 if (lck_state.got_tokens &&
1537 !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
1539 /* Become the user who requested the delete. */
1541 DBG_INFO("dir %s. Change user to uid %u\n",
1542 fsp_str_dbg(fsp),
1543 (unsigned int)lck_state.del_token->uid);
1545 if (!push_sec_ctx()) {
1546 smb_panic("close_directory: failed to push sec_ctx.\n");
1549 set_sec_ctx(lck_state.del_token->uid,
1550 lck_state.del_token->gid,
1551 lck_state.del_token->ngroups,
1552 lck_state.del_token->groups,
1553 lck_state.del_nt_token);
1555 changed_user = true;
1558 if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1559 && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1561 status = delete_all_streams(fsp->conn, fsp->fsp_name);
1562 if (!NT_STATUS_IS_OK(status)) {
1563 DEBUG(5, ("delete_all_streams failed: %s\n",
1564 nt_errstr(status)));
1565 goto done;
1569 status = rmdir_internals(talloc_tos(), fsp);
1571 DEBUG(5,("close_directory: %s. Delete on close was set - "
1572 "deleting directory returned %s.\n",
1573 fsp_str_dbg(fsp), nt_errstr(status)));
1576 * Ensure we remove any change notify requests that would
1577 * now fail as the directory has been deleted.
1580 if (NT_STATUS_IS_OK(status)) {
1581 notify_status = NT_STATUS_DELETE_PENDING;
1584 done:
1585 if (changed_user) {
1586 /* unbecome user. */
1587 pop_sec_ctx();
1590 ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
1591 lck_state.cleanup_fn,
1592 &lck_state);
1593 if (!NT_STATUS_IS_OK(ulstatus)) {
1594 DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
1595 fsp_str_dbg(fsp), nt_errstr(ulstatus));
1596 smb_panic("share_mode_entry_prepare_unlock() failed!");
1599 remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1601 status1 = fd_close(fsp);
1603 if (!NT_STATUS_IS_OK(status1)) {
1604 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1605 fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1606 strerror(errno)));
1609 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1610 status = status1;
1612 return status;
1615 /****************************************************************************
1616 Rundown all SMB-related dependencies of a files struct
1617 ****************************************************************************/
1619 NTSTATUS close_file_smb(struct smb_request *req,
1620 struct files_struct *fsp,
1621 enum file_close_type close_type)
1623 NTSTATUS status;
1626 * This fsp can never be an internal dirfsp. They must
1627 * be explicitly closed by TALLOC_FREE of the dir handle.
1629 SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1632 * Never call directly on a base fsp
1634 SMB_ASSERT(fsp->stream_fsp == NULL);
1636 if (fsp->fake_file_handle != NULL) {
1637 status = close_fake_file(req, fsp);
1638 } else if (fsp->print_file != NULL) {
1639 /* FIXME: return spool errors */
1640 print_spool_end(fsp, close_type);
1641 fd_close(fsp);
1642 status = NT_STATUS_OK;
1643 } else if (!fsp->fsp_flags.is_fsa) {
1644 if (close_type == NORMAL_CLOSE) {
1645 DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1646 "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1647 fsp_str_dbg(fsp),
1648 fsp->fsp_flags.is_fsa,
1649 fsp->fsp_flags.is_pathref,
1650 fsp->fsp_flags.is_directory);
1652 SMB_ASSERT(close_type != NORMAL_CLOSE);
1653 fd_close(fsp);
1654 status = NT_STATUS_OK;
1655 } else if (fsp->fsp_flags.is_directory) {
1656 status = close_directory(req, fsp, close_type);
1657 } else {
1658 status = close_normal_file(req, fsp, close_type);
1661 if (fsp_is_alternate_stream(fsp)) {
1663 * fsp was a stream, its base_fsp can't be a stream
1664 * as well
1666 SMB_ASSERT(!fsp_is_alternate_stream(fsp->base_fsp));
1669 * There's a 1:1 relationship between fsp and a base_fsp
1671 SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1674 * Make base_fsp look standalone now
1676 fsp->base_fsp->stream_fsp = NULL;
1678 close_file_free(req, &fsp->base_fsp, close_type);
1681 fsp_unbind_smb(req, fsp);
1683 return status;
1686 NTSTATUS close_file_free(struct smb_request *req,
1687 struct files_struct **_fsp,
1688 enum file_close_type close_type)
1690 struct files_struct *fsp = *_fsp;
1691 NTSTATUS status;
1693 status = close_file_smb(req, fsp, close_type);
1695 file_free(req, fsp);
1696 *_fsp = NULL;
1698 return status;
1701 /****************************************************************************
1702 Deal with an (authorized) message to close a file given the share mode
1703 entry.
1704 ****************************************************************************/
1706 void msg_close_file(struct messaging_context *msg_ctx,
1707 void *private_data,
1708 uint32_t msg_type,
1709 struct server_id server_id,
1710 DATA_BLOB *data)
1712 files_struct *fsp = NULL;
1713 struct file_id id;
1714 struct share_mode_entry e;
1715 struct smbd_server_connection *sconn =
1716 talloc_get_type_abort(private_data,
1717 struct smbd_server_connection);
1719 message_to_share_mode_entry(&id, &e, (char *)data->data);
1721 if(DEBUGLVL(10)) {
1722 char *sm_str = share_mode_str(NULL, 0, &id, &e);
1723 if (!sm_str) {
1724 smb_panic("talloc failed");
1726 DEBUG(10,("msg_close_file: got request to close share mode "
1727 "entry %s\n", sm_str));
1728 TALLOC_FREE(sm_str);
1731 fsp = file_find_dif(sconn, id, e.share_file_id);
1732 if (!fsp) {
1733 DEBUG(10,("msg_close_file: failed to find file.\n"));
1734 return;
1736 close_file_free(NULL, &fsp, NORMAL_CLOSE);