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