s4:dsdb:tests: Also pass tests if asserted identity is present
[Samba.git] / source3 / smbd / close.c
bloba4bdd56729a0a9e0bc7ac49c3ef1e04b1c552a9d
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 /****************************************************************************
278 Deal with removing a share mode on last close.
279 ****************************************************************************/
281 static NTSTATUS close_remove_share_mode(files_struct *fsp,
282 enum file_close_type close_type)
284 connection_struct *conn = fsp->conn;
285 bool delete_file = false;
286 bool changed_user = false;
287 struct share_mode_lock *lck = NULL;
288 NTSTATUS status = NT_STATUS_OK;
289 NTSTATUS tmp_status;
290 struct file_id id;
291 const struct security_unix_token *del_token = NULL;
292 const struct security_token *del_nt_token = NULL;
293 struct smb_filename *parent_fname = NULL;
294 struct smb_filename *base_fname = NULL;
295 bool got_tokens = false;
296 bool normal_close;
297 int ret;
299 /* Ensure any pending write time updates are done. */
300 if (fsp->update_write_time_event) {
301 fsp_flush_write_time_update(fsp);
305 * Lock the share entries, and determine if we should delete
306 * on close. If so delete whilst the lock is still in effect.
307 * This prevents race conditions with the file being created. JRA.
310 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
311 if (lck == NULL) {
312 DEBUG(0, ("close_remove_share_mode: Could not get share mode "
313 "lock for file %s\n", fsp_str_dbg(fsp)));
314 return NT_STATUS_INVALID_PARAMETER;
317 /* Remove the oplock before potentially deleting the file. */
318 if(fsp->oplock_type) {
319 remove_oplock(fsp);
322 if (fsp->fsp_flags.write_time_forced) {
323 NTTIME mtime = share_mode_changed_write_time(lck);
324 struct timespec ts = nt_time_to_full_timespec(mtime);
326 DEBUG(10,("close_remove_share_mode: write time forced "
327 "for file %s\n",
328 fsp_str_dbg(fsp)));
329 set_close_write_time(fsp, ts);
330 } else if (fsp->fsp_flags.update_write_time_on_close) {
331 /* Someone had a pending write. */
332 if (is_omit_timespec(&fsp->close_write_time)) {
333 DEBUG(10,("close_remove_share_mode: update to current time "
334 "for file %s\n",
335 fsp_str_dbg(fsp)));
336 /* Update to current time due to "normal" write. */
337 set_close_write_time(fsp, timespec_current());
338 } else {
339 DEBUG(10,("close_remove_share_mode: write time pending "
340 "for file %s\n",
341 fsp_str_dbg(fsp)));
342 /* Update to time set on close call. */
343 set_close_write_time(fsp, fsp->close_write_time);
347 if (fsp->fsp_flags.initial_delete_on_close &&
348 !is_delete_on_close_set(lck, fsp->name_hash)) {
349 /* Initial delete on close was set and no one else
350 * wrote a real delete on close. */
352 fsp->fsp_flags.delete_on_close = true;
353 set_delete_on_close_lck(fsp, lck,
354 fsp->conn->session_info->security_token,
355 fsp->conn->session_info->unix_token);
358 delete_file = is_delete_on_close_set(lck, fsp->name_hash) &&
359 !has_other_nonposix_opens(lck, fsp);
362 * NT can set delete_on_close of the last open
363 * reference to a file.
366 normal_close = (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE);
368 if (!normal_close || !delete_file) {
369 status = NT_STATUS_OK;
370 goto done;
374 * Ok, we have to delete the file
377 DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
378 "- deleting file.\n", fsp_str_dbg(fsp)));
381 * Don't try to update the write time when we delete the file
383 fsp->fsp_flags.update_write_time_on_close = false;
385 got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
386 &del_nt_token, &del_token);
387 SMB_ASSERT(got_tokens);
389 if (!unix_token_equal(del_token, get_current_utok(conn))) {
390 /* Become the user who requested the delete. */
392 DEBUG(5,("close_remove_share_mode: file %s. "
393 "Change user to uid %u\n",
394 fsp_str_dbg(fsp),
395 (unsigned int)del_token->uid));
397 if (!push_sec_ctx()) {
398 smb_panic("close_remove_share_mode: file %s. failed to push "
399 "sec_ctx.\n");
402 set_sec_ctx(del_token->uid,
403 del_token->gid,
404 del_token->ngroups,
405 del_token->groups,
406 del_nt_token);
408 changed_user = true;
411 /* We can only delete the file if the name we have is still valid and
412 hasn't been renamed. */
414 tmp_status = vfs_stat_fsp(fsp);
415 if (!NT_STATUS_IS_OK(tmp_status)) {
416 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
417 "was set and stat failed with error %s\n",
418 fsp_str_dbg(fsp), nt_errstr(tmp_status)));
420 * Don't save the errno here, we ignore this error
422 goto done;
425 id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
427 if (!file_id_equal(&fsp->file_id, &id)) {
428 struct file_id_buf ftmp1, ftmp2;
429 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
430 "was set and dev and/or inode does not match\n",
431 fsp_str_dbg(fsp)));
432 DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
433 "stat file_id %s\n",
434 fsp_str_dbg(fsp),
435 file_id_str_buf(fsp->file_id, &ftmp1),
436 file_id_str_buf(id, &ftmp2)));
438 * Don't save the errno here, we ignore this error
440 goto done;
443 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
444 && !fsp_is_alternate_stream(fsp)) {
446 status = delete_all_streams(conn, fsp->fsp_name);
448 if (!NT_STATUS_IS_OK(status)) {
449 DEBUG(5, ("delete_all_streams failed: %s\n",
450 nt_errstr(status)));
451 goto done;
455 if (fsp->fsp_flags.kernel_share_modes_taken) {
457 * A file system sharemode could block the unlink;
458 * remove filesystem sharemodes first.
460 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
461 if (ret == -1) {
462 DBG_INFO("Removing file system sharemode for %s "
463 "failed: %s\n",
464 fsp_str_dbg(fsp), strerror(errno));
467 fsp->fsp_flags.kernel_share_modes_taken = false;
470 status = parent_pathref(talloc_tos(),
471 conn->cwd_fsp,
472 fsp->fsp_name,
473 &parent_fname,
474 &base_fname);
475 if (!NT_STATUS_IS_OK(status)) {
476 goto done;
479 ret = SMB_VFS_UNLINKAT(conn,
480 parent_fname->fsp,
481 base_fname,
483 TALLOC_FREE(parent_fname);
484 base_fname = NULL;
485 if (ret != 0) {
487 * This call can potentially fail as another smbd may
488 * have had the file open with delete on close set and
489 * deleted it when its last reference to this file
490 * went away. Hence we log this but not at debug level
491 * zero.
494 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
495 "was set and unlink failed with error %s\n",
496 fsp_str_dbg(fsp), strerror(errno)));
498 status = map_nt_error_from_unix(errno);
501 /* As we now have POSIX opens which can unlink
502 * with other open files we may have taken
503 * this code path with more than one share mode
504 * entry - ensure we only delete once by resetting
505 * the delete on close flag. JRA.
508 fsp->fsp_flags.delete_on_close = false;
509 reset_delete_on_close_lck(fsp, lck);
511 done:
513 if (changed_user) {
514 /* unbecome user. */
515 pop_sec_ctx();
518 if (fsp->fsp_flags.kernel_share_modes_taken) {
519 /* remove filesystem sharemodes */
520 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
521 if (ret == -1) {
522 DBG_INFO("Removing file system sharemode for "
523 "%s failed: %s\n",
524 fsp_str_dbg(fsp), strerror(errno));
528 if (!del_share_mode(lck, fsp)) {
529 DEBUG(0, ("close_remove_share_mode: Could not delete share "
530 "entry for file %s\n", fsp_str_dbg(fsp)));
533 TALLOC_FREE(lck);
535 if (delete_file) {
537 * Do the notification after we released the share
538 * mode lock. Inside notify_fname we take out another
539 * tdb lock. With ctdb also accessing our databases,
540 * this can lead to deadlocks. Putting this notify
541 * after the TALLOC_FREE(lck) above we avoid locking
542 * two records simultaneously. Notifies are async and
543 * informational only, so calling the notify_fname
544 * without holding the share mode lock should not do
545 * any harm.
547 notify_fname(conn, NOTIFY_ACTION_REMOVED,
548 FILE_NOTIFY_CHANGE_FILE_NAME,
549 fsp->fsp_name->base_name);
552 return status;
555 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
557 DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
559 if (is_omit_timespec(&ts)) {
560 return;
562 fsp->fsp_flags.write_time_forced = false;
563 fsp->fsp_flags.update_write_time_on_close = true;
564 fsp->close_write_time = ts;
567 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
569 struct smb_file_time ft;
570 NTSTATUS status;
571 struct share_mode_lock *lck = NULL;
573 init_smb_file_time(&ft);
575 if (!(fsp->fsp_flags.update_write_time_on_close)) {
576 return NT_STATUS_OK;
579 if (is_omit_timespec(&fsp->close_write_time)) {
580 fsp->close_write_time = timespec_current();
583 /* Ensure we have a valid stat struct for the source. */
584 status = vfs_stat_fsp(fsp);
585 if (!NT_STATUS_IS_OK(status)) {
586 return status;
589 if (!VALID_STAT(fsp->fsp_name->st)) {
590 /* if it doesn't seem to be a real file */
591 return NT_STATUS_OK;
595 * get_existing_share_mode_lock() isn't really the right
596 * call here, as we're being called after
597 * close_remove_share_mode() inside close_normal_file()
598 * so it's quite normal to not have an existing share
599 * mode here. However, get_share_mode_lock() doesn't
600 * work because that will create a new share mode if
601 * one doesn't exist - so stick with this call (just
602 * ignore any error we get if the share mode doesn't
603 * exist.
606 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
607 if (lck) {
608 NTTIME share_mtime = share_mode_changed_write_time(lck);
609 /* On close if we're changing the real file time we
610 * must update it in the open file db too. */
611 (void)set_write_time(fsp->file_id, fsp->close_write_time);
613 /* Close write times overwrite sticky write times
614 so we must replace any sticky write time here. */
615 if (!null_nttime(share_mtime)) {
616 (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
618 TALLOC_FREE(lck);
621 ft.mtime = fsp->close_write_time;
622 /* As this is a close based update, we are not directly changing the
623 file attributes from a client call, but indirectly from a write. */
624 status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
625 if (!NT_STATUS_IS_OK(status)) {
626 DEBUG(10,("update_write_time_on_close: smb_set_file_time "
627 "on file %s returned %s\n",
628 fsp_str_dbg(fsp),
629 nt_errstr(status)));
630 return status;
633 return status;
636 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
638 if (!NT_STATUS_IS_OK(s1)) {
639 return s1;
641 return s2;
644 static void assert_no_pending_aio(struct files_struct *fsp,
645 enum file_close_type close_type)
647 struct smbXsrv_client *client = global_smbXsrv_client;
648 size_t num_connections_alive;
649 unsigned num_requests = fsp->num_aio_requests;
651 if (num_requests == 0) {
652 return;
655 num_connections_alive = smbXsrv_client_valid_connections(client);
657 if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
659 * fsp->aio_requests and the contents (fsp->aio_requests[x])
660 * are both independently owned by fsp and are not in a
661 * talloc heirarchy. This allows the fsp->aio_requests array to
662 * be reallocated independently of the array contents so it can
663 * grow on demand.
665 * This means we must ensure order of deallocation
666 * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
667 * contents first, as their destructors access the
668 * fsp->aio_request array. If we don't deallocate them
669 * first, when fsp is deallocated fsp->aio_requests
670 * could have been deallocated *before* its contents
671 * fsp->aio_requests[x], causing a crash.
673 while (fsp->num_aio_requests != 0) {
675 * NB. We *MUST* use
676 * talloc_free(fsp->aio_requests[0]),
677 * and *NOT* TALLOC_FREE() here, as
678 * TALLOC_FREE(fsp->aio_requests[0])
679 * will overwrite any new contents of
680 * fsp->aio_requests[0] that were
681 * copied into it via the destructor
682 * aio_del_req_from_fsp().
684 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
686 talloc_free(fsp->aio_requests[0]);
688 return;
691 DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
692 smb_panic("can not close with outstanding aio requests");
693 return;
696 /****************************************************************************
697 Close a file.
699 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
700 printing and magic scripts are only run on normal close.
701 delete on close is done on normal and shutdown close.
702 ****************************************************************************/
704 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
705 enum file_close_type close_type)
707 NTSTATUS status = NT_STATUS_OK;
708 NTSTATUS tmp;
709 connection_struct *conn = fsp->conn;
710 bool is_durable = false;
712 SMB_ASSERT(fsp->fsp_flags.is_fsa);
714 assert_no_pending_aio(fsp, close_type);
716 while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
717 smbd_smb1_brl_finish_by_req(
718 fsp->blocked_smb1_lock_reqs[0],
719 NT_STATUS_RANGE_NOT_LOCKED);
723 * If we're flushing on a close we can get a write
724 * error here, we must remember this.
727 if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
728 is_durable = fsp->op->global->durable;
731 if (close_type != SHUTDOWN_CLOSE) {
732 is_durable = false;
735 if (is_durable) {
736 DATA_BLOB new_cookie = data_blob_null;
738 tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
739 fsp->op->global->backend_cookie,
740 fsp->op,
741 &new_cookie);
742 if (NT_STATUS_IS_OK(tmp)) {
743 struct timeval tv;
744 NTTIME now;
746 if (req != NULL) {
747 tv = req->request_time;
748 } else {
749 tv = timeval_current();
751 now = timeval_to_nttime(&tv);
753 data_blob_free(&fsp->op->global->backend_cookie);
754 fsp->op->global->backend_cookie = new_cookie;
756 fsp->op->compat = NULL;
757 tmp = smbXsrv_open_close(fsp->op, now);
758 if (!NT_STATUS_IS_OK(tmp)) {
759 DEBUG(1, ("Failed to update smbXsrv_open "
760 "record when disconnecting durable "
761 "handle for file %s: %s - "
762 "proceeding with normal close\n",
763 fsp_str_dbg(fsp), nt_errstr(tmp)));
765 scavenger_schedule_disconnected(fsp);
766 } else {
767 DEBUG(1, ("Failed to disconnect durable handle for "
768 "file %s: %s - proceeding with normal "
769 "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
771 if (!NT_STATUS_IS_OK(tmp)) {
772 is_durable = false;
776 if (is_durable) {
778 * This is the case where we successfully disconnected
779 * a durable handle and closed the underlying file.
780 * In all other cases, we proceed with a genuine close.
782 DEBUG(10, ("%s disconnected durable handle for file %s\n",
783 conn->session_info->unix_info->unix_name,
784 fsp_str_dbg(fsp)));
785 return NT_STATUS_OK;
788 if (fsp->op != NULL) {
790 * Make sure the handle is not marked as durable anymore
792 fsp->op->global->durable = false;
795 /* If this is an old DOS or FCB open and we have multiple opens on
796 the same handle we only have one share mode. Ensure we only remove
797 the share mode on the last close. */
799 if (fh_get_refcount(fsp->fh) == 1) {
800 /* Should we return on error here... ? */
801 tmp = close_remove_share_mode(fsp, close_type);
802 status = ntstatus_keeperror(status, tmp);
805 locking_close_file(fsp, close_type);
808 * Ensure pending modtime is set before closing underlying fd.
811 tmp = update_write_time_on_close(fsp);
812 if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
814 * Someone renamed the file or a parent directory containing
815 * this file. We can't do anything about this, eat the error.
817 tmp = NT_STATUS_OK;
819 status = ntstatus_keeperror(status, tmp);
821 tmp = fd_close(fsp);
822 status = ntstatus_keeperror(status, tmp);
824 /* check for magic scripts */
825 if (close_type == NORMAL_CLOSE) {
826 tmp = check_magic(fsp);
827 status = ntstatus_keeperror(status, tmp);
830 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
831 conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
832 conn->num_files_open - 1,
833 nt_errstr(status) ));
835 return status;
837 /****************************************************************************
838 Function used by reply_rmdir to delete an entire directory
839 tree recursively. Return True on ok, False on fail.
840 ****************************************************************************/
842 NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
843 connection_struct *conn,
844 struct smb_filename *smb_dname)
846 const char *dname = NULL;
847 char *talloced = NULL;
848 long offset = 0;
849 SMB_STRUCT_STAT st;
850 struct smb_Dir *dir_hnd = NULL;
851 struct files_struct *dirfsp = NULL;
852 int retval;
853 NTSTATUS status = NT_STATUS_OK;
855 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
857 status = OpenDir(talloc_tos(),
858 conn,
859 smb_dname,
860 NULL,
862 &dir_hnd);
863 if (!NT_STATUS_IS_OK(status)) {
864 return status;
867 dirfsp = dir_hnd_fetch_fsp(dir_hnd);
869 while ((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
870 struct smb_filename *atname = NULL;
871 struct smb_filename *smb_dname_full = NULL;
872 char *fullname = NULL;
873 bool do_break = true;
874 int unlink_flags = 0;
876 if (ISDOT(dname) || ISDOTDOT(dname)) {
877 TALLOC_FREE(talloced);
878 continue;
881 /* Construct the full name. */
882 fullname = talloc_asprintf(ctx,
883 "%s/%s",
884 smb_dname->base_name,
885 dname);
886 if (!fullname) {
887 status = NT_STATUS_NO_MEMORY;
888 goto err_break;
891 smb_dname_full = synthetic_smb_fname(talloc_tos(),
892 fullname,
893 NULL,
894 NULL,
895 smb_dname->twrp,
896 smb_dname->flags);
897 if (smb_dname_full == NULL) {
898 status = NT_STATUS_NO_MEMORY;
899 goto err_break;
902 if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
903 status = map_nt_error_from_unix(errno);
904 goto err_break;
907 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
908 status = recursive_rmdir(ctx, conn, smb_dname_full);
909 if (!NT_STATUS_IS_OK(status)) {
910 goto err_break;
912 unlink_flags = AT_REMOVEDIR;
915 status = synthetic_pathref(talloc_tos(),
916 dirfsp,
917 dname,
918 NULL,
919 &smb_dname_full->st,
920 smb_dname_full->twrp,
921 smb_dname_full->flags,
922 &atname);
923 if (!NT_STATUS_IS_OK(status)) {
924 goto err_break;
927 if (!is_visible_fsp(atname->fsp)) {
928 TALLOC_FREE(smb_dname_full);
929 TALLOC_FREE(fullname);
930 TALLOC_FREE(talloced);
931 TALLOC_FREE(atname);
932 continue;
935 retval = SMB_VFS_UNLINKAT(conn,
936 dirfsp,
937 atname,
938 unlink_flags);
939 if (retval != 0) {
940 status = map_nt_error_from_unix(errno);
941 goto err_break;
944 /* Successful iteration. */
945 do_break = false;
947 err_break:
948 TALLOC_FREE(smb_dname_full);
949 TALLOC_FREE(fullname);
950 TALLOC_FREE(talloced);
951 TALLOC_FREE(atname);
952 if (do_break) {
953 break;
956 TALLOC_FREE(dir_hnd);
957 return status;
960 /****************************************************************************
961 The internals of the rmdir code - called elsewhere.
962 ****************************************************************************/
964 static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
966 struct connection_struct *conn = fsp->conn;
967 struct smb_filename *smb_dname = fsp->fsp_name;
968 struct smb_filename *parent_fname = NULL;
969 struct smb_filename *at_fname = NULL;
970 SMB_STRUCT_STAT st;
971 const char *dname = NULL;
972 char *talloced = NULL;
973 long dirpos = 0;
974 struct smb_Dir *dir_hnd = NULL;
975 struct files_struct *dirfsp = NULL;
976 int unlink_flags = 0;
977 NTSTATUS status;
978 int ret;
980 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
982 status = parent_pathref(talloc_tos(),
983 conn->cwd_fsp,
984 fsp->fsp_name,
985 &parent_fname,
986 &at_fname);
987 if (!NT_STATUS_IS_OK(status)) {
988 return status;
992 * Todo: use SMB_VFS_STATX() once it's available.
995 /* Might be a symlink. */
996 ret = SMB_VFS_LSTAT(conn, smb_dname);
997 if (ret != 0) {
998 TALLOC_FREE(parent_fname);
999 return map_nt_error_from_unix(errno);
1002 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
1003 /* Is what it points to a directory ? */
1004 ret = SMB_VFS_STAT(conn, smb_dname);
1005 if (ret != 0) {
1006 TALLOC_FREE(parent_fname);
1007 return map_nt_error_from_unix(errno);
1009 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
1010 TALLOC_FREE(parent_fname);
1011 return NT_STATUS_NOT_A_DIRECTORY;
1013 } else {
1014 unlink_flags = AT_REMOVEDIR;
1017 ret = SMB_VFS_UNLINKAT(conn,
1018 parent_fname->fsp,
1019 at_fname,
1020 unlink_flags);
1021 if (ret == 0) {
1022 TALLOC_FREE(parent_fname);
1023 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1024 FILE_NOTIFY_CHANGE_DIR_NAME,
1025 smb_dname->base_name);
1026 return NT_STATUS_OK;
1029 if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1030 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1031 "%s\n", smb_fname_str_dbg(smb_dname),
1032 strerror(errno)));
1033 TALLOC_FREE(parent_fname);
1034 return map_nt_error_from_unix(errno);
1038 * Here we know the initial directory unlink failed with
1039 * ENOTEMPTY or EEXIST so we know there are objects within.
1040 * If we don't have permission to delete files non
1041 * visible to the client just fail the directory delete.
1044 if (!lp_delete_veto_files(SNUM(conn))) {
1045 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1046 goto err;
1050 * Check to see if the only thing in this directory are
1051 * files non-visible to the client. If not, fail the delete.
1054 status = OpenDir(talloc_tos(),
1055 conn,
1056 smb_dname,
1057 NULL,
1059 &dir_hnd);
1060 if (!NT_STATUS_IS_OK(status)) {
1062 * Note, we deliberately squash the error here
1063 * to avoid leaking information about what we
1064 * can't delete.
1066 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1067 goto err;
1070 dirfsp = dir_hnd_fetch_fsp(dir_hnd);
1072 while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
1073 struct smb_filename *smb_dname_full = NULL;
1074 struct smb_filename *direntry_fname = NULL;
1075 char *fullname = NULL;
1076 int retval;
1078 if (ISDOT(dname) || ISDOTDOT(dname)) {
1079 TALLOC_FREE(talloced);
1080 continue;
1082 if (IS_VETO_PATH(conn, dname)) {
1083 TALLOC_FREE(talloced);
1084 continue;
1087 fullname = talloc_asprintf(talloc_tos(),
1088 "%s/%s",
1089 smb_dname->base_name,
1090 dname);
1092 if (fullname == NULL) {
1093 TALLOC_FREE(talloced);
1094 status = NT_STATUS_NO_MEMORY;
1095 goto err;
1098 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1099 fullname,
1100 NULL,
1101 NULL,
1102 smb_dname->twrp,
1103 smb_dname->flags);
1104 if (smb_dname_full == NULL) {
1105 TALLOC_FREE(talloced);
1106 TALLOC_FREE(fullname);
1107 status = NT_STATUS_NO_MEMORY;
1108 goto err;
1111 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1112 if (retval != 0) {
1113 status = map_nt_error_from_unix(errno);
1114 TALLOC_FREE(talloced);
1115 TALLOC_FREE(fullname);
1116 TALLOC_FREE(smb_dname_full);
1117 goto err;
1120 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1121 /* Could it be an msdfs link ? */
1122 if (lp_host_msdfs() &&
1123 lp_msdfs_root(SNUM(conn))) {
1124 struct smb_filename *smb_atname;
1125 smb_atname = synthetic_smb_fname(talloc_tos(),
1126 dname,
1127 NULL,
1128 &smb_dname_full->st,
1129 fsp->fsp_name->twrp,
1130 fsp->fsp_name->flags);
1131 if (smb_atname == NULL) {
1132 TALLOC_FREE(talloced);
1133 TALLOC_FREE(fullname);
1134 TALLOC_FREE(smb_dname_full);
1135 status = NT_STATUS_NO_MEMORY;
1136 goto err;
1138 if (is_msdfs_link(fsp, smb_atname)) {
1139 TALLOC_FREE(talloced);
1140 TALLOC_FREE(fullname);
1141 TALLOC_FREE(smb_dname_full);
1142 TALLOC_FREE(smb_atname);
1143 DBG_DEBUG("got msdfs link name %s "
1144 "- can't delete directory %s\n",
1145 dname,
1146 fsp_str_dbg(fsp));
1147 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1148 goto err;
1150 TALLOC_FREE(smb_atname);
1153 /* Not a DFS link - could it be a dangling symlink ? */
1154 retval = SMB_VFS_STAT(conn, smb_dname_full);
1155 if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
1157 * Dangling symlink.
1158 * Allow delete as "delete veto files = yes"
1160 TALLOC_FREE(talloced);
1161 TALLOC_FREE(fullname);
1162 TALLOC_FREE(smb_dname_full);
1163 continue;
1166 DBG_DEBUG("got symlink name %s - "
1167 "can't delete directory %s\n",
1168 dname,
1169 fsp_str_dbg(fsp));
1170 TALLOC_FREE(talloced);
1171 TALLOC_FREE(fullname);
1172 TALLOC_FREE(smb_dname_full);
1173 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1174 goto err;
1177 /* Not a symlink, get a pathref. */
1178 status = synthetic_pathref(talloc_tos(),
1179 dirfsp,
1180 dname,
1181 NULL,
1182 &smb_dname_full->st,
1183 smb_dname->twrp,
1184 smb_dname->flags,
1185 &direntry_fname);
1186 if (!NT_STATUS_IS_OK(status)) {
1187 TALLOC_FREE(talloced);
1188 TALLOC_FREE(fullname);
1189 TALLOC_FREE(smb_dname_full);
1190 goto err;
1193 if (!is_visible_fsp(direntry_fname->fsp)) {
1194 TALLOC_FREE(talloced);
1195 TALLOC_FREE(fullname);
1196 TALLOC_FREE(smb_dname_full);
1197 TALLOC_FREE(direntry_fname);
1198 continue;
1202 * We found a client visible name.
1203 * We cannot delete this directory.
1205 DBG_DEBUG("got name %s - "
1206 "can't delete directory %s\n",
1207 dname,
1208 fsp_str_dbg(fsp));
1209 TALLOC_FREE(talloced);
1210 TALLOC_FREE(fullname);
1211 TALLOC_FREE(smb_dname_full);
1212 TALLOC_FREE(direntry_fname);
1213 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1214 goto err;
1217 /* Do a recursive delete. */
1218 RewindDir(dir_hnd,&dirpos);
1220 while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
1221 struct smb_filename *direntry_fname = NULL;
1222 struct smb_filename *smb_dname_full = NULL;
1223 char *fullname = NULL;
1224 bool do_break = true;
1225 int retval;
1227 if (ISDOT(dname) || ISDOTDOT(dname)) {
1228 TALLOC_FREE(talloced);
1229 continue;
1232 fullname = talloc_asprintf(ctx,
1233 "%s/%s",
1234 smb_dname->base_name,
1235 dname);
1237 if (fullname == NULL) {
1238 status = NT_STATUS_NO_MEMORY;
1239 goto err_break;
1242 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1243 fullname,
1244 NULL,
1245 NULL,
1246 smb_dname->twrp,
1247 smb_dname->flags);
1248 if (smb_dname_full == NULL) {
1249 status = NT_STATUS_NO_MEMORY;
1250 goto err_break;
1254 * Todo: use SMB_VFS_STATX() once that's available.
1257 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1258 if (retval != 0) {
1259 status = map_nt_error_from_unix(errno);
1260 goto err_break;
1264 * We are only dealing with VETO'ed objects
1265 * here. If it's a symlink, just delete the
1266 * link without caring what it is pointing
1267 * to.
1269 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1270 direntry_fname = synthetic_smb_fname(talloc_tos(),
1271 dname,
1272 NULL,
1273 &smb_dname_full->st,
1274 smb_dname->twrp,
1275 smb_dname->flags);
1276 if (direntry_fname == NULL) {
1277 status = NT_STATUS_NO_MEMORY;
1278 goto err_break;
1280 } else {
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 goto err_break;
1293 if (!is_visible_fsp(direntry_fname->fsp)) {
1294 TALLOC_FREE(fullname);
1295 TALLOC_FREE(smb_dname_full);
1296 TALLOC_FREE(talloced);
1297 TALLOC_FREE(direntry_fname);
1298 continue;
1302 unlink_flags = 0;
1304 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1305 status = recursive_rmdir(ctx, conn, smb_dname_full);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 goto err_break;
1309 unlink_flags = AT_REMOVEDIR;
1312 retval = SMB_VFS_UNLINKAT(conn,
1313 dirfsp,
1314 direntry_fname,
1315 unlink_flags);
1316 if (retval != 0) {
1317 status = map_nt_error_from_unix(errno);
1318 goto err_break;
1321 /* Successful iteration. */
1322 do_break = false;
1324 err_break:
1325 TALLOC_FREE(fullname);
1326 TALLOC_FREE(smb_dname_full);
1327 TALLOC_FREE(talloced);
1328 TALLOC_FREE(direntry_fname);
1329 if (do_break) {
1330 break;
1334 /* If we get here, we know NT_STATUS_IS_OK(status) */
1335 SMB_ASSERT(NT_STATUS_IS_OK(status));
1337 /* Retry the rmdir */
1338 ret = SMB_VFS_UNLINKAT(conn,
1339 parent_fname->fsp,
1340 at_fname,
1341 AT_REMOVEDIR);
1342 if (ret != 0) {
1343 status = map_nt_error_from_unix(errno);
1346 err:
1348 TALLOC_FREE(dir_hnd);
1349 TALLOC_FREE(parent_fname);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 DBG_NOTICE("couldn't remove directory %s : "
1353 "%s\n", smb_fname_str_dbg(smb_dname),
1354 nt_errstr(status));
1355 return status;
1358 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1359 FILE_NOTIFY_CHANGE_DIR_NAME,
1360 smb_dname->base_name);
1362 return status;
1365 /****************************************************************************
1366 Close a directory opened by an NT SMB call.
1367 ****************************************************************************/
1369 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1370 enum file_close_type close_type)
1372 struct share_mode_lock *lck = NULL;
1373 bool delete_dir = False;
1374 NTSTATUS status = NT_STATUS_OK;
1375 NTSTATUS status1 = NT_STATUS_OK;
1376 const struct security_token *del_nt_token = NULL;
1377 const struct security_unix_token *del_token = NULL;
1378 NTSTATUS notify_status;
1380 SMB_ASSERT(fsp->fsp_flags.is_fsa);
1382 if (fsp->conn->sconn->using_smb2) {
1383 notify_status = NT_STATUS_NOTIFY_CLEANUP;
1384 } else {
1385 notify_status = NT_STATUS_OK;
1388 assert_no_pending_aio(fsp, close_type);
1391 * NT can set delete_on_close of the last open
1392 * reference to a directory also.
1395 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1396 if (lck == NULL) {
1397 DEBUG(0, ("close_directory: Could not get share mode lock for "
1398 "%s\n", fsp_str_dbg(fsp)));
1399 return NT_STATUS_INVALID_PARAMETER;
1402 if (fsp->fsp_flags.initial_delete_on_close) {
1403 /* Initial delete on close was set - for
1404 * directories we don't care if anyone else
1405 * wrote a real delete on close. */
1407 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
1408 fsp->fsp_name->base_name);
1409 set_delete_on_close_lck(fsp, lck,
1410 fsp->conn->session_info->security_token,
1411 fsp->conn->session_info->unix_token);
1412 fsp->fsp_flags.delete_on_close = true;
1415 delete_dir = get_delete_on_close_token(
1416 lck, fsp->name_hash, &del_nt_token, &del_token) &&
1417 !has_other_nonposix_opens(lck, fsp);
1419 if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
1420 delete_dir) {
1422 /* Become the user who requested the delete. */
1424 if (!push_sec_ctx()) {
1425 smb_panic("close_directory: failed to push sec_ctx.\n");
1428 set_sec_ctx(del_token->uid,
1429 del_token->gid,
1430 del_token->ngroups,
1431 del_token->groups,
1432 del_nt_token);
1434 if (!del_share_mode(lck, fsp)) {
1435 DEBUG(0, ("close_directory: Could not delete share entry for "
1436 "%s\n", fsp_str_dbg(fsp)));
1439 TALLOC_FREE(lck);
1441 if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1442 && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1444 status = delete_all_streams(fsp->conn, fsp->fsp_name);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 DEBUG(5, ("delete_all_streams failed: %s\n",
1447 nt_errstr(status)));
1448 /* unbecome user. */
1449 pop_sec_ctx();
1450 return status;
1454 status = rmdir_internals(talloc_tos(), fsp);
1456 DEBUG(5,("close_directory: %s. Delete on close was set - "
1457 "deleting directory returned %s.\n",
1458 fsp_str_dbg(fsp), nt_errstr(status)));
1460 /* unbecome user. */
1461 pop_sec_ctx();
1464 * Ensure we remove any change notify requests that would
1465 * now fail as the directory has been deleted.
1468 if (NT_STATUS_IS_OK(status)) {
1469 notify_status = NT_STATUS_DELETE_PENDING;
1471 } else {
1472 if (!del_share_mode(lck, fsp)) {
1473 DEBUG(0, ("close_directory: Could not delete share entry for "
1474 "%s\n", fsp_str_dbg(fsp)));
1477 TALLOC_FREE(lck);
1480 remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1482 status1 = fd_close(fsp);
1484 if (!NT_STATUS_IS_OK(status1)) {
1485 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1486 fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1487 strerror(errno)));
1490 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1491 status = status1;
1493 return status;
1496 /****************************************************************************
1497 Rundown all SMB-related dependencies of a files struct
1498 ****************************************************************************/
1500 NTSTATUS close_file_smb(struct smb_request *req,
1501 struct files_struct *fsp,
1502 enum file_close_type close_type)
1504 NTSTATUS status;
1507 * This fsp can never be an internal dirfsp. They must
1508 * be explicitly closed by TALLOC_FREE of the dir handle.
1510 SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1513 * Never call directly on a base fsp
1515 SMB_ASSERT(fsp->stream_fsp == NULL);
1517 if (fsp->fake_file_handle != NULL) {
1518 status = close_fake_file(req, fsp);
1519 } else if (fsp->print_file != NULL) {
1520 /* FIXME: return spool errors */
1521 print_spool_end(fsp, close_type);
1522 fd_close(fsp);
1523 status = NT_STATUS_OK;
1524 } else if (!fsp->fsp_flags.is_fsa) {
1525 if (close_type == NORMAL_CLOSE) {
1526 DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1527 "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1528 fsp_str_dbg(fsp),
1529 fsp->fsp_flags.is_fsa,
1530 fsp->fsp_flags.is_pathref,
1531 fsp->fsp_flags.is_directory);
1533 SMB_ASSERT(close_type != NORMAL_CLOSE);
1534 fd_close(fsp);
1535 status = NT_STATUS_OK;
1536 } else if (fsp->fsp_flags.is_directory) {
1537 status = close_directory(req, fsp, close_type);
1538 } else {
1539 status = close_normal_file(req, fsp, close_type);
1542 if (fsp_is_alternate_stream(fsp)) {
1544 * fsp was a stream, its base_fsp can't be a stream
1545 * as well
1547 SMB_ASSERT(!fsp_is_alternate_stream(fsp->base_fsp));
1550 * There's a 1:1 relationship between fsp and a base_fsp
1552 SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1555 * Make base_fsp look standalone now
1557 fsp->base_fsp->stream_fsp = NULL;
1559 close_file_free(req, &fsp->base_fsp, close_type);
1562 fsp_unbind_smb(req, fsp);
1564 return status;
1567 NTSTATUS close_file_free(struct smb_request *req,
1568 struct files_struct **_fsp,
1569 enum file_close_type close_type)
1571 struct files_struct *fsp = *_fsp;
1572 NTSTATUS status;
1574 status = close_file_smb(req, fsp, close_type);
1576 file_free(req, fsp);
1577 *_fsp = NULL;
1579 return status;
1582 /****************************************************************************
1583 Deal with an (authorized) message to close a file given the share mode
1584 entry.
1585 ****************************************************************************/
1587 void msg_close_file(struct messaging_context *msg_ctx,
1588 void *private_data,
1589 uint32_t msg_type,
1590 struct server_id server_id,
1591 DATA_BLOB *data)
1593 files_struct *fsp = NULL;
1594 struct file_id id;
1595 struct share_mode_entry e;
1596 struct smbd_server_connection *sconn =
1597 talloc_get_type_abort(private_data,
1598 struct smbd_server_connection);
1600 message_to_share_mode_entry(&id, &e, (char *)data->data);
1602 if(DEBUGLVL(10)) {
1603 char *sm_str = share_mode_str(NULL, 0, &id, &e);
1604 if (!sm_str) {
1605 smb_panic("talloc failed");
1607 DEBUG(10,("msg_close_file: got request to close share mode "
1608 "entry %s\n", sm_str));
1609 TALLOC_FREE(sm_str);
1612 fsp = file_find_dif(sconn, id, e.share_file_id);
1613 if (!fsp) {
1614 DEBUG(10,("msg_close_file: failed to find file.\n"));
1615 return;
1617 close_file_free(NULL, &fsp, NORMAL_CLOSE);