Add samba.tests.source, which checks Python files for copyright lines, license header...
[Samba/gebeck_regimport.git] / source3 / smbd / close.c
bloba1b6fd8f2531a5da46197e992d24e99c2b9d6f60
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 "printing.h"
25 #include "smbd/smbd.h"
26 #include "smbd/globals.h"
27 #include "fake_file.h"
28 #include "transfer_file.h"
29 #include "auth.h"
30 #include "messages.h"
32 /****************************************************************************
33 Run a file if it is a magic script.
34 ****************************************************************************/
36 static NTSTATUS check_magic(struct files_struct *fsp)
38 int ret;
39 const char *magic_output = NULL;
40 SMB_STRUCT_STAT st;
41 int tmp_fd, outfd;
42 TALLOC_CTX *ctx = NULL;
43 const char *p;
44 struct connection_struct *conn = fsp->conn;
45 char *fname = NULL;
46 NTSTATUS status;
48 if (!*lp_magicscript(SNUM(conn))) {
49 return NT_STATUS_OK;
52 DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));
54 ctx = talloc_stackframe();
56 fname = fsp->fsp_name->base_name;
58 if (!(p = strrchr_m(fname,'/'))) {
59 p = fname;
60 } else {
61 p++;
64 if (!strequal(lp_magicscript(SNUM(conn)),p)) {
65 status = NT_STATUS_OK;
66 goto out;
69 if (*lp_magicoutput(SNUM(conn))) {
70 magic_output = lp_magicoutput(SNUM(conn));
71 } else {
72 magic_output = talloc_asprintf(ctx,
73 "%s.out",
74 fname);
76 if (!magic_output) {
77 status = NT_STATUS_NO_MEMORY;
78 goto out;
81 /* Ensure we don't depend on user's PATH. */
82 p = talloc_asprintf(ctx, "./%s", fname);
83 if (!p) {
84 status = NT_STATUS_NO_MEMORY;
85 goto out;
88 if (chmod(fname, 0755) == -1) {
89 status = map_nt_error_from_unix(errno);
90 goto out;
92 ret = smbrun(p,&tmp_fd);
93 DEBUG(3,("Invoking magic command %s gave %d\n",
94 p,ret));
96 unlink(fname);
97 if (ret != 0 || tmp_fd == -1) {
98 if (tmp_fd != -1) {
99 close(tmp_fd);
101 status = NT_STATUS_UNSUCCESSFUL;
102 goto out;
104 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
105 if (outfd == -1) {
106 int err = errno;
107 close(tmp_fd);
108 status = map_nt_error_from_unix(err);
109 goto out;
112 if (sys_fstat(tmp_fd, &st, false) == -1) {
113 int err = errno;
114 close(tmp_fd);
115 close(outfd);
116 status = map_nt_error_from_unix(err);
117 goto out;
120 if (transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_ex_size) == (SMB_OFF_T)-1) {
121 int err = errno;
122 close(tmp_fd);
123 close(outfd);
124 status = map_nt_error_from_unix(err);
125 goto out;
127 close(tmp_fd);
128 if (close(outfd) == -1) {
129 status = map_nt_error_from_unix(errno);
130 goto out;
133 status = NT_STATUS_OK;
135 out:
136 TALLOC_FREE(ctx);
137 return status;
140 /****************************************************************************
141 Common code to close a file or a directory.
142 ****************************************************************************/
144 static NTSTATUS close_filestruct(files_struct *fsp)
146 NTSTATUS status = NT_STATUS_OK;
148 if (fsp->fh->fd != -1) {
149 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
150 status = map_nt_error_from_unix(errno);
152 delete_write_cache(fsp);
155 return status;
158 /****************************************************************************
159 If any deferred opens are waiting on this close, notify them.
160 ****************************************************************************/
162 static void notify_deferred_opens(struct messaging_context *msg_ctx,
163 struct share_mode_lock *lck)
165 int i;
167 if (!should_notify_deferred_opens()) {
168 return;
171 for (i=0; i<lck->num_share_modes; i++) {
172 struct share_mode_entry *e = &lck->share_modes[i];
174 if (!is_deferred_open_entry(e)) {
175 continue;
178 if (procid_is_me(&e->pid)) {
179 struct smbd_server_connection *sconn;
181 * We need to notify ourself to retry the open. Do
182 * this by finding the queued SMB record, moving it to
183 * the head of the queue and changing the wait time to
184 * zero.
186 sconn = msg_ctx_to_sconn(msg_ctx);
187 if (sconn != NULL) {
188 schedule_deferred_open_message_smb(
189 sconn, e->op_mid);
191 } else {
192 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
194 share_mode_entry_to_message(msg, e);
196 messaging_send_buf(msg_ctx, e->pid, MSG_SMB_OPEN_RETRY,
197 (uint8 *)msg,
198 MSG_SMB_SHARE_MODE_ENTRY_SIZE);
203 /****************************************************************************
204 Delete all streams
205 ****************************************************************************/
207 NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
209 struct stream_struct *stream_info;
210 int i;
211 unsigned int num_streams;
212 TALLOC_CTX *frame = talloc_stackframe();
213 NTSTATUS status;
215 status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
216 &num_streams, &stream_info);
218 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
219 DEBUG(10, ("no streams around\n"));
220 TALLOC_FREE(frame);
221 return NT_STATUS_OK;
224 if (!NT_STATUS_IS_OK(status)) {
225 DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
226 nt_errstr(status)));
227 goto fail;
230 DEBUG(10, ("delete_all_streams found %d streams\n",
231 num_streams));
233 if (num_streams == 0) {
234 TALLOC_FREE(frame);
235 return NT_STATUS_OK;
238 for (i=0; i<num_streams; i++) {
239 int res;
240 struct smb_filename *smb_fname_stream = NULL;
242 if (strequal(stream_info[i].name, "::$DATA")) {
243 continue;
246 status = create_synthetic_smb_fname(talloc_tos(), fname,
247 stream_info[i].name, NULL,
248 &smb_fname_stream);
250 if (!NT_STATUS_IS_OK(status)) {
251 DEBUG(0, ("talloc_aprintf failed\n"));
252 goto fail;
255 res = SMB_VFS_UNLINK(conn, smb_fname_stream);
257 if (res == -1) {
258 status = map_nt_error_from_unix(errno);
259 DEBUG(10, ("Could not delete stream %s: %s\n",
260 smb_fname_str_dbg(smb_fname_stream),
261 strerror(errno)));
262 TALLOC_FREE(smb_fname_stream);
263 break;
265 TALLOC_FREE(smb_fname_stream);
268 fail:
269 TALLOC_FREE(frame);
270 return status;
273 /****************************************************************************
274 Deal with removing a share mode on last close.
275 ****************************************************************************/
277 static NTSTATUS close_remove_share_mode(files_struct *fsp,
278 enum file_close_type close_type)
280 connection_struct *conn = fsp->conn;
281 bool delete_file = false;
282 bool changed_user = false;
283 struct share_mode_lock *lck = NULL;
284 NTSTATUS status = NT_STATUS_OK;
285 NTSTATUS tmp_status;
286 struct file_id id;
287 const struct security_unix_token *del_token = NULL;
289 /* Ensure any pending write time updates are done. */
290 if (fsp->update_write_time_event) {
291 update_write_time_handler(server_event_context(),
292 fsp->update_write_time_event,
293 timeval_current(),
294 (void *)fsp);
298 * Lock the share entries, and determine if we should delete
299 * on close. If so delete whilst the lock is still in effect.
300 * This prevents race conditions with the file being created. JRA.
303 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
304 NULL);
306 if (lck == NULL) {
307 DEBUG(0, ("close_remove_share_mode: Could not get share mode "
308 "lock for file %s\n", fsp_str_dbg(fsp)));
309 status = NT_STATUS_INVALID_PARAMETER;
310 goto done;
313 if (fsp->write_time_forced) {
314 DEBUG(10,("close_remove_share_mode: write time forced "
315 "for file %s\n",
316 fsp_str_dbg(fsp)));
317 set_close_write_time(fsp, lck->changed_write_time);
318 } else if (fsp->update_write_time_on_close) {
319 /* Someone had a pending write. */
320 if (null_timespec(fsp->close_write_time)) {
321 DEBUG(10,("close_remove_share_mode: update to current time "
322 "for file %s\n",
323 fsp_str_dbg(fsp)));
324 /* Update to current time due to "normal" write. */
325 set_close_write_time(fsp, timespec_current());
326 } else {
327 DEBUG(10,("close_remove_share_mode: write time pending "
328 "for file %s\n",
329 fsp_str_dbg(fsp)));
330 /* Update to time set on close call. */
331 set_close_write_time(fsp, fsp->close_write_time);
335 if (!del_share_mode(lck, fsp)) {
336 DEBUG(0, ("close_remove_share_mode: Could not delete share "
337 "entry for file %s\n",
338 fsp_str_dbg(fsp)));
341 if (fsp->initial_delete_on_close &&
342 !is_delete_on_close_set(lck, fsp->name_hash)) {
343 bool became_user = False;
345 /* Initial delete on close was set and no one else
346 * wrote a real delete on close. */
348 if (get_current_vuid(conn) != fsp->vuid) {
349 become_user(conn, fsp->vuid);
350 became_user = True;
352 fsp->delete_on_close = true;
353 set_delete_on_close_lck(fsp, lck, True, get_current_utok(conn));
354 if (became_user) {
355 unbecome_user();
359 delete_file = is_delete_on_close_set(lck, fsp->name_hash);
361 if (delete_file) {
362 int i;
363 /* See if others still have the file open via this pathname.
364 If this is the case, then don't delete. If all opens are
365 POSIX delete now. */
366 for (i=0; i<lck->num_share_modes; i++) {
367 struct share_mode_entry *e = &lck->share_modes[i];
368 if (is_valid_share_mode_entry(e) &&
369 e->name_hash == fsp->name_hash) {
370 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
371 continue;
373 delete_file = False;
374 break;
379 /* Notify any deferred opens waiting on this close. */
380 notify_deferred_opens(conn->sconn->msg_ctx, lck);
381 reply_to_oplock_break_requests(fsp);
384 * NT can set delete_on_close of the last open
385 * reference to a file.
388 if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) ||
389 !delete_file) {
390 TALLOC_FREE(lck);
391 return NT_STATUS_OK;
395 * Ok, we have to delete the file
398 DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
399 "- deleting file.\n", fsp_str_dbg(fsp)));
402 * Don't try to update the write time when we delete the file
404 fsp->update_write_time_on_close = false;
406 del_token = get_delete_on_close_token(lck, fsp->name_hash);
407 SMB_ASSERT(del_token != NULL);
409 if (!unix_token_equal(del_token, get_current_utok(conn))) {
410 /* Become the user who requested the delete. */
412 DEBUG(5,("close_remove_share_mode: file %s. "
413 "Change user to uid %u\n",
414 fsp_str_dbg(fsp),
415 (unsigned int)del_token->uid));
417 if (!push_sec_ctx()) {
418 smb_panic("close_remove_share_mode: file %s. failed to push "
419 "sec_ctx.\n");
422 set_sec_ctx(del_token->uid,
423 del_token->gid,
424 del_token->ngroups,
425 del_token->groups,
426 NULL);
428 changed_user = true;
431 /* We can only delete the file if the name we have is still valid and
432 hasn't been renamed. */
434 tmp_status = vfs_stat_fsp(fsp);
435 if (!NT_STATUS_IS_OK(tmp_status)) {
436 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
437 "was set and stat failed with error %s\n",
438 fsp_str_dbg(fsp), nt_errstr(tmp_status)));
440 * Don't save the errno here, we ignore this error
442 goto done;
445 id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
447 if (!file_id_equal(&fsp->file_id, &id)) {
448 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
449 "was set and dev and/or inode does not match\n",
450 fsp_str_dbg(fsp)));
451 DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
452 "stat file_id %s\n",
453 fsp_str_dbg(fsp),
454 file_id_string_tos(&fsp->file_id),
455 file_id_string_tos(&id)));
457 * Don't save the errno here, we ignore this error
459 goto done;
462 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
463 && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
465 status = delete_all_streams(conn, fsp->fsp_name->base_name);
467 if (!NT_STATUS_IS_OK(status)) {
468 DEBUG(5, ("delete_all_streams failed: %s\n",
469 nt_errstr(status)));
470 goto done;
475 if (SMB_VFS_UNLINK(conn, fsp->fsp_name) != 0) {
477 * This call can potentially fail as another smbd may
478 * have had the file open with delete on close set and
479 * deleted it when its last reference to this file
480 * went away. Hence we log this but not at debug level
481 * zero.
484 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
485 "was set and unlink failed with error %s\n",
486 fsp_str_dbg(fsp), strerror(errno)));
488 status = map_nt_error_from_unix(errno);
491 /* As we now have POSIX opens which can unlink
492 * with other open files we may have taken
493 * this code path with more than one share mode
494 * entry - ensure we only delete once by resetting
495 * the delete on close flag. JRA.
498 fsp->delete_on_close = false;
499 set_delete_on_close_lck(fsp, lck, false, NULL);
501 done:
503 if (changed_user) {
504 /* unbecome user. */
505 pop_sec_ctx();
508 TALLOC_FREE(lck);
510 if (delete_file) {
512 * Do the notification after we released the share
513 * mode lock. Inside notify_fname we take out another
514 * tdb lock. With ctdb also accessing our databases,
515 * this can lead to deadlocks. Putting this notify
516 * after the TALLOC_FREE(lck) above we avoid locking
517 * two records simultaneously. Notifies are async and
518 * informational only, so calling the notify_fname
519 * without holding the share mode lock should not do
520 * any harm.
522 notify_fname(conn, NOTIFY_ACTION_REMOVED,
523 FILE_NOTIFY_CHANGE_FILE_NAME,
524 fsp->fsp_name->base_name);
527 return status;
530 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
532 DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
534 if (null_timespec(ts)) {
535 return;
537 fsp->write_time_forced = false;
538 fsp->update_write_time_on_close = true;
539 fsp->close_write_time = ts;
542 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
544 struct smb_file_time ft;
545 NTSTATUS status;
546 struct share_mode_lock *lck = NULL;
548 ZERO_STRUCT(ft);
550 if (!fsp->update_write_time_on_close) {
551 return NT_STATUS_OK;
554 if (null_timespec(fsp->close_write_time)) {
555 fsp->close_write_time = timespec_current();
558 /* Ensure we have a valid stat struct for the source. */
559 status = vfs_stat_fsp(fsp);
560 if (!NT_STATUS_IS_OK(status)) {
561 return status;
564 if (!VALID_STAT(fsp->fsp_name->st)) {
565 /* if it doesn't seem to be a real file */
566 return NT_STATUS_OK;
569 /* On close if we're changing the real file time we
570 * must update it in the open file db too. */
571 (void)set_write_time(fsp->file_id, fsp->close_write_time);
573 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL);
574 if (lck) {
575 /* Close write times overwrite sticky write times
576 so we must replace any sticky write time here. */
577 if (!null_timespec(lck->changed_write_time)) {
578 (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
580 TALLOC_FREE(lck);
583 ft.mtime = fsp->close_write_time;
584 /* We must use NULL for the fsp handle here, as smb_set_file_time()
585 checks the fsp access_mask, which may not include FILE_WRITE_ATTRIBUTES.
586 As this is a close based update, we are not directly changing the
587 file attributes from a client call, but indirectly from a write. */
588 status = smb_set_file_time(fsp->conn, NULL, fsp->fsp_name, &ft, false);
589 if (!NT_STATUS_IS_OK(status)) {
590 DEBUG(10,("update_write_time_on_close: smb_set_file_time "
591 "on file %s returned %s\n",
592 fsp_str_dbg(fsp),
593 nt_errstr(status)));
594 return status;
597 return status;
600 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
602 if (!NT_STATUS_IS_OK(s1)) {
603 return s1;
605 return s2;
608 /****************************************************************************
609 Close a file.
611 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
612 printing and magic scripts are only run on normal close.
613 delete on close is done on normal and shutdown close.
614 ****************************************************************************/
616 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
617 enum file_close_type close_type)
619 NTSTATUS status = NT_STATUS_OK;
620 NTSTATUS tmp;
621 connection_struct *conn = fsp->conn;
623 if (close_type == ERROR_CLOSE) {
624 cancel_aio_by_fsp(fsp);
625 } else {
627 * If we're finishing async io on a close we can get a write
628 * error here, we must remember this.
630 int ret = wait_for_aio_completion(fsp);
631 if (ret) {
632 status = ntstatus_keeperror(
633 status, map_nt_error_from_unix(ret));
638 * If we're flushing on a close we can get a write
639 * error here, we must remember this.
642 tmp = close_filestruct(fsp);
643 status = ntstatus_keeperror(status, tmp);
645 if (fsp->print_file) {
646 /* FIXME: return spool errors */
647 print_spool_end(fsp, close_type);
648 file_free(req, fsp);
649 return NT_STATUS_OK;
652 /* Remove the oplock before potentially deleting the file. */
653 if(fsp->oplock_type) {
654 release_file_oplock(fsp);
657 /* If this is an old DOS or FCB open and we have multiple opens on
658 the same handle we only have one share mode. Ensure we only remove
659 the share mode on the last close. */
661 if (fsp->fh->ref_count == 1) {
662 /* Should we return on error here... ? */
663 tmp = close_remove_share_mode(fsp, close_type);
664 status = ntstatus_keeperror(status, tmp);
667 locking_close_file(conn->sconn->msg_ctx, fsp, close_type);
669 tmp = fd_close(fsp);
670 status = ntstatus_keeperror(status, tmp);
672 /* check for magic scripts */
673 if (close_type == NORMAL_CLOSE) {
674 tmp = check_magic(fsp);
675 status = ntstatus_keeperror(status, tmp);
679 * Ensure pending modtime is set after close.
682 tmp = update_write_time_on_close(fsp);
683 if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
684 /* Someone renamed the file or a parent directory containing
685 * this file. We can't do anything about this, we don't have
686 * an "update timestamp by fd" call in POSIX. Eat the error. */
688 tmp = NT_STATUS_OK;
691 status = ntstatus_keeperror(status, tmp);
693 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
694 conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
695 conn->num_files_open - 1,
696 nt_errstr(status) ));
698 file_free(req, fsp);
699 return status;
701 /****************************************************************************
702 Static function used by reply_rmdir to delete an entire directory
703 tree recursively. Return True on ok, False on fail.
704 ****************************************************************************/
706 static bool recursive_rmdir(TALLOC_CTX *ctx,
707 connection_struct *conn,
708 struct smb_filename *smb_dname)
710 const char *dname = NULL;
711 char *talloced = NULL;
712 bool ret = True;
713 long offset = 0;
714 SMB_STRUCT_STAT st;
715 struct smb_Dir *dir_hnd;
717 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
719 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
720 if(dir_hnd == NULL)
721 return False;
723 while((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
724 struct smb_filename *smb_dname_full = NULL;
725 char *fullname = NULL;
726 bool do_break = true;
727 NTSTATUS status;
729 if (ISDOT(dname) || ISDOTDOT(dname)) {
730 TALLOC_FREE(talloced);
731 continue;
734 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
735 false)) {
736 TALLOC_FREE(talloced);
737 continue;
740 /* Construct the full name. */
741 fullname = talloc_asprintf(ctx,
742 "%s/%s",
743 smb_dname->base_name,
744 dname);
745 if (!fullname) {
746 errno = ENOMEM;
747 goto err_break;
750 status = create_synthetic_smb_fname(talloc_tos(), fullname,
751 NULL, NULL,
752 &smb_dname_full);
753 if (!NT_STATUS_IS_OK(status)) {
754 goto err_break;
757 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
758 goto err_break;
761 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
762 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
763 goto err_break;
765 if(SMB_VFS_RMDIR(conn,
766 smb_dname_full->base_name) != 0) {
767 goto err_break;
769 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
770 goto err_break;
773 /* Successful iteration. */
774 do_break = false;
776 err_break:
777 TALLOC_FREE(smb_dname_full);
778 TALLOC_FREE(fullname);
779 TALLOC_FREE(talloced);
780 if (do_break) {
781 ret = false;
782 break;
785 TALLOC_FREE(dir_hnd);
786 return ret;
789 /****************************************************************************
790 The internals of the rmdir code - called elsewhere.
791 ****************************************************************************/
793 static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
795 connection_struct *conn = fsp->conn;
796 struct smb_filename *smb_dname = fsp->fsp_name;
797 int ret;
799 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
801 /* Might be a symlink. */
802 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
803 return map_nt_error_from_unix(errno);
806 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
807 /* Is what it points to a directory ? */
808 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
809 return map_nt_error_from_unix(errno);
811 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
812 return NT_STATUS_NOT_A_DIRECTORY;
814 ret = SMB_VFS_UNLINK(conn, smb_dname);
815 } else {
816 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
818 if (ret == 0) {
819 notify_fname(conn, NOTIFY_ACTION_REMOVED,
820 FILE_NOTIFY_CHANGE_DIR_NAME,
821 smb_dname->base_name);
822 return NT_STATUS_OK;
825 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
827 * Check to see if the only thing in this directory are
828 * vetoed files/directories. If so then delete them and
829 * retry. If we fail to delete any of them (and we *don't*
830 * do a recursive delete) then fail the rmdir.
832 SMB_STRUCT_STAT st;
833 const char *dname = NULL;
834 char *talloced = NULL;
835 long dirpos = 0;
836 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
837 smb_dname->base_name, NULL,
840 if(dir_hnd == NULL) {
841 errno = ENOTEMPTY;
842 goto err;
845 while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
846 &talloced)) != NULL) {
847 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
848 TALLOC_FREE(talloced);
849 continue;
851 if (!is_visible_file(conn, smb_dname->base_name, dname,
852 &st, false)) {
853 TALLOC_FREE(talloced);
854 continue;
856 if(!IS_VETO_PATH(conn, dname)) {
857 TALLOC_FREE(dir_hnd);
858 TALLOC_FREE(talloced);
859 errno = ENOTEMPTY;
860 goto err;
862 TALLOC_FREE(talloced);
865 /* We only have veto files/directories.
866 * Are we allowed to delete them ? */
868 if(!lp_recursive_veto_delete(SNUM(conn))) {
869 TALLOC_FREE(dir_hnd);
870 errno = ENOTEMPTY;
871 goto err;
874 /* Do a recursive delete. */
875 RewindDir(dir_hnd,&dirpos);
876 while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
877 &talloced)) != NULL) {
878 struct smb_filename *smb_dname_full = NULL;
879 char *fullname = NULL;
880 bool do_break = true;
881 NTSTATUS status;
883 if (ISDOT(dname) || ISDOTDOT(dname)) {
884 TALLOC_FREE(talloced);
885 continue;
887 if (!is_visible_file(conn, smb_dname->base_name, dname,
888 &st, false)) {
889 TALLOC_FREE(talloced);
890 continue;
893 fullname = talloc_asprintf(ctx,
894 "%s/%s",
895 smb_dname->base_name,
896 dname);
898 if(!fullname) {
899 errno = ENOMEM;
900 goto err_break;
903 status = create_synthetic_smb_fname(talloc_tos(),
904 fullname, NULL,
905 NULL,
906 &smb_dname_full);
907 if (!NT_STATUS_IS_OK(status)) {
908 errno = map_errno_from_nt_status(status);
909 goto err_break;
912 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
913 goto err_break;
915 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
916 if(!recursive_rmdir(ctx, conn,
917 smb_dname_full)) {
918 goto err_break;
920 if(SMB_VFS_RMDIR(conn,
921 smb_dname_full->base_name) != 0) {
922 goto err_break;
924 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
925 goto err_break;
928 /* Successful iteration. */
929 do_break = false;
931 err_break:
932 TALLOC_FREE(fullname);
933 TALLOC_FREE(smb_dname_full);
934 TALLOC_FREE(talloced);
935 if (do_break)
936 break;
938 TALLOC_FREE(dir_hnd);
939 /* Retry the rmdir */
940 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
943 err:
945 if (ret != 0) {
946 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
947 "%s\n", smb_fname_str_dbg(smb_dname),
948 strerror(errno)));
949 return map_nt_error_from_unix(errno);
952 notify_fname(conn, NOTIFY_ACTION_REMOVED,
953 FILE_NOTIFY_CHANGE_DIR_NAME,
954 smb_dname->base_name);
956 return NT_STATUS_OK;
959 /****************************************************************************
960 Close a directory opened by an NT SMB call.
961 ****************************************************************************/
963 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
964 enum file_close_type close_type)
966 struct share_mode_lock *lck = NULL;
967 bool delete_dir = False;
968 NTSTATUS status = NT_STATUS_OK;
969 NTSTATUS status1 = NT_STATUS_OK;
970 const struct security_unix_token *del_token = NULL;
973 * NT can set delete_on_close of the last open
974 * reference to a directory also.
977 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
978 NULL);
980 if (lck == NULL) {
981 DEBUG(0, ("close_directory: Could not get share mode lock for "
982 "%s\n", fsp_str_dbg(fsp)));
983 status = NT_STATUS_INVALID_PARAMETER;
984 goto out;
987 if (!del_share_mode(lck, fsp)) {
988 DEBUG(0, ("close_directory: Could not delete share entry for "
989 "%s\n", fsp_str_dbg(fsp)));
992 if (fsp->initial_delete_on_close) {
993 bool became_user = False;
995 /* Initial delete on close was set - for
996 * directories we don't care if anyone else
997 * wrote a real delete on close. */
999 if (get_current_vuid(fsp->conn) != fsp->vuid) {
1000 become_user(fsp->conn, fsp->vuid);
1001 became_user = True;
1003 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
1004 fsp->fsp_name->base_name);
1005 set_delete_on_close_lck(fsp, lck, true,
1006 get_current_utok(fsp->conn));
1007 fsp->delete_on_close = true;
1008 if (became_user) {
1009 unbecome_user();
1013 del_token = get_delete_on_close_token(lck, fsp->name_hash);
1014 delete_dir = (del_token != NULL);
1016 if (delete_dir) {
1017 int i;
1018 /* See if others still have the dir open. If this is the
1019 * case, then don't delete. If all opens are POSIX delete now. */
1020 for (i=0; i<lck->num_share_modes; i++) {
1021 struct share_mode_entry *e = &lck->share_modes[i];
1022 if (is_valid_share_mode_entry(e) &&
1023 e->name_hash == fsp->name_hash) {
1024 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
1025 continue;
1027 delete_dir = False;
1028 break;
1033 if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
1034 delete_dir) {
1036 /* Become the user who requested the delete. */
1038 if (!push_sec_ctx()) {
1039 smb_panic("close_directory: failed to push sec_ctx.\n");
1042 set_sec_ctx(del_token->uid,
1043 del_token->gid,
1044 del_token->ngroups,
1045 del_token->groups,
1046 NULL);
1048 TALLOC_FREE(lck);
1050 status = rmdir_internals(talloc_tos(), fsp);
1052 DEBUG(5,("close_directory: %s. Delete on close was set - "
1053 "deleting directory returned %s.\n",
1054 fsp_str_dbg(fsp), nt_errstr(status)));
1056 /* unbecome user. */
1057 pop_sec_ctx();
1060 * Ensure we remove any change notify requests that would
1061 * now fail as the directory has been deleted.
1064 if(NT_STATUS_IS_OK(status)) {
1065 remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
1067 } else {
1068 TALLOC_FREE(lck);
1069 remove_pending_change_notify_requests_by_fid(
1070 fsp, NT_STATUS_OK);
1073 status1 = fd_close(fsp);
1075 if (!NT_STATUS_IS_OK(status1)) {
1076 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1077 fsp_str_dbg(fsp), fsp->fh->fd, errno,
1078 strerror(errno)));
1082 * Do the code common to files and directories.
1084 close_filestruct(fsp);
1085 file_free(req, fsp);
1087 out:
1088 TALLOC_FREE(lck);
1089 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1090 status = status1;
1092 return status;
1095 /****************************************************************************
1096 Close a files_struct.
1097 ****************************************************************************/
1099 NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
1100 enum file_close_type close_type)
1102 NTSTATUS status;
1103 struct files_struct *base_fsp = fsp->base_fsp;
1105 if(fsp->is_directory) {
1106 status = close_directory(req, fsp, close_type);
1107 } else if (fsp->fake_file_handle != NULL) {
1108 status = close_fake_file(req, fsp);
1109 } else {
1110 status = close_normal_file(req, fsp, close_type);
1113 if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
1116 * fsp was a stream, the base fsp can't be a stream as well
1118 * For SHUTDOWN_CLOSE this is not possible here, because
1119 * SHUTDOWN_CLOSE only happens from files.c which walks the
1120 * complete list of files. If we mess with more than one fsp
1121 * those loops will become confused.
1124 SMB_ASSERT(base_fsp->base_fsp == NULL);
1125 close_file(req, base_fsp, close_type);
1128 return status;
1131 /****************************************************************************
1132 Deal with an (authorized) message to close a file given the share mode
1133 entry.
1134 ****************************************************************************/
1136 void msg_close_file(struct messaging_context *msg_ctx,
1137 void *private_data,
1138 uint32_t msg_type,
1139 struct server_id server_id,
1140 DATA_BLOB *data)
1142 struct smbd_server_connection *sconn;
1143 files_struct *fsp = NULL;
1144 struct share_mode_entry e;
1146 sconn = msg_ctx_to_sconn(msg_ctx);
1147 if (sconn == NULL) {
1148 DEBUG(1, ("could not find sconn\n"));
1149 return;
1152 message_to_share_mode_entry(&e, (char *)data->data);
1154 if(DEBUGLVL(10)) {
1155 char *sm_str = share_mode_str(NULL, 0, &e);
1156 if (!sm_str) {
1157 smb_panic("talloc failed");
1159 DEBUG(10,("msg_close_file: got request to close share mode "
1160 "entry %s\n", sm_str));
1161 TALLOC_FREE(sm_str);
1164 fsp = file_find_dif(sconn, e.id, e.share_file_id);
1165 if (!fsp) {
1166 DEBUG(10,("msg_close_file: failed to find file.\n"));
1167 return;
1169 close_file(NULL, fsp, NORMAL_CLOSE);