s3: smbd: Fix logic in rmdir_internals() to cope with dangling symlinks.
[samba.git] / source3 / smbd / close.c
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
7
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.
12
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.
17
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/>.
20 */
21
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/scavenger.h"
30 #include "fake_file.h"
31 #include "transfer_file.h"
32 #include "auth.h"
33 #include "messages.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "lib/util/tevent_ntstatus.h"
36
37 /****************************************************************************
38  Run a file if it is a magic script.
39 ****************************************************************************/
40
41 static NTSTATUS check_magic(struct files_struct *fsp)
42 {
43         int ret;
44         const struct loadparm_substitution *lp_sub =
45                 loadparm_s3_global_substitution();
46         const char *magic_output = NULL;
47         SMB_STRUCT_STAT st;
48         int tmp_fd, outfd;
49         TALLOC_CTX *ctx = NULL;
50         const char *p;
51         struct connection_struct *conn = fsp->conn;
52         char *fname = NULL;
53         NTSTATUS status;
54
55         if (!*lp_magic_script(talloc_tos(), lp_sub, SNUM(conn))) {
56                 return NT_STATUS_OK;
57         }
58
59         DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));
60
61         ctx = talloc_stackframe();
62
63         fname = fsp->fsp_name->base_name;
64
65         if (!(p = strrchr_m(fname,'/'))) {
66                 p = fname;
67         } else {
68                 p++;
69         }
70
71         if (!strequal(lp_magic_script(talloc_tos(), lp_sub, SNUM(conn)),p)) {
72                 status = NT_STATUS_OK;
73                 goto out;
74         }
75
76         if (*lp_magic_output(talloc_tos(), lp_sub, SNUM(conn))) {
77                 magic_output = lp_magic_output(talloc_tos(), lp_sub, SNUM(conn));
78         } else {
79                 magic_output = talloc_asprintf(ctx,
80                                 "%s.out",
81                                 fname);
82         }
83         if (!magic_output) {
84                 status = NT_STATUS_NO_MEMORY;
85                 goto out;
86         }
87
88         /* Ensure we don't depend on user's PATH. */
89         p = talloc_asprintf(ctx, "./%s", fname);
90         if (!p) {
91                 status = NT_STATUS_NO_MEMORY;
92                 goto out;
93         }
94
95         if (chmod(fname, 0755) == -1) {
96                 status = map_nt_error_from_unix(errno);
97                 goto out;
98         }
99         ret = smbrun(p, &tmp_fd, NULL);
100         DEBUG(3,("Invoking magic command %s gave %d\n",
101                 p,ret));
102
103         unlink(fname);
104         if (ret != 0 || tmp_fd == -1) {
105                 if (tmp_fd != -1) {
106                         close(tmp_fd);
107                 }
108                 status = NT_STATUS_UNSUCCESSFUL;
109                 goto out;
110         }
111         outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
112         if (outfd == -1) {
113                 int err = errno;
114                 close(tmp_fd);
115                 status = map_nt_error_from_unix(err);
116                 goto out;
117         }
118
119         if (sys_fstat(tmp_fd, &st, false) == -1) {
120                 int err = errno;
121                 close(tmp_fd);
122                 close(outfd);
123                 status = map_nt_error_from_unix(err);
124                 goto out;
125         }
126
127         if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) {
128                 int err = errno;
129                 close(tmp_fd);
130                 close(outfd);
131                 status = map_nt_error_from_unix(err);
132                 goto out;
133         }
134         close(tmp_fd);
135         if (close(outfd) == -1) {
136                 status = map_nt_error_from_unix(errno);
137                 goto out;
138         }
139
140         status = NT_STATUS_OK;
141
142  out:
143         TALLOC_FREE(ctx);
144         return status;
145 }
146
147 /****************************************************************************
148  Delete all streams
149 ****************************************************************************/
150
151 NTSTATUS delete_all_streams(connection_struct *conn,
152                         const struct smb_filename *smb_fname)
153 {
154         struct stream_struct *stream_info = NULL;
155         unsigned int i;
156         unsigned int num_streams = 0;
157         TALLOC_CTX *frame = talloc_stackframe();
158         NTSTATUS status;
159
160         status = vfs_fstreaminfo(smb_fname->fsp, talloc_tos(),
161                                 &num_streams, &stream_info);
162
163         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
164                 DEBUG(10, ("no streams around\n"));
165                 TALLOC_FREE(frame);
166                 return NT_STATUS_OK;
167         }
168
169         if (!NT_STATUS_IS_OK(status)) {
170                 DEBUG(10, ("vfs_fstreaminfo failed: %s\n",
171                            nt_errstr(status)));
172                 goto fail;
173         }
174
175         DEBUG(10, ("delete_all_streams found %d streams\n",
176                    num_streams));
177
178         if (num_streams == 0) {
179                 TALLOC_FREE(frame);
180                 return NT_STATUS_OK;
181         }
182
183         for (i=0; i<num_streams; i++) {
184                 int res;
185                 struct smb_filename *smb_fname_stream;
186
187                 if (strequal(stream_info[i].name, "::$DATA")) {
188                         continue;
189                 }
190
191                 status = synthetic_pathref(talloc_tos(),
192                                            conn->cwd_fsp,
193                                            smb_fname->base_name,
194                                            stream_info[i].name,
195                                            NULL,
196                                            smb_fname->twrp,
197                                            (smb_fname->flags &
198                                             ~SMB_FILENAME_POSIX_PATH),
199                                            &smb_fname_stream);
200                 if (!NT_STATUS_IS_OK(status)) {
201                         DEBUG(0, ("talloc_aprintf failed\n"));
202                         status = NT_STATUS_NO_MEMORY;
203                         goto fail;
204                 }
205
206                 res = SMB_VFS_UNLINKAT(conn,
207                                 conn->cwd_fsp,
208                                 smb_fname_stream,
209                                 0);
210
211                 if (res == -1) {
212                         status = map_nt_error_from_unix(errno);
213                         DEBUG(10, ("Could not delete stream %s: %s\n",
214                                    smb_fname_str_dbg(smb_fname_stream),
215                                    strerror(errno)));
216                         TALLOC_FREE(smb_fname_stream);
217                         break;
218                 }
219                 TALLOC_FREE(smb_fname_stream);
220         }
221
222  fail:
223         TALLOC_FREE(frame);
224         return status;
225 }
226
227 struct has_other_nonposix_opens_state {
228         files_struct *fsp;
229         bool found_another;
230 };
231
232 static bool has_other_nonposix_opens_fn(
233         struct share_mode_entry *e,
234         bool *modified,
235         void *private_data)
236 {
237         struct has_other_nonposix_opens_state *state = private_data;
238         struct files_struct *fsp = state->fsp;
239
240         if (e->name_hash != fsp->name_hash) {
241                 return false;
242         }
243         if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) &&
244             (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
245                 return false;
246         }
247         if (e->share_file_id == fh_get_gen_id(fsp->fh)) {
248                 struct server_id self = messaging_server_id(
249                         fsp->conn->sconn->msg_ctx);
250                 if (server_id_equal(&self, &e->pid)) {
251                         return false;
252                 }
253         }
254         if (share_entry_stale_pid(e)) {
255                 return false;
256         }
257
258         state->found_another = true;
259         return true;
260 }
261
262 bool has_other_nonposix_opens(struct share_mode_lock *lck,
263                               struct files_struct *fsp)
264 {
265         struct has_other_nonposix_opens_state state = { .fsp = fsp };
266         bool ok;
267
268         ok = share_mode_forall_entries(
269                 lck, has_other_nonposix_opens_fn, &state);
270         if (!ok) {
271                 return false;
272         }
273         return state.found_another;
274 }
275
276 /****************************************************************************
277  Deal with removing a share mode on last close.
278 ****************************************************************************/
279
280 static NTSTATUS close_remove_share_mode(files_struct *fsp,
281                                         enum file_close_type close_type)
282 {
283         connection_struct *conn = fsp->conn;
284         bool delete_file = false;
285         bool changed_user = false;
286         struct share_mode_lock *lck = NULL;
287         NTSTATUS status = NT_STATUS_OK;
288         NTSTATUS tmp_status;
289         struct file_id id;
290         const struct security_unix_token *del_token = NULL;
291         const struct security_token *del_nt_token = NULL;
292         struct smb_filename *parent_fname = NULL;
293         struct smb_filename *base_fname = NULL;
294         bool got_tokens = false;
295         bool normal_close;
296         int ret;
297
298         /* Ensure any pending write time updates are done. */
299         if (fsp->update_write_time_event) {
300                 fsp_flush_write_time_update(fsp);
301         }
302
303         /*
304          * Lock the share entries, and determine if we should delete
305          * on close. If so delete whilst the lock is still in effect.
306          * This prevents race conditions with the file being created. JRA.
307          */
308
309         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
310         if (lck == NULL) {
311                 DEBUG(0, ("close_remove_share_mode: Could not get share mode "
312                           "lock for file %s\n", fsp_str_dbg(fsp)));
313                 return NT_STATUS_INVALID_PARAMETER;
314         }
315
316         /* Remove the oplock before potentially deleting the file. */
317         if(fsp->oplock_type) {
318                 remove_oplock(fsp);
319         }
320
321         if (fsp->fsp_flags.write_time_forced) {
322                 NTTIME mtime = share_mode_changed_write_time(lck);
323                 struct timespec ts = nt_time_to_full_timespec(mtime);
324
325                 DEBUG(10,("close_remove_share_mode: write time forced "
326                         "for file %s\n",
327                         fsp_str_dbg(fsp)));
328                 set_close_write_time(fsp, ts);
329         } else if (fsp->fsp_flags.update_write_time_on_close) {
330                 /* Someone had a pending write. */
331                 if (is_omit_timespec(&fsp->close_write_time)) {
332                         DEBUG(10,("close_remove_share_mode: update to current time "
333                                 "for file %s\n",
334                                 fsp_str_dbg(fsp)));
335                         /* Update to current time due to "normal" write. */
336                         set_close_write_time(fsp, timespec_current());
337                 } else {
338                         DEBUG(10,("close_remove_share_mode: write time pending "
339                                 "for file %s\n",
340                                 fsp_str_dbg(fsp)));
341                         /* Update to time set on close call. */
342                         set_close_write_time(fsp, fsp->close_write_time);
343                 }
344         }
345
346         if (fsp->fsp_flags.initial_delete_on_close &&
347                         !is_delete_on_close_set(lck, fsp->name_hash)) {
348                 /* Initial delete on close was set and no one else
349                  * wrote a real delete on close. */
350
351                 fsp->fsp_flags.delete_on_close = true;
352                 set_delete_on_close_lck(fsp, lck,
353                                         fsp->conn->session_info->security_token,
354                                         fsp->conn->session_info->unix_token);
355         }
356
357         delete_file = is_delete_on_close_set(lck, fsp->name_hash) &&
358                 !has_other_nonposix_opens(lck, fsp);
359
360         /*
361          * NT can set delete_on_close of the last open
362          * reference to a file.
363          */
364
365         normal_close = (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE);
366
367         if (!normal_close || !delete_file) {
368                 status = NT_STATUS_OK;
369                 goto done;
370         }
371
372         /*
373          * Ok, we have to delete the file
374          */
375
376         DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
377                  "- deleting file.\n", fsp_str_dbg(fsp)));
378
379         /*
380          * Don't try to update the write time when we delete the file
381          */
382         fsp->fsp_flags.update_write_time_on_close = false;
383
384         got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
385                                         &del_nt_token, &del_token);
386         SMB_ASSERT(got_tokens);
387
388         if (!unix_token_equal(del_token, get_current_utok(conn))) {
389                 /* Become the user who requested the delete. */
390
391                 DEBUG(5,("close_remove_share_mode: file %s. "
392                         "Change user to uid %u\n",
393                         fsp_str_dbg(fsp),
394                         (unsigned int)del_token->uid));
395
396                 if (!push_sec_ctx()) {
397                         smb_panic("close_remove_share_mode: file %s. failed to push "
398                                   "sec_ctx.\n");
399                 }
400
401                 set_sec_ctx(del_token->uid,
402                             del_token->gid,
403                             del_token->ngroups,
404                             del_token->groups,
405                             del_nt_token);
406
407                 changed_user = true;
408         }
409
410         /* We can only delete the file if the name we have is still valid and
411            hasn't been renamed. */
412
413         tmp_status = vfs_stat_fsp(fsp);
414         if (!NT_STATUS_IS_OK(tmp_status)) {
415                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
416                          "was set and stat failed with error %s\n",
417                          fsp_str_dbg(fsp), nt_errstr(tmp_status)));
418                 /*
419                  * Don't save the errno here, we ignore this error
420                  */
421                 goto done;
422         }
423
424         id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
425
426         if (!file_id_equal(&fsp->file_id, &id)) {
427                 struct file_id_buf ftmp1, ftmp2;
428                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
429                          "was set and dev and/or inode does not match\n",
430                          fsp_str_dbg(fsp)));
431                 DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
432                          "stat file_id %s\n",
433                          fsp_str_dbg(fsp),
434                          file_id_str_buf(fsp->file_id, &ftmp1),
435                          file_id_str_buf(id, &ftmp2)));
436                 /*
437                  * Don't save the errno here, we ignore this error
438                  */
439                 goto done;
440         }
441
442         if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
443             && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
444
445                 status = delete_all_streams(conn, fsp->fsp_name);
446
447                 if (!NT_STATUS_IS_OK(status)) {
448                         DEBUG(5, ("delete_all_streams failed: %s\n",
449                                   nt_errstr(status)));
450                         goto done;
451                 }
452         }
453
454         if (fsp->fsp_flags.kernel_share_modes_taken) {
455                 /*
456                  * A file system sharemode could block the unlink;
457                  * remove filesystem sharemodes first.
458                  */
459                 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
460                 if (ret == -1) {
461                         DBG_INFO("Removing file system sharemode for %s "
462                                  "failed: %s\n",
463                                  fsp_str_dbg(fsp), strerror(errno));
464                 }
465
466                 fsp->fsp_flags.kernel_share_modes_taken = false;
467         }
468
469         status = parent_pathref(talloc_tos(),
470                                 conn->cwd_fsp,
471                                 fsp->fsp_name,
472                                 &parent_fname,
473                                 &base_fname);
474         if (!NT_STATUS_IS_OK(status)) {
475                 goto done;
476         }
477
478         ret = SMB_VFS_UNLINKAT(conn,
479                                parent_fname->fsp,
480                                base_fname,
481                                0);
482         TALLOC_FREE(parent_fname);
483         base_fname = NULL;
484         if (ret != 0) {
485                 /*
486                  * This call can potentially fail as another smbd may
487                  * have had the file open with delete on close set and
488                  * deleted it when its last reference to this file
489                  * went away. Hence we log this but not at debug level
490                  * zero.
491                  */
492
493                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
494                          "was set and unlink failed with error %s\n",
495                          fsp_str_dbg(fsp), strerror(errno)));
496
497                 status = map_nt_error_from_unix(errno);
498         }
499
500         /* As we now have POSIX opens which can unlink
501          * with other open files we may have taken
502          * this code path with more than one share mode
503          * entry - ensure we only delete once by resetting
504          * the delete on close flag. JRA.
505          */
506
507         fsp->fsp_flags.delete_on_close = false;
508         reset_delete_on_close_lck(fsp, lck);
509
510  done:
511
512         if (changed_user) {
513                 /* unbecome user. */
514                 pop_sec_ctx();
515         }
516
517         if (fsp->fsp_flags.kernel_share_modes_taken) {
518                 /* remove filesystem sharemodes */
519                 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
520                 if (ret == -1) {
521                         DBG_INFO("Removing file system sharemode for "
522                                  "%s failed: %s\n",
523                                  fsp_str_dbg(fsp), strerror(errno));
524                 }
525         }
526
527         if (!del_share_mode(lck, fsp)) {
528                 DEBUG(0, ("close_remove_share_mode: Could not delete share "
529                           "entry for file %s\n", fsp_str_dbg(fsp)));
530         }
531
532         TALLOC_FREE(lck);
533
534         if (delete_file) {
535                 /*
536                  * Do the notification after we released the share
537                  * mode lock. Inside notify_fname we take out another
538                  * tdb lock. With ctdb also accessing our databases,
539                  * this can lead to deadlocks. Putting this notify
540                  * after the TALLOC_FREE(lck) above we avoid locking
541                  * two records simultaneously. Notifies are async and
542                  * informational only, so calling the notify_fname
543                  * without holding the share mode lock should not do
544                  * any harm.
545                  */
546                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
547                              FILE_NOTIFY_CHANGE_FILE_NAME,
548                              fsp->fsp_name->base_name);
549         }
550
551         return status;
552 }
553
554 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
555 {
556         DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
557
558         if (is_omit_timespec(&ts)) {
559                 return;
560         }
561         fsp->fsp_flags.write_time_forced = false;
562         fsp->fsp_flags.update_write_time_on_close = true;
563         fsp->close_write_time = ts;
564 }
565
566 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
567 {
568         struct smb_file_time ft;
569         NTSTATUS status;
570         struct share_mode_lock *lck = NULL;
571
572         init_smb_file_time(&ft);
573
574         if (!(fsp->fsp_flags.update_write_time_on_close)) {
575                 return NT_STATUS_OK;
576         }
577
578         if (is_omit_timespec(&fsp->close_write_time)) {
579                 fsp->close_write_time = timespec_current();
580         }
581
582         /* Ensure we have a valid stat struct for the source. */
583         status = vfs_stat_fsp(fsp);
584         if (!NT_STATUS_IS_OK(status)) {
585                 return status;
586         }
587
588         if (!VALID_STAT(fsp->fsp_name->st)) {
589                 /* if it doesn't seem to be a real file */
590                 return NT_STATUS_OK;
591         }
592
593         /*
594          * get_existing_share_mode_lock() isn't really the right
595          * call here, as we're being called after
596          * close_remove_share_mode() inside close_normal_file()
597          * so it's quite normal to not have an existing share
598          * mode here. However, get_share_mode_lock() doesn't
599          * work because that will create a new share mode if
600          * one doesn't exist - so stick with this call (just
601          * ignore any error we get if the share mode doesn't
602          * exist.
603          */
604
605         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
606         if (lck) {
607                 NTTIME share_mtime = share_mode_changed_write_time(lck);
608                 /* On close if we're changing the real file time we
609                  * must update it in the open file db too. */
610                 (void)set_write_time(fsp->file_id, fsp->close_write_time);
611
612                 /* Close write times overwrite sticky write times
613                    so we must replace any sticky write time here. */
614                 if (!null_nttime(share_mtime)) {
615                         (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
616                 }
617                 TALLOC_FREE(lck);
618         }
619
620         ft.mtime = fsp->close_write_time;
621         /* As this is a close based update, we are not directly changing the
622            file attributes from a client call, but indirectly from a write. */
623         status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
624         if (!NT_STATUS_IS_OK(status)) {
625                 DEBUG(10,("update_write_time_on_close: smb_set_file_time "
626                         "on file %s returned %s\n",
627                         fsp_str_dbg(fsp),
628                         nt_errstr(status)));
629                 return status;
630         }
631
632         return status;
633 }
634
635 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
636 {
637         if (!NT_STATUS_IS_OK(s1)) {
638                 return s1;
639         }
640         return s2;
641 }
642
643 static void assert_no_pending_aio(struct files_struct *fsp,
644                                   enum file_close_type close_type)
645 {
646         struct smbXsrv_client *client = global_smbXsrv_client;
647         size_t num_connections_alive;
648         unsigned num_requests = fsp->num_aio_requests;
649
650         if (num_requests == 0) {
651                 return;
652         }
653
654         num_connections_alive = smbXsrv_client_valid_connections(client);
655
656         if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
657                 /*
658                  * fsp->aio_requests and the contents (fsp->aio_requests[x])
659                  * are both independently owned by fsp and are not in a
660                  * talloc heirarchy. This allows the fsp->aio_requests array to
661                  * be reallocated independently of the array contents so it can
662                  * grow on demand.
663                  *
664                  * This means we must ensure order of deallocation
665                  * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
666                  * contents first, as their destructors access the
667                  * fsp->aio_request array. If we don't deallocate them
668                  * first, when fsp is deallocated fsp->aio_requests
669                  * could have been deallocated *before* its contents
670                  * fsp->aio_requests[x], causing a crash.
671                  */
672                 while (fsp->num_aio_requests != 0) {
673                         /*
674                          * NB. We *MUST* use
675                          * talloc_free(fsp->aio_requests[0]),
676                          * and *NOT* TALLOC_FREE() here, as
677                          * TALLOC_FREE(fsp->aio_requests[0])
678                          * will overwrite any new contents of
679                          * fsp->aio_requests[0] that were
680                          * copied into it via the destructor
681                          * aio_del_req_from_fsp().
682                          *
683                          * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
684                          */
685                         talloc_free(fsp->aio_requests[0]);
686                 }
687                 return;
688         }
689
690         DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
691         smb_panic("can not close with outstanding aio requests");
692         return;
693 }
694
695 /****************************************************************************
696  Close a file.
697
698  close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
699  printing and magic scripts are only run on normal close.
700  delete on close is done on normal and shutdown close.
701 ****************************************************************************/
702
703 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
704                                   enum file_close_type close_type)
705 {
706         NTSTATUS status = NT_STATUS_OK;
707         NTSTATUS tmp;
708         connection_struct *conn = fsp->conn;
709         bool is_durable = false;
710
711         SMB_ASSERT(fsp->fsp_flags.is_fsa);
712
713         assert_no_pending_aio(fsp, close_type);
714
715         while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
716                 smbd_smb1_brl_finish_by_req(
717                         fsp->blocked_smb1_lock_reqs[0],
718                         NT_STATUS_RANGE_NOT_LOCKED);
719         }
720
721         /*
722          * If we're flushing on a close we can get a write
723          * error here, we must remember this.
724          */
725
726         if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
727                 is_durable = fsp->op->global->durable;
728         }
729
730         if (close_type != SHUTDOWN_CLOSE) {
731                 is_durable = false;
732         }
733
734         if (is_durable) {
735                 DATA_BLOB new_cookie = data_blob_null;
736
737                 tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
738                                         fsp->op->global->backend_cookie,
739                                         fsp->op,
740                                         &new_cookie);
741                 if (NT_STATUS_IS_OK(tmp)) {
742                         struct timeval tv;
743                         NTTIME now;
744
745                         if (req != NULL) {
746                                 tv = req->request_time;
747                         } else {
748                                 tv = timeval_current();
749                         }
750                         now = timeval_to_nttime(&tv);
751
752                         data_blob_free(&fsp->op->global->backend_cookie);
753                         fsp->op->global->backend_cookie = new_cookie;
754
755                         fsp->op->compat = NULL;
756                         tmp = smbXsrv_open_close(fsp->op, now);
757                         if (!NT_STATUS_IS_OK(tmp)) {
758                                 DEBUG(1, ("Failed to update smbXsrv_open "
759                                           "record when disconnecting durable "
760                                           "handle for file %s: %s - "
761                                           "proceeding with normal close\n",
762                                           fsp_str_dbg(fsp), nt_errstr(tmp)));
763                         }
764                         scavenger_schedule_disconnected(fsp);
765                 } else {
766                         DEBUG(1, ("Failed to disconnect durable handle for "
767                                   "file %s: %s - proceeding with normal "
768                                   "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
769                 }
770                 if (!NT_STATUS_IS_OK(tmp)) {
771                         is_durable = false;
772                 }
773         }
774
775         if (is_durable) {
776                 /*
777                  * This is the case where we successfully disconnected
778                  * a durable handle and closed the underlying file.
779                  * In all other cases, we proceed with a genuine close.
780                  */
781                 DEBUG(10, ("%s disconnected durable handle for file %s\n",
782                            conn->session_info->unix_info->unix_name,
783                            fsp_str_dbg(fsp)));
784                 file_free(req, fsp);
785                 return NT_STATUS_OK;
786         }
787
788         if (fsp->op != NULL) {
789                 /*
790                  * Make sure the handle is not marked as durable anymore
791                  */
792                 fsp->op->global->durable = false;
793         }
794
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. */
798
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);
803         }
804
805         locking_close_file(fsp, close_type);
806
807         /*
808          * Ensure pending modtime is set before closing underlying fd.
809          */
810
811         tmp = update_write_time_on_close(fsp);
812         if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
813                 /*
814                  * Someone renamed the file or a parent directory containing
815                  * this file. We can't do anything about this, eat the error.
816                  */
817                 tmp = NT_STATUS_OK;
818         }
819         status = ntstatus_keeperror(status, tmp);
820
821         tmp = fd_close(fsp);
822         status = ntstatus_keeperror(status, tmp);
823
824         /* check for magic scripts */
825         if (close_type == NORMAL_CLOSE) {
826                 tmp = check_magic(fsp);
827                 status = ntstatus_keeperror(status, tmp);
828         }
829
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) ));
834
835         file_free(req, fsp);
836         return status;
837 }
838 /****************************************************************************
839  Function used by reply_rmdir to delete an entire directory
840  tree recursively. Return True on ok, False on fail.
841 ****************************************************************************/
842
843 bool recursive_rmdir(TALLOC_CTX *ctx,
844                      connection_struct *conn,
845                      struct smb_filename *smb_dname)
846 {
847         const char *dname = NULL;
848         char *talloced = NULL;
849         bool ret = True;
850         long offset = 0;
851         SMB_STRUCT_STAT st;
852         struct smb_Dir *dir_hnd;
853         struct files_struct *dirfsp = NULL;
854         int retval;
855         NTSTATUS status;
856
857         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
858
859         dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0);
860         if (dir_hnd == NULL)
861                 return False;
862
863         dirfsp = dir_hnd_fetch_fsp(dir_hnd);
864
865         while ((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
866                 struct smb_filename *atname = NULL;
867                 struct smb_filename *smb_dname_full = NULL;
868                 char *fullname = NULL;
869                 bool do_break = true;
870                 int unlink_flags = 0;
871
872                 if (ISDOT(dname) || ISDOTDOT(dname)) {
873                         TALLOC_FREE(talloced);
874                         continue;
875                 }
876
877                 /* Construct the full name. */
878                 fullname = talloc_asprintf(ctx,
879                                 "%s/%s",
880                                 smb_dname->base_name,
881                                 dname);
882                 if (!fullname) {
883                         errno = ENOMEM;
884                         goto err_break;
885                 }
886
887                 smb_dname_full = synthetic_smb_fname(talloc_tos(),
888                                                 fullname,
889                                                 NULL,
890                                                 NULL,
891                                                 smb_dname->twrp,
892                                                 smb_dname->flags);
893                 if (smb_dname_full == NULL) {
894                         errno = ENOMEM;
895                         goto err_break;
896                 }
897
898                 if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
899                         goto err_break;
900                 }
901
902                 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
903                         if (!recursive_rmdir(ctx, conn, smb_dname_full)) {
904                                 goto err_break;
905                         }
906                         unlink_flags = AT_REMOVEDIR;
907                 }
908
909                 status = synthetic_pathref(talloc_tos(),
910                                            dirfsp,
911                                            dname,
912                                            NULL,
913                                            &smb_dname_full->st,
914                                            smb_dname_full->twrp,
915                                            smb_dname_full->flags,
916                                            &atname);
917                 if (!NT_STATUS_IS_OK(status)) {
918                         errno = map_errno_from_nt_status(status);
919                         goto err_break;
920                 }
921
922                 if (!is_visible_fsp(atname->fsp)) {
923                         TALLOC_FREE(smb_dname_full);
924                         TALLOC_FREE(fullname);
925                         TALLOC_FREE(talloced);
926                         TALLOC_FREE(atname);
927                         continue;
928                 }
929
930                 retval = SMB_VFS_UNLINKAT(conn,
931                                           dirfsp,
932                                           atname,
933                                           unlink_flags);
934                 if (retval != 0) {
935                         goto err_break;
936                 }
937
938                 /* Successful iteration. */
939                 do_break = false;
940
941          err_break:
942                 TALLOC_FREE(smb_dname_full);
943                 TALLOC_FREE(fullname);
944                 TALLOC_FREE(talloced);
945                 TALLOC_FREE(atname);
946                 if (do_break) {
947                         ret = false;
948                         break;
949                 }
950         }
951         TALLOC_FREE(dir_hnd);
952         return ret;
953 }
954
955 /****************************************************************************
956  The internals of the rmdir code - called elsewhere.
957 ****************************************************************************/
958
959 static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
960 {
961         struct connection_struct *conn = fsp->conn;
962         struct smb_filename *smb_dname = fsp->fsp_name;
963         struct smb_filename *parent_fname = NULL;
964         struct smb_filename *at_fname = NULL;
965         SMB_STRUCT_STAT st;
966         const char *dname = NULL;
967         char *talloced = NULL;
968         long dirpos = 0;
969         struct smb_Dir *dir_hnd = NULL;
970         struct files_struct *dirfsp = NULL;
971         int unlink_flags = 0;
972         NTSTATUS status;
973         int ret;
974
975         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
976
977         status = parent_pathref(talloc_tos(),
978                                 conn->cwd_fsp,
979                                 fsp->fsp_name,
980                                 &parent_fname,
981                                 &at_fname);
982         if (!NT_STATUS_IS_OK(status)) {
983                 return status;
984         }
985
986         /*
987          * Todo: use SMB_VFS_STATX() once it's available.
988          */
989
990         /* Might be a symlink. */
991         ret = SMB_VFS_LSTAT(conn, smb_dname);
992         if (ret != 0) {
993                 TALLOC_FREE(parent_fname);
994                 return map_nt_error_from_unix(errno);
995         }
996
997         if (S_ISLNK(smb_dname->st.st_ex_mode)) {
998                 /* Is what it points to a directory ? */
999                 ret = SMB_VFS_STAT(conn, smb_dname);
1000                 if (ret != 0) {
1001                         TALLOC_FREE(parent_fname);
1002                         return map_nt_error_from_unix(errno);
1003                 }
1004                 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
1005                         TALLOC_FREE(parent_fname);
1006                         return NT_STATUS_NOT_A_DIRECTORY;
1007                 }
1008         } else {
1009                 unlink_flags = AT_REMOVEDIR;
1010         }
1011
1012         ret = SMB_VFS_UNLINKAT(conn,
1013                                parent_fname->fsp,
1014                                at_fname,
1015                                unlink_flags);
1016         if (ret == 0) {
1017                 TALLOC_FREE(parent_fname);
1018                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1019                              FILE_NOTIFY_CHANGE_DIR_NAME,
1020                              smb_dname->base_name);
1021                 return NT_STATUS_OK;
1022         }
1023
1024         if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1025                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1026                          "%s\n", smb_fname_str_dbg(smb_dname),
1027                          strerror(errno)));
1028                 TALLOC_FREE(parent_fname);
1029                 return map_nt_error_from_unix(errno);
1030         }
1031
1032         /*
1033          * Here we know the initial directory unlink failed with
1034          * ENOTEMPTY or EEXIST so we know there are objects within.
1035          * If we don't have permission to delete files non
1036          * visible to the client just fail the directory delete.
1037          */
1038
1039         if (!lp_delete_veto_files(SNUM(conn))) {
1040                 errno = ENOTEMPTY;
1041                 goto err;
1042         }
1043
1044         /*
1045          * Check to see if the only thing in this directory are
1046          * files non-visible to the client. If not, fail the delete.
1047          */
1048
1049         dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0);
1050         if (dir_hnd == NULL) {
1051                 errno = ENOTEMPTY;
1052                 goto err;
1053         }
1054
1055         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
1056                 struct smb_filename *smb_dname_full = NULL;
1057                 struct smb_filename *direntry_fname = NULL;
1058                 char *fullname = NULL;
1059
1060                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1061                         TALLOC_FREE(talloced);
1062                         continue;
1063                 }
1064                 if (IS_VETO_PATH(conn, dname)) {
1065                         TALLOC_FREE(talloced);
1066                         continue;
1067                 }
1068
1069                 fullname = talloc_asprintf(talloc_tos(),
1070                                            "%s/%s",
1071                                            smb_dname->base_name,
1072                                            dname);
1073
1074                 if (fullname == NULL) {
1075                         TALLOC_FREE(talloced);
1076                         errno = ENOMEM;
1077                         goto err;
1078                 }
1079
1080                 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1081                                                      fullname,
1082                                                      NULL,
1083                                                      NULL,
1084                                                      smb_dname->twrp,
1085                                                      smb_dname->flags);
1086                 if (smb_dname_full == NULL) {
1087                         TALLOC_FREE(talloced);
1088                         TALLOC_FREE(fullname);
1089                         errno = ENOMEM;
1090                         goto err;
1091                 }
1092
1093                 ret = SMB_VFS_LSTAT(conn, smb_dname_full);
1094                 if (ret != 0) {
1095                         int saved_errno = errno;
1096                         TALLOC_FREE(talloced);
1097                         TALLOC_FREE(fullname);
1098                         TALLOC_FREE(smb_dname_full);
1099                         errno = saved_errno;
1100                         goto err;
1101                 }
1102
1103                 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1104                         /* Could it be an msdfs link ? */
1105                         if (lp_host_msdfs() &&
1106                             lp_msdfs_root(SNUM(conn))) {
1107                                 struct smb_filename *smb_atname;
1108                                 smb_atname = synthetic_smb_fname(talloc_tos(),
1109                                                         dname,
1110                                                         NULL,
1111                                                         &smb_dname_full->st,
1112                                                         fsp->fsp_name->twrp,
1113                                                         fsp->fsp_name->flags);
1114                                 if (smb_atname == NULL) {
1115                                         TALLOC_FREE(talloced);
1116                                         TALLOC_FREE(fullname);
1117                                         TALLOC_FREE(smb_dname_full);
1118                                         errno = ENOMEM;
1119                                         goto err;
1120                                 }
1121                                 if (is_msdfs_link(fsp, smb_atname)) {
1122                                         TALLOC_FREE(talloced);
1123                                         TALLOC_FREE(fullname);
1124                                         TALLOC_FREE(smb_dname_full);
1125                                         TALLOC_FREE(smb_atname);
1126                                         DBG_DEBUG("got msdfs link name %s "
1127                                                 "- can't delete directory %s\n",
1128                                                 dname,
1129                                                 fsp_str_dbg(fsp));
1130                                         errno = ENOTEMPTY;
1131                                         goto err;
1132                                 }
1133                                 TALLOC_FREE(smb_atname);
1134                         }
1135
1136                         /* Not a DFS link - could it be a dangling symlink ? */
1137                         ret = SMB_VFS_STAT(conn, smb_dname_full);
1138                         if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
1139                                 /*
1140                                  * Dangling symlink.
1141                                  * Allow delete as "delete veto files = yes"
1142                                  */
1143                                 TALLOC_FREE(talloced);
1144                                 TALLOC_FREE(fullname);
1145                                 TALLOC_FREE(smb_dname_full);
1146                                 continue;
1147                         }
1148
1149                         DBG_DEBUG("got symlink name %s - "
1150                                 "can't delete directory %s\n",
1151                                 dname,
1152                                 fsp_str_dbg(fsp));
1153                         TALLOC_FREE(talloced);
1154                         TALLOC_FREE(fullname);
1155                         TALLOC_FREE(smb_dname_full);
1156                         errno = ENOTEMPTY;
1157                         goto err;
1158                 }
1159
1160                 /* Not a symlink, get a pathref. */
1161                 status = synthetic_pathref(talloc_tos(),
1162                                            dirfsp,
1163                                            dname,
1164                                            NULL,
1165                                            &smb_dname_full->st,
1166                                            smb_dname->twrp,
1167                                            smb_dname->flags,
1168                                            &direntry_fname);
1169                 if (!NT_STATUS_IS_OK(status)) {
1170                         TALLOC_FREE(talloced);
1171                         TALLOC_FREE(fullname);
1172                         TALLOC_FREE(smb_dname_full);
1173                         errno = map_errno_from_nt_status(status);
1174                         goto err;
1175                 }
1176
1177                 if (!is_visible_fsp(direntry_fname->fsp)) {
1178                         TALLOC_FREE(talloced);
1179                         TALLOC_FREE(fullname);
1180                         TALLOC_FREE(smb_dname_full);
1181                         TALLOC_FREE(direntry_fname);
1182                         continue;
1183                 }
1184
1185                 /*
1186                  * We found a client visible name.
1187                  * We cannot delete this directory.
1188                  */
1189                 DBG_DEBUG("got name %s - "
1190                         "can't delete directory %s\n",
1191                         dname,
1192                         fsp_str_dbg(fsp));
1193                 TALLOC_FREE(talloced);
1194                 TALLOC_FREE(fullname);
1195                 TALLOC_FREE(smb_dname_full);
1196                 TALLOC_FREE(direntry_fname);
1197                 errno = ENOTEMPTY;
1198                 goto err;
1199         }
1200
1201         /* Do a recursive delete. */
1202         RewindDir(dir_hnd,&dirpos);
1203         dirfsp = dir_hnd_fetch_fsp(dir_hnd);
1204
1205         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
1206                 struct smb_filename *direntry_fname = NULL;
1207                 struct smb_filename *smb_dname_full = NULL;
1208                 char *fullname = NULL;
1209                 bool do_break = true;
1210                 int retval;
1211
1212                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1213                         TALLOC_FREE(talloced);
1214                         continue;
1215                 }
1216
1217                 fullname = talloc_asprintf(ctx,
1218                                            "%s/%s",
1219                                            smb_dname->base_name,
1220                                            dname);
1221
1222                 if (fullname == NULL) {
1223                         errno = ENOMEM;
1224                         goto err_break;
1225                 }
1226
1227                 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1228                                                      fullname,
1229                                                      NULL,
1230                                                      NULL,
1231                                                      smb_dname->twrp,
1232                                                      smb_dname->flags);
1233                 if (smb_dname_full == NULL) {
1234                         errno = ENOMEM;
1235                         goto err_break;
1236                 }
1237
1238                 /*
1239                  * Todo: use SMB_VFS_STATX() once that's available.
1240                  */
1241
1242                 ret = SMB_VFS_LSTAT(conn, smb_dname_full);
1243                 if (ret != 0) {
1244                         goto err_break;
1245                 }
1246
1247                 /*
1248                  * We are only dealing with VETO'ed objects
1249                  * here. If it's a symlink, just delete the
1250                  * link without caring what it is pointing
1251                  * to.
1252                  */
1253                 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1254                         direntry_fname = synthetic_smb_fname(talloc_tos(),
1255                                                         dname,
1256                                                         NULL,
1257                                                         &smb_dname_full->st,
1258                                                         smb_dname->twrp,
1259                                                         smb_dname->flags);
1260                         if (direntry_fname == NULL) {
1261                                 errno = ENOMEM;
1262                                 goto err_break;
1263                         }
1264                 } else {
1265                         status = synthetic_pathref(talloc_tos(),
1266                                                    dirfsp,
1267                                                    dname,
1268                                                    NULL,
1269                                                    &smb_dname_full->st,
1270                                                    smb_dname->twrp,
1271                                                    smb_dname->flags,
1272                                                    &direntry_fname);
1273                         if (!NT_STATUS_IS_OK(status)) {
1274                                 errno = map_errno_from_nt_status(status);
1275                                 goto err_break;
1276                         }
1277
1278                         if (!is_visible_fsp(direntry_fname->fsp)) {
1279                                 TALLOC_FREE(fullname);
1280                                 TALLOC_FREE(smb_dname_full);
1281                                 TALLOC_FREE(talloced);
1282                                 TALLOC_FREE(direntry_fname);
1283                                 continue;
1284                         }
1285                 }
1286
1287                 unlink_flags = 0;
1288
1289                 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1290                         if (!recursive_rmdir(ctx, conn,
1291                                              smb_dname_full))
1292                         {
1293                                 goto err_break;
1294                         }
1295                         unlink_flags = AT_REMOVEDIR;
1296                 }
1297
1298                 retval = SMB_VFS_UNLINKAT(conn,
1299                                           dirfsp,
1300                                           direntry_fname,
1301                                           unlink_flags);
1302                 if (retval != 0) {
1303                         goto err_break;
1304                 }
1305
1306                 /* Successful iteration. */
1307                 do_break = false;
1308
1309         err_break:
1310                 TALLOC_FREE(fullname);
1311                 TALLOC_FREE(smb_dname_full);
1312                 TALLOC_FREE(talloced);
1313                 TALLOC_FREE(direntry_fname);
1314                 if (do_break) {
1315                         break;
1316                 }
1317         }
1318
1319         /* Retry the rmdir */
1320         ret = SMB_VFS_UNLINKAT(conn,
1321                                parent_fname->fsp,
1322                                at_fname,
1323                                AT_REMOVEDIR);
1324
1325
1326   err:
1327
1328         TALLOC_FREE(dir_hnd);
1329         TALLOC_FREE(parent_fname);
1330
1331         if (ret != 0) {
1332                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1333                          "%s\n", smb_fname_str_dbg(smb_dname),
1334                          strerror(errno)));
1335                 return map_nt_error_from_unix(errno);
1336         }
1337
1338         notify_fname(conn, NOTIFY_ACTION_REMOVED,
1339                      FILE_NOTIFY_CHANGE_DIR_NAME,
1340                      smb_dname->base_name);
1341
1342         return NT_STATUS_OK;
1343 }
1344
1345 /****************************************************************************
1346  Close a directory opened by an NT SMB call. 
1347 ****************************************************************************/
1348   
1349 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1350                                 enum file_close_type close_type)
1351 {
1352         struct share_mode_lock *lck = NULL;
1353         bool delete_dir = False;
1354         NTSTATUS status = NT_STATUS_OK;
1355         NTSTATUS status1 = NT_STATUS_OK;
1356         const struct security_token *del_nt_token = NULL;
1357         const struct security_unix_token *del_token = NULL;
1358         NTSTATUS notify_status;
1359
1360         SMB_ASSERT(fsp->fsp_flags.is_fsa);
1361
1362         if (fsp->conn->sconn->using_smb2) {
1363                 notify_status = NT_STATUS_NOTIFY_CLEANUP;
1364         } else {
1365                 notify_status = NT_STATUS_OK;
1366         }
1367
1368         assert_no_pending_aio(fsp, close_type);
1369
1370         /*
1371          * NT can set delete_on_close of the last open
1372          * reference to a directory also.
1373          */
1374
1375         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1376         if (lck == NULL) {
1377                 DEBUG(0, ("close_directory: Could not get share mode lock for "
1378                           "%s\n", fsp_str_dbg(fsp)));
1379                 file_free(req, fsp);
1380                 return NT_STATUS_INVALID_PARAMETER;
1381         }
1382
1383         if (fsp->fsp_flags.initial_delete_on_close) {
1384                 /* Initial delete on close was set - for
1385                  * directories we don't care if anyone else
1386                  * wrote a real delete on close. */
1387
1388                 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
1389                                                fsp->fsp_name->base_name);
1390                 set_delete_on_close_lck(fsp, lck,
1391                                         fsp->conn->session_info->security_token,
1392                                         fsp->conn->session_info->unix_token);
1393                 fsp->fsp_flags.delete_on_close = true;
1394         }
1395
1396         delete_dir = get_delete_on_close_token(
1397                 lck, fsp->name_hash, &del_nt_token, &del_token) &&
1398                 !has_other_nonposix_opens(lck, fsp);
1399
1400         if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
1401                                 delete_dir) {
1402         
1403                 /* Become the user who requested the delete. */
1404
1405                 if (!push_sec_ctx()) {
1406                         smb_panic("close_directory: failed to push sec_ctx.\n");
1407                 }
1408
1409                 set_sec_ctx(del_token->uid,
1410                                 del_token->gid,
1411                                 del_token->ngroups,
1412                                 del_token->groups,
1413                                 del_nt_token);
1414
1415                 if (!del_share_mode(lck, fsp)) {
1416                         DEBUG(0, ("close_directory: Could not delete share entry for "
1417                                   "%s\n", fsp_str_dbg(fsp)));
1418                 }
1419
1420                 TALLOC_FREE(lck);
1421
1422                 if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1423                     && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1424
1425                         status = delete_all_streams(fsp->conn, fsp->fsp_name);
1426                         if (!NT_STATUS_IS_OK(status)) {
1427                                 DEBUG(5, ("delete_all_streams failed: %s\n",
1428                                           nt_errstr(status)));
1429                                 file_free(req, fsp);
1430                                 return status;
1431                         }
1432                 }
1433
1434                 status = rmdir_internals(talloc_tos(), fsp);
1435
1436                 DEBUG(5,("close_directory: %s. Delete on close was set - "
1437                          "deleting directory returned %s.\n",
1438                          fsp_str_dbg(fsp), nt_errstr(status)));
1439
1440                 /* unbecome user. */
1441                 pop_sec_ctx();
1442
1443                 /*
1444                  * Ensure we remove any change notify requests that would
1445                  * now fail as the directory has been deleted.
1446                  */
1447
1448                 if (NT_STATUS_IS_OK(status)) {
1449                         notify_status = NT_STATUS_DELETE_PENDING;
1450                 }
1451         } else {
1452                 if (!del_share_mode(lck, fsp)) {
1453                         DEBUG(0, ("close_directory: Could not delete share entry for "
1454                                   "%s\n", fsp_str_dbg(fsp)));
1455                 }
1456
1457                 TALLOC_FREE(lck);
1458         }
1459
1460         remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1461
1462         status1 = fd_close(fsp);
1463
1464         if (!NT_STATUS_IS_OK(status1)) {
1465                 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1466                           fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1467                           strerror(errno)));
1468         }
1469
1470         /*
1471          * Do the code common to files and directories.
1472          */
1473         file_free(req, fsp);
1474
1475         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1476                 status = status1;
1477         }
1478         return status;
1479 }
1480
1481 /****************************************************************************
1482  Close a files_struct.
1483 ****************************************************************************/
1484   
1485 NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
1486                     enum file_close_type close_type)
1487 {
1488         NTSTATUS status;
1489         struct files_struct *base_fsp = fsp->base_fsp;
1490         bool close_base_fsp = false;
1491
1492         /*
1493          * This fsp can never be an internal dirfsp. They must
1494          * be explicitly closed by TALLOC_FREE of the dir handle.
1495          */
1496         SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1497
1498         if (fsp->stream_fsp != NULL) {
1499                 /*
1500                  * fsp is the base for a stream.
1501                  *
1502                  * We're called with SHUTDOWN_CLOSE from files.c which walks the
1503                  * complete list of files.
1504                  *
1505                  * We need to wait until the stream is closed.
1506                  */
1507                 SMB_ASSERT(close_type == SHUTDOWN_CLOSE);
1508                 return NT_STATUS_OK;
1509         }
1510
1511         if (base_fsp != NULL) {
1512                 /*
1513                  * We need to remove the link in order to
1514                  * recurse for the base fsp below.
1515                  */
1516                 SMB_ASSERT(base_fsp->base_fsp == NULL);
1517                 SMB_ASSERT(base_fsp->stream_fsp == fsp);
1518                 base_fsp->stream_fsp = NULL;
1519
1520                 if (close_type == SHUTDOWN_CLOSE) {
1521                         /*
1522                          * We're called with SHUTDOWN_CLOSE from files.c
1523                          * which walks the complete list of files.
1524                          *
1525                          * We may need to defer the SHUTDOWN_CLOSE
1526                          * if it's the next in the linked list.
1527                          *
1528                          * So we only close if the base is *not* the
1529                          * next in the list.
1530                          */
1531                         close_base_fsp = (fsp->next != base_fsp);
1532                 } else {
1533                         close_base_fsp = true;
1534                 }
1535         }
1536
1537         if (fsp->fake_file_handle != NULL) {
1538                 status = close_fake_file(req, fsp);
1539         } else if (fsp->print_file != NULL) {
1540                 /* FIXME: return spool errors */
1541                 print_spool_end(fsp, close_type);
1542                 file_free(req, fsp);
1543                 status = NT_STATUS_OK;
1544         } else if (!fsp->fsp_flags.is_fsa) {
1545                 if (close_type == NORMAL_CLOSE) {
1546                         DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1547                                 "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1548                                 fsp_str_dbg(fsp),
1549                                 fsp->fsp_flags.is_fsa,
1550                                 fsp->fsp_flags.is_pathref,
1551                                 fsp->fsp_flags.is_directory);
1552                 }
1553                 SMB_ASSERT(close_type != NORMAL_CLOSE);
1554                 fd_close(fsp);
1555                 file_free(req, fsp);
1556                 status = NT_STATUS_OK;
1557         } else if (fsp->fsp_flags.is_directory) {
1558                 status = close_directory(req, fsp, close_type);
1559         } else {
1560                 status = close_normal_file(req, fsp, close_type);
1561         }
1562
1563         if (close_base_fsp) {
1564
1565                 /*
1566                  * fsp was a stream, the base fsp can't be a stream as well
1567                  *
1568                  * For SHUTDOWN_CLOSE this is not possible here
1569                  * (if the base_fsp was the next in the linked list), because
1570                  * SHUTDOWN_CLOSE only happens from files.c which walks the
1571                  * complete list of files. If we mess with more than one fsp
1572                  * those loops will become confused.
1573                  */
1574
1575                 close_file(req, base_fsp, close_type);
1576         }
1577
1578         return status;
1579 }
1580
1581 /****************************************************************************
1582  Deal with an (authorized) message to close a file given the share mode
1583  entry.
1584 ****************************************************************************/
1585
1586 void msg_close_file(struct messaging_context *msg_ctx,
1587                         void *private_data,
1588                         uint32_t msg_type,
1589                         struct server_id server_id,
1590                         DATA_BLOB *data)
1591 {
1592         files_struct *fsp = NULL;
1593         struct file_id id;
1594         struct share_mode_entry e;
1595         struct smbd_server_connection *sconn =
1596                 talloc_get_type_abort(private_data,
1597                 struct smbd_server_connection);
1598
1599         message_to_share_mode_entry(&id, &e, (char *)data->data);
1600
1601         if(DEBUGLVL(10)) {
1602                 char *sm_str = share_mode_str(NULL, 0, &id, &e);
1603                 if (!sm_str) {
1604                         smb_panic("talloc failed");
1605                 }
1606                 DEBUG(10,("msg_close_file: got request to close share mode "
1607                         "entry %s\n", sm_str));
1608                 TALLOC_FREE(sm_str);
1609         }
1610
1611         fsp = file_find_dif(sconn, id, e.share_file_id);
1612         if (!fsp) {
1613                 DEBUG(10,("msg_close_file: failed to find file.\n"));
1614                 return;
1615         }
1616         close_file(NULL, fsp, NORMAL_CLOSE);
1617 }