s3-krb: Reformat and add doxygen comment to decode_pac_data()
[Samba.git] / source3 / smbd / close.c
blobfad960149142eb66b2c642492485be5011e112ff
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 "printing.h"
24 #include "librpc/gen_ndr/messaging.h"
25 #include "smbd/globals.h"
27 /****************************************************************************
28 Run a file if it is a magic script.
29 ****************************************************************************/
31 static NTSTATUS check_magic(struct files_struct *fsp)
33 int ret;
34 const char *magic_output = NULL;
35 SMB_STRUCT_STAT st;
36 int tmp_fd, outfd;
37 TALLOC_CTX *ctx = NULL;
38 const char *p;
39 struct connection_struct *conn = fsp->conn;
40 char *fname = NULL;
41 NTSTATUS status;
43 if (!*lp_magicscript(SNUM(conn))) {
44 return NT_STATUS_OK;
47 DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));
49 ctx = talloc_stackframe();
51 fname = fsp->fsp_name->base_name;
53 if (!(p = strrchr_m(fname,'/'))) {
54 p = fname;
55 } else {
56 p++;
59 if (!strequal(lp_magicscript(SNUM(conn)),p)) {
60 status = NT_STATUS_OK;
61 goto out;
64 if (*lp_magicoutput(SNUM(conn))) {
65 magic_output = lp_magicoutput(SNUM(conn));
66 } else {
67 magic_output = talloc_asprintf(ctx,
68 "%s.out",
69 fname);
71 if (!magic_output) {
72 status = NT_STATUS_NO_MEMORY;
73 goto out;
76 /* Ensure we don't depend on user's PATH. */
77 p = talloc_asprintf(ctx, "./%s", fname);
78 if (!p) {
79 status = NT_STATUS_NO_MEMORY;
80 goto out;
83 if (chmod(fname, 0755) == -1) {
84 status = map_nt_error_from_unix(errno);
85 goto out;
87 ret = smbrun(p,&tmp_fd);
88 DEBUG(3,("Invoking magic command %s gave %d\n",
89 p,ret));
91 unlink(fname);
92 if (ret != 0 || tmp_fd == -1) {
93 if (tmp_fd != -1) {
94 close(tmp_fd);
96 status = NT_STATUS_UNSUCCESSFUL;
97 goto out;
99 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
100 if (outfd == -1) {
101 int err = errno;
102 close(tmp_fd);
103 status = map_nt_error_from_unix(err);
104 goto out;
107 if (sys_fstat(tmp_fd, &st, false) == -1) {
108 int err = errno;
109 close(tmp_fd);
110 close(outfd);
111 status = map_nt_error_from_unix(err);
112 goto out;
115 if (transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_ex_size) == (SMB_OFF_T)-1) {
116 int err = errno;
117 close(tmp_fd);
118 close(outfd);
119 status = map_nt_error_from_unix(err);
120 goto out;
122 close(tmp_fd);
123 if (close(outfd) == -1) {
124 status = map_nt_error_from_unix(errno);
125 goto out;
128 status = NT_STATUS_OK;
130 out:
131 TALLOC_FREE(ctx);
132 return status;
135 /****************************************************************************
136 Common code to close a file or a directory.
137 ****************************************************************************/
139 static NTSTATUS close_filestruct(files_struct *fsp)
141 NTSTATUS status = NT_STATUS_OK;
143 if (fsp->fh->fd != -1) {
144 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
145 status = map_nt_error_from_unix(errno);
147 delete_write_cache(fsp);
150 return status;
153 /****************************************************************************
154 If any deferred opens are waiting on this close, notify them.
155 ****************************************************************************/
157 static void notify_deferred_opens(struct messaging_context *msg_ctx,
158 struct share_mode_lock *lck)
160 int i;
162 if (!should_notify_deferred_opens()) {
163 return;
166 for (i=0; i<lck->num_share_modes; i++) {
167 struct share_mode_entry *e = &lck->share_modes[i];
169 if (!is_deferred_open_entry(e)) {
170 continue;
173 if (procid_is_me(&e->pid)) {
175 * We need to notify ourself to retry the open. Do
176 * this by finding the queued SMB record, moving it to
177 * the head of the queue and changing the wait time to
178 * zero.
180 schedule_deferred_open_message_smb(e->op_mid);
181 } else {
182 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
184 share_mode_entry_to_message(msg, e);
186 messaging_send_buf(msg_ctx, e->pid, MSG_SMB_OPEN_RETRY,
187 (uint8 *)msg,
188 MSG_SMB_SHARE_MODE_ENTRY_SIZE);
193 /****************************************************************************
194 Delete all streams
195 ****************************************************************************/
197 NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
199 struct stream_struct *stream_info;
200 int i;
201 unsigned int num_streams;
202 TALLOC_CTX *frame = talloc_stackframe();
203 NTSTATUS status;
205 status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
206 &num_streams, &stream_info);
208 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
209 DEBUG(10, ("no streams around\n"));
210 TALLOC_FREE(frame);
211 return NT_STATUS_OK;
214 if (!NT_STATUS_IS_OK(status)) {
215 DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
216 nt_errstr(status)));
217 goto fail;
220 DEBUG(10, ("delete_all_streams found %d streams\n",
221 num_streams));
223 if (num_streams == 0) {
224 TALLOC_FREE(frame);
225 return NT_STATUS_OK;
228 for (i=0; i<num_streams; i++) {
229 int res;
230 struct smb_filename *smb_fname_stream = NULL;
232 if (strequal(stream_info[i].name, "::$DATA")) {
233 continue;
236 status = create_synthetic_smb_fname(talloc_tos(), fname,
237 stream_info[i].name, NULL,
238 &smb_fname_stream);
240 if (!NT_STATUS_IS_OK(status)) {
241 DEBUG(0, ("talloc_aprintf failed\n"));
242 goto fail;
245 res = SMB_VFS_UNLINK(conn, smb_fname_stream);
247 if (res == -1) {
248 status = map_nt_error_from_unix(errno);
249 DEBUG(10, ("Could not delete stream %s: %s\n",
250 smb_fname_str_dbg(smb_fname_stream),
251 strerror(errno)));
252 TALLOC_FREE(smb_fname_stream);
253 break;
255 TALLOC_FREE(smb_fname_stream);
258 fail:
259 TALLOC_FREE(frame);
260 return status;
263 /****************************************************************************
264 Deal with removing a share mode on last close.
265 ****************************************************************************/
267 static NTSTATUS close_remove_share_mode(files_struct *fsp,
268 enum file_close_type close_type)
270 connection_struct *conn = fsp->conn;
271 bool delete_file = false;
272 bool changed_user = false;
273 struct share_mode_lock *lck = NULL;
274 NTSTATUS status = NT_STATUS_OK;
275 NTSTATUS tmp_status;
276 struct file_id id;
278 /* Ensure any pending write time updates are done. */
279 if (fsp->update_write_time_event) {
280 update_write_time_handler(smbd_event_context(),
281 fsp->update_write_time_event,
282 timeval_current(),
283 (void *)fsp);
287 * Lock the share entries, and determine if we should delete
288 * on close. If so delete whilst the lock is still in effect.
289 * This prevents race conditions with the file being created. JRA.
292 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
293 NULL);
295 if (lck == NULL) {
296 DEBUG(0, ("close_remove_share_mode: Could not get share mode "
297 "lock for file %s\n", fsp_str_dbg(fsp)));
298 status = NT_STATUS_INVALID_PARAMETER;
299 goto done;
302 if (fsp->write_time_forced) {
303 DEBUG(10,("close_remove_share_mode: write time forced "
304 "for file %s\n",
305 fsp_str_dbg(fsp)));
306 set_close_write_time(fsp, lck->changed_write_time);
307 } else if (fsp->update_write_time_on_close) {
308 /* Someone had a pending write. */
309 if (null_timespec(fsp->close_write_time)) {
310 DEBUG(10,("close_remove_share_mode: update to current time "
311 "for file %s\n",
312 fsp_str_dbg(fsp)));
313 /* Update to current time due to "normal" write. */
314 set_close_write_time(fsp, timespec_current());
315 } else {
316 DEBUG(10,("close_remove_share_mode: write time pending "
317 "for file %s\n",
318 fsp_str_dbg(fsp)));
319 /* Update to time set on close call. */
320 set_close_write_time(fsp, fsp->close_write_time);
324 if (!del_share_mode(lck, fsp)) {
325 DEBUG(0, ("close_remove_share_mode: Could not delete share "
326 "entry for file %s\n",
327 fsp_str_dbg(fsp)));
330 if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
331 bool became_user = False;
333 /* Initial delete on close was set and no one else
334 * wrote a real delete on close. */
336 if (get_current_vuid(conn) != fsp->vuid) {
337 become_user(conn, fsp->vuid);
338 became_user = True;
340 fsp->delete_on_close = true;
341 set_delete_on_close_lck(lck, True, get_current_utok(conn));
342 if (became_user) {
343 unbecome_user();
347 delete_file = lck->delete_on_close;
349 if (delete_file) {
350 int i;
351 /* See if others still have the file open. If this is the
352 * case, then don't delete. If all opens are POSIX delete now. */
353 for (i=0; i<lck->num_share_modes; i++) {
354 struct share_mode_entry *e = &lck->share_modes[i];
355 if (is_valid_share_mode_entry(e)) {
356 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
357 continue;
359 delete_file = False;
360 break;
365 /* Notify any deferred opens waiting on this close. */
366 notify_deferred_opens(conn->sconn->msg_ctx, lck);
367 reply_to_oplock_break_requests(fsp);
370 * NT can set delete_on_close of the last open
371 * reference to a file.
374 if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE)
375 || !delete_file
376 || (lck->delete_token == NULL)) {
377 TALLOC_FREE(lck);
378 return NT_STATUS_OK;
382 * Ok, we have to delete the file
385 DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
386 "- deleting file.\n", fsp_str_dbg(fsp)));
389 * Don't try to update the write time when we delete the file
391 fsp->update_write_time_on_close = false;
393 if (!unix_token_equal(lck->delete_token, get_current_utok(conn))) {
394 /* Become the user who requested the delete. */
396 DEBUG(5,("close_remove_share_mode: file %s. "
397 "Change user to uid %u\n",
398 fsp_str_dbg(fsp),
399 (unsigned int)lck->delete_token->uid));
401 if (!push_sec_ctx()) {
402 smb_panic("close_remove_share_mode: file %s. failed to push "
403 "sec_ctx.\n");
406 set_sec_ctx(lck->delete_token->uid,
407 lck->delete_token->gid,
408 lck->delete_token->ngroups,
409 lck->delete_token->groups,
410 NULL);
412 changed_user = true;
415 /* We can only delete the file if the name we have is still valid and
416 hasn't been renamed. */
418 tmp_status = vfs_stat_fsp(fsp);
419 if (!NT_STATUS_IS_OK(tmp_status)) {
420 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
421 "was set and stat failed with error %s\n",
422 fsp_str_dbg(fsp), nt_errstr(tmp_status)));
424 * Don't save the errno here, we ignore this error
426 goto done;
429 id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
431 if (!file_id_equal(&fsp->file_id, &id)) {
432 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
433 "was set and dev and/or inode does not match\n",
434 fsp_str_dbg(fsp)));
435 DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
436 "stat file_id %s\n",
437 fsp_str_dbg(fsp),
438 file_id_string_tos(&fsp->file_id),
439 file_id_string_tos(&id)));
441 * Don't save the errno here, we ignore this error
443 goto done;
446 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
447 && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
449 status = delete_all_streams(conn, fsp->fsp_name->base_name);
451 if (!NT_STATUS_IS_OK(status)) {
452 DEBUG(5, ("delete_all_streams failed: %s\n",
453 nt_errstr(status)));
454 goto done;
459 if (SMB_VFS_UNLINK(conn, fsp->fsp_name) != 0) {
461 * This call can potentially fail as another smbd may
462 * have had the file open with delete on close set and
463 * deleted it when its last reference to this file
464 * went away. Hence we log this but not at debug level
465 * zero.
468 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
469 "was set and unlink failed with error %s\n",
470 fsp_str_dbg(fsp), strerror(errno)));
472 status = map_nt_error_from_unix(errno);
475 notify_fname(conn, NOTIFY_ACTION_REMOVED,
476 FILE_NOTIFY_CHANGE_FILE_NAME,
477 fsp->fsp_name->base_name);
479 /* As we now have POSIX opens which can unlink
480 * with other open files we may have taken
481 * this code path with more than one share mode
482 * entry - ensure we only delete once by resetting
483 * the delete on close flag. JRA.
486 fsp->delete_on_close = false;
487 set_delete_on_close_lck(lck, False, NULL);
489 done:
491 if (changed_user) {
492 /* unbecome user. */
493 pop_sec_ctx();
496 TALLOC_FREE(lck);
497 return status;
500 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
502 DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
504 if (null_timespec(ts)) {
505 return;
507 fsp->write_time_forced = false;
508 fsp->update_write_time_on_close = true;
509 fsp->close_write_time = ts;
512 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
514 struct smb_file_time ft;
515 NTSTATUS status;
516 struct share_mode_lock *lck = NULL;
518 ZERO_STRUCT(ft);
520 if (!fsp->update_write_time_on_close) {
521 return NT_STATUS_OK;
524 if (null_timespec(fsp->close_write_time)) {
525 fsp->close_write_time = timespec_current();
528 /* Ensure we have a valid stat struct for the source. */
529 status = vfs_stat_fsp(fsp);
530 if (!NT_STATUS_IS_OK(status)) {
531 return status;
534 if (!VALID_STAT(fsp->fsp_name->st)) {
535 /* if it doesn't seem to be a real file */
536 return NT_STATUS_OK;
539 /* On close if we're changing the real file time we
540 * must update it in the open file db too. */
541 (void)set_write_time(fsp->file_id, fsp->close_write_time);
543 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL);
544 if (lck) {
545 /* Close write times overwrite sticky write times
546 so we must replace any sticky write time here. */
547 if (!null_timespec(lck->changed_write_time)) {
548 (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
550 TALLOC_FREE(lck);
553 ft.mtime = fsp->close_write_time;
554 status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
555 if (!NT_STATUS_IS_OK(status)) {
556 return status;
559 return status;
562 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
564 if (!NT_STATUS_IS_OK(s1)) {
565 return s1;
567 return s2;
570 /****************************************************************************
571 Close a file.
573 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
574 printing and magic scripts are only run on normal close.
575 delete on close is done on normal and shutdown close.
576 ****************************************************************************/
578 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
579 enum file_close_type close_type)
581 NTSTATUS status = NT_STATUS_OK;
582 NTSTATUS tmp;
583 connection_struct *conn = fsp->conn;
585 if (close_type == ERROR_CLOSE) {
586 cancel_aio_by_fsp(fsp);
587 } else {
589 * If we're finishing async io on a close we can get a write
590 * error here, we must remember this.
592 int ret = wait_for_aio_completion(fsp);
593 if (ret) {
594 status = ntstatus_keeperror(
595 status, map_nt_error_from_unix(ret));
600 * If we're flushing on a close we can get a write
601 * error here, we must remember this.
604 tmp = close_filestruct(fsp);
605 status = ntstatus_keeperror(status, tmp);
607 if (fsp->print_file) {
608 /* FIXME: return spool errors */
609 print_spool_end(fsp, close_type);
610 file_free(req, fsp);
611 return NT_STATUS_OK;
614 /* Remove the oplock before potentially deleting the file. */
615 if(fsp->oplock_type) {
616 release_file_oplock(fsp);
619 /* If this is an old DOS or FCB open and we have multiple opens on
620 the same handle we only have one share mode. Ensure we only remove
621 the share mode on the last close. */
623 if (fsp->fh->ref_count == 1) {
624 /* Should we return on error here... ? */
625 tmp = close_remove_share_mode(fsp, close_type);
626 status = ntstatus_keeperror(status, tmp);
629 locking_close_file(conn->sconn->msg_ctx, fsp, close_type);
631 tmp = fd_close(fsp);
632 status = ntstatus_keeperror(status, tmp);
634 /* check for magic scripts */
635 if (close_type == NORMAL_CLOSE) {
636 tmp = check_magic(fsp);
637 status = ntstatus_keeperror(status, tmp);
641 * Ensure pending modtime is set after close.
644 tmp = update_write_time_on_close(fsp);
645 if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
646 /* Someone renamed the file or a parent directory containing
647 * this file. We can't do anything about this, we don't have
648 * an "update timestamp by fd" call in POSIX. Eat the error. */
650 tmp = NT_STATUS_OK;
653 status = ntstatus_keeperror(status, tmp);
655 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
656 conn->server_info->unix_name, fsp_str_dbg(fsp),
657 conn->num_files_open - 1,
658 nt_errstr(status) ));
660 file_free(req, fsp);
661 return status;
663 /****************************************************************************
664 Static function used by reply_rmdir to delete an entire directory
665 tree recursively. Return True on ok, False on fail.
666 ****************************************************************************/
668 static bool recursive_rmdir(TALLOC_CTX *ctx,
669 connection_struct *conn,
670 struct smb_filename *smb_dname)
672 const char *dname = NULL;
673 char *talloced = NULL;
674 bool ret = True;
675 long offset = 0;
676 SMB_STRUCT_STAT st;
677 struct smb_Dir *dir_hnd;
679 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
681 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
682 if(dir_hnd == NULL)
683 return False;
685 while((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
686 struct smb_filename *smb_dname_full = NULL;
687 char *fullname = NULL;
688 bool do_break = true;
689 NTSTATUS status;
691 if (ISDOT(dname) || ISDOTDOT(dname)) {
692 TALLOC_FREE(talloced);
693 continue;
696 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
697 false)) {
698 TALLOC_FREE(talloced);
699 continue;
702 /* Construct the full name. */
703 fullname = talloc_asprintf(ctx,
704 "%s/%s",
705 smb_dname->base_name,
706 dname);
707 if (!fullname) {
708 errno = ENOMEM;
709 goto err_break;
712 status = create_synthetic_smb_fname(talloc_tos(), fullname,
713 NULL, NULL,
714 &smb_dname_full);
715 if (!NT_STATUS_IS_OK(status)) {
716 goto err_break;
719 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
720 goto err_break;
723 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
724 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
725 goto err_break;
727 if(SMB_VFS_RMDIR(conn,
728 smb_dname_full->base_name) != 0) {
729 goto err_break;
731 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
732 goto err_break;
735 /* Successful iteration. */
736 do_break = false;
738 err_break:
739 TALLOC_FREE(smb_dname_full);
740 TALLOC_FREE(fullname);
741 TALLOC_FREE(talloced);
742 if (do_break) {
743 ret = false;
744 break;
747 TALLOC_FREE(dir_hnd);
748 return ret;
751 /****************************************************************************
752 The internals of the rmdir code - called elsewhere.
753 ****************************************************************************/
755 static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
757 connection_struct *conn = fsp->conn;
758 struct smb_filename *smb_dname = fsp->fsp_name;
759 int ret;
761 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
763 /* Might be a symlink. */
764 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
765 return map_nt_error_from_unix(errno);
768 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
769 /* Is what it points to a directory ? */
770 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
771 return map_nt_error_from_unix(errno);
773 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
774 return NT_STATUS_NOT_A_DIRECTORY;
776 ret = SMB_VFS_UNLINK(conn, smb_dname);
777 } else {
778 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
780 if (ret == 0) {
781 notify_fname(conn, NOTIFY_ACTION_REMOVED,
782 FILE_NOTIFY_CHANGE_DIR_NAME,
783 smb_dname->base_name);
784 return NT_STATUS_OK;
787 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
789 * Check to see if the only thing in this directory are
790 * vetoed files/directories. If so then delete them and
791 * retry. If we fail to delete any of them (and we *don't*
792 * do a recursive delete) then fail the rmdir.
794 SMB_STRUCT_STAT st;
795 const char *dname = NULL;
796 char *talloced = NULL;
797 long dirpos = 0;
798 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
799 smb_dname->base_name, NULL,
802 if(dir_hnd == NULL) {
803 errno = ENOTEMPTY;
804 goto err;
807 while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
808 &talloced)) != NULL) {
809 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
810 TALLOC_FREE(talloced);
811 continue;
813 if (!is_visible_file(conn, smb_dname->base_name, dname,
814 &st, false)) {
815 TALLOC_FREE(talloced);
816 continue;
818 if(!IS_VETO_PATH(conn, dname)) {
819 TALLOC_FREE(dir_hnd);
820 TALLOC_FREE(talloced);
821 errno = ENOTEMPTY;
822 goto err;
824 TALLOC_FREE(talloced);
827 /* We only have veto files/directories.
828 * Are we allowed to delete them ? */
830 if(!lp_recursive_veto_delete(SNUM(conn))) {
831 TALLOC_FREE(dir_hnd);
832 errno = ENOTEMPTY;
833 goto err;
836 /* Do a recursive delete. */
837 RewindDir(dir_hnd,&dirpos);
838 while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
839 &talloced)) != NULL) {
840 struct smb_filename *smb_dname_full = NULL;
841 char *fullname = NULL;
842 bool do_break = true;
843 NTSTATUS status;
845 if (ISDOT(dname) || ISDOTDOT(dname)) {
846 TALLOC_FREE(talloced);
847 continue;
849 if (!is_visible_file(conn, smb_dname->base_name, dname,
850 &st, false)) {
851 TALLOC_FREE(talloced);
852 continue;
855 fullname = talloc_asprintf(ctx,
856 "%s/%s",
857 smb_dname->base_name,
858 dname);
860 if(!fullname) {
861 errno = ENOMEM;
862 goto err_break;
865 status = create_synthetic_smb_fname(talloc_tos(),
866 fullname, NULL,
867 NULL,
868 &smb_dname_full);
869 if (!NT_STATUS_IS_OK(status)) {
870 errno = map_errno_from_nt_status(status);
871 goto err_break;
874 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
875 goto err_break;
877 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
878 if(!recursive_rmdir(ctx, conn,
879 smb_dname_full)) {
880 goto err_break;
882 if(SMB_VFS_RMDIR(conn,
883 smb_dname_full->base_name) != 0) {
884 goto err_break;
886 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
887 goto err_break;
890 /* Successful iteration. */
891 do_break = false;
893 err_break:
894 TALLOC_FREE(fullname);
895 TALLOC_FREE(smb_dname_full);
896 TALLOC_FREE(talloced);
897 if (do_break)
898 break;
900 TALLOC_FREE(dir_hnd);
901 /* Retry the rmdir */
902 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
905 err:
907 if (ret != 0) {
908 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
909 "%s\n", smb_fname_str_dbg(smb_dname),
910 strerror(errno)));
911 return map_nt_error_from_unix(errno);
914 notify_fname(conn, NOTIFY_ACTION_REMOVED,
915 FILE_NOTIFY_CHANGE_DIR_NAME,
916 smb_dname->base_name);
918 return NT_STATUS_OK;
921 /****************************************************************************
922 Close a directory opened by an NT SMB call.
923 ****************************************************************************/
925 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
926 enum file_close_type close_type)
928 struct share_mode_lock *lck = NULL;
929 bool delete_dir = False;
930 NTSTATUS status = NT_STATUS_OK;
931 NTSTATUS status1 = NT_STATUS_OK;
934 * NT can set delete_on_close of the last open
935 * reference to a directory also.
938 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
939 NULL);
941 if (lck == NULL) {
942 DEBUG(0, ("close_directory: Could not get share mode lock for "
943 "%s\n", fsp_str_dbg(fsp)));
944 status = NT_STATUS_INVALID_PARAMETER;
945 goto out;
948 if (!del_share_mode(lck, fsp)) {
949 DEBUG(0, ("close_directory: Could not delete share entry for "
950 "%s\n", fsp_str_dbg(fsp)));
953 if (fsp->initial_delete_on_close) {
954 bool became_user = False;
956 /* Initial delete on close was set - for
957 * directories we don't care if anyone else
958 * wrote a real delete on close. */
960 if (get_current_vuid(fsp->conn) != fsp->vuid) {
961 become_user(fsp->conn, fsp->vuid);
962 became_user = True;
964 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
965 fsp->fsp_name->base_name);
966 set_delete_on_close_lck(lck, True, get_current_utok(fsp->conn));
967 fsp->delete_on_close = true;
968 if (became_user) {
969 unbecome_user();
973 delete_dir = lck->delete_on_close;
975 if (delete_dir) {
976 int i;
977 /* See if others still have the dir open. If this is the
978 * case, then don't delete. If all opens are POSIX delete now. */
979 for (i=0; i<lck->num_share_modes; i++) {
980 struct share_mode_entry *e = &lck->share_modes[i];
981 if (is_valid_share_mode_entry(e)) {
982 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
983 continue;
985 delete_dir = False;
986 break;
991 if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
992 delete_dir &&
993 lck->delete_token) {
995 /* Become the user who requested the delete. */
997 if (!push_sec_ctx()) {
998 smb_panic("close_directory: failed to push sec_ctx.\n");
1001 set_sec_ctx(lck->delete_token->uid,
1002 lck->delete_token->gid,
1003 lck->delete_token->ngroups,
1004 lck->delete_token->groups,
1005 NULL);
1007 TALLOC_FREE(lck);
1009 status = rmdir_internals(talloc_tos(), fsp);
1011 DEBUG(5,("close_directory: %s. Delete on close was set - "
1012 "deleting directory returned %s.\n",
1013 fsp_str_dbg(fsp), nt_errstr(status)));
1015 /* unbecome user. */
1016 pop_sec_ctx();
1019 * Ensure we remove any change notify requests that would
1020 * now fail as the directory has been deleted.
1023 if(NT_STATUS_IS_OK(status)) {
1024 remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
1026 } else {
1027 TALLOC_FREE(lck);
1028 remove_pending_change_notify_requests_by_fid(
1029 fsp, NT_STATUS_OK);
1032 status1 = fd_close(fsp);
1034 if (!NT_STATUS_IS_OK(status1)) {
1035 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1036 fsp_str_dbg(fsp), fsp->fh->fd, errno,
1037 strerror(errno)));
1040 if (fsp->dptr) {
1041 dptr_CloseDir(fsp->dptr);
1045 * Do the code common to files and directories.
1047 close_filestruct(fsp);
1048 file_free(req, fsp);
1050 out:
1051 TALLOC_FREE(lck);
1052 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1053 status = status1;
1055 return status;
1058 /****************************************************************************
1059 Close a files_struct.
1060 ****************************************************************************/
1062 NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
1063 enum file_close_type close_type)
1065 NTSTATUS status;
1066 struct files_struct *base_fsp = fsp->base_fsp;
1068 if(fsp->is_directory) {
1069 status = close_directory(req, fsp, close_type);
1070 } else if (fsp->fake_file_handle != NULL) {
1071 status = close_fake_file(req, fsp);
1072 } else {
1073 status = close_normal_file(req, fsp, close_type);
1076 if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
1079 * fsp was a stream, the base fsp can't be a stream as well
1081 * For SHUTDOWN_CLOSE this is not possible here, because
1082 * SHUTDOWN_CLOSE only happens from files.c which walks the
1083 * complete list of files. If we mess with more than one fsp
1084 * those loops will become confused.
1087 SMB_ASSERT(base_fsp->base_fsp == NULL);
1088 close_file(req, base_fsp, close_type);
1091 return status;
1094 /****************************************************************************
1095 Deal with an (authorized) message to close a file given the share mode
1096 entry.
1097 ****************************************************************************/
1099 void msg_close_file(struct messaging_context *msg_ctx,
1100 void *private_data,
1101 uint32_t msg_type,
1102 struct server_id server_id,
1103 DATA_BLOB *data)
1105 files_struct *fsp = NULL;
1106 struct share_mode_entry e;
1108 message_to_share_mode_entry(&e, (char *)data->data);
1110 if(DEBUGLVL(10)) {
1111 char *sm_str = share_mode_str(NULL, 0, &e);
1112 if (!sm_str) {
1113 smb_panic("talloc failed");
1115 DEBUG(10,("msg_close_file: got request to close share mode "
1116 "entry %s\n", sm_str));
1117 TALLOC_FREE(sm_str);
1120 fsp = file_find_dif(e.id, e.share_file_id);
1121 if (!fsp) {
1122 DEBUG(10,("msg_close_file: failed to find file.\n"));
1123 return;
1125 close_file(NULL, fsp, NORMAL_CLOSE);