smbd: NULL out "fsp" in close_file()
[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
368         if (!normal_close || !delete_file) {
369                 status = NT_STATUS_OK;
370                 goto done;
371         }
372
373         /*
374          * Ok, we have to delete the file
375          */
376
377         DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
378                  "- deleting file.\n", fsp_str_dbg(fsp)));
379
380         /*
381          * Don't try to update the write time when we delete the file
382          */
383         fsp->fsp_flags.update_write_time_on_close = false;
384
385         got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
386                                         &del_nt_token, &del_token);
387         SMB_ASSERT(got_tokens);
388
389         if (!unix_token_equal(del_token, get_current_utok(conn))) {
390                 /* Become the user who requested the delete. */
391
392                 DEBUG(5,("close_remove_share_mode: file %s. "
393                         "Change user to uid %u\n",
394                         fsp_str_dbg(fsp),
395                         (unsigned int)del_token->uid));
396
397                 if (!push_sec_ctx()) {
398                         smb_panic("close_remove_share_mode: file %s. failed to push "
399                                   "sec_ctx.\n");
400                 }
401
402                 set_sec_ctx(del_token->uid,
403                             del_token->gid,
404                             del_token->ngroups,
405                             del_token->groups,
406                             del_nt_token);
407
408                 changed_user = true;
409         }
410
411         /* We can only delete the file if the name we have is still valid and
412            hasn't been renamed. */
413
414         tmp_status = vfs_stat_fsp(fsp);
415         if (!NT_STATUS_IS_OK(tmp_status)) {
416                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
417                          "was set and stat failed with error %s\n",
418                          fsp_str_dbg(fsp), nt_errstr(tmp_status)));
419                 /*
420                  * Don't save the errno here, we ignore this error
421                  */
422                 goto done;
423         }
424
425         id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
426
427         if (!file_id_equal(&fsp->file_id, &id)) {
428                 struct file_id_buf ftmp1, ftmp2;
429                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
430                          "was set and dev and/or inode does not match\n",
431                          fsp_str_dbg(fsp)));
432                 DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
433                          "stat file_id %s\n",
434                          fsp_str_dbg(fsp),
435                          file_id_str_buf(fsp->file_id, &ftmp1),
436                          file_id_str_buf(id, &ftmp2)));
437                 /*
438                  * Don't save the errno here, we ignore this error
439                  */
440                 goto done;
441         }
442
443         if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
444             && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
445
446                 status = delete_all_streams(conn, fsp->fsp_name);
447
448                 if (!NT_STATUS_IS_OK(status)) {
449                         DEBUG(5, ("delete_all_streams failed: %s\n",
450                                   nt_errstr(status)));
451                         goto done;
452                 }
453         }
454
455         if (fsp->fsp_flags.kernel_share_modes_taken) {
456                 /*
457                  * A file system sharemode could block the unlink;
458                  * remove filesystem sharemodes first.
459                  */
460                 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
461                 if (ret == -1) {
462                         DBG_INFO("Removing file system sharemode for %s "
463                                  "failed: %s\n",
464                                  fsp_str_dbg(fsp), strerror(errno));
465                 }
466
467                 fsp->fsp_flags.kernel_share_modes_taken = false;
468         }
469
470         status = parent_pathref(talloc_tos(),
471                                 conn->cwd_fsp,
472                                 fsp->fsp_name,
473                                 &parent_fname,
474                                 &base_fname);
475         if (!NT_STATUS_IS_OK(status)) {
476                 goto done;
477         }
478
479         ret = SMB_VFS_UNLINKAT(conn,
480                                parent_fname->fsp,
481                                base_fname,
482                                0);
483         TALLOC_FREE(parent_fname);
484         base_fname = NULL;
485         if (ret != 0) {
486                 /*
487                  * This call can potentially fail as another smbd may
488                  * have had the file open with delete on close set and
489                  * deleted it when its last reference to this file
490                  * went away. Hence we log this but not at debug level
491                  * zero.
492                  */
493
494                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
495                          "was set and unlink failed with error %s\n",
496                          fsp_str_dbg(fsp), strerror(errno)));
497
498                 status = map_nt_error_from_unix(errno);
499         }
500
501         /* As we now have POSIX opens which can unlink
502          * with other open files we may have taken
503          * this code path with more than one share mode
504          * entry - ensure we only delete once by resetting
505          * the delete on close flag. JRA.
506          */
507
508         fsp->fsp_flags.delete_on_close = false;
509         reset_delete_on_close_lck(fsp, lck);
510
511  done:
512
513         if (changed_user) {
514                 /* unbecome user. */
515                 pop_sec_ctx();
516         }
517
518         if (fsp->fsp_flags.kernel_share_modes_taken) {
519                 /* remove filesystem sharemodes */
520                 ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
521                 if (ret == -1) {
522                         DBG_INFO("Removing file system sharemode for "
523                                  "%s failed: %s\n",
524                                  fsp_str_dbg(fsp), strerror(errno));
525                 }
526         }
527
528         if (!del_share_mode(lck, fsp)) {
529                 DEBUG(0, ("close_remove_share_mode: Could not delete share "
530                           "entry for file %s\n", fsp_str_dbg(fsp)));
531         }
532
533         TALLOC_FREE(lck);
534
535         if (delete_file) {
536                 /*
537                  * Do the notification after we released the share
538                  * mode lock. Inside notify_fname we take out another
539                  * tdb lock. With ctdb also accessing our databases,
540                  * this can lead to deadlocks. Putting this notify
541                  * after the TALLOC_FREE(lck) above we avoid locking
542                  * two records simultaneously. Notifies are async and
543                  * informational only, so calling the notify_fname
544                  * without holding the share mode lock should not do
545                  * any harm.
546                  */
547                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
548                              FILE_NOTIFY_CHANGE_FILE_NAME,
549                              fsp->fsp_name->base_name);
550         }
551
552         return status;
553 }
554
555 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
556 {
557         DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
558
559         if (is_omit_timespec(&ts)) {
560                 return;
561         }
562         fsp->fsp_flags.write_time_forced = false;
563         fsp->fsp_flags.update_write_time_on_close = true;
564         fsp->close_write_time = ts;
565 }
566
567 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
568 {
569         struct smb_file_time ft;
570         NTSTATUS status;
571         struct share_mode_lock *lck = NULL;
572
573         init_smb_file_time(&ft);
574
575         if (!(fsp->fsp_flags.update_write_time_on_close)) {
576                 return NT_STATUS_OK;
577         }
578
579         if (is_omit_timespec(&fsp->close_write_time)) {
580                 fsp->close_write_time = timespec_current();
581         }
582
583         /* Ensure we have a valid stat struct for the source. */
584         status = vfs_stat_fsp(fsp);
585         if (!NT_STATUS_IS_OK(status)) {
586                 return status;
587         }
588
589         if (!VALID_STAT(fsp->fsp_name->st)) {
590                 /* if it doesn't seem to be a real file */
591                 return NT_STATUS_OK;
592         }
593
594         /*
595          * get_existing_share_mode_lock() isn't really the right
596          * call here, as we're being called after
597          * close_remove_share_mode() inside close_normal_file()
598          * so it's quite normal to not have an existing share
599          * mode here. However, get_share_mode_lock() doesn't
600          * work because that will create a new share mode if
601          * one doesn't exist - so stick with this call (just
602          * ignore any error we get if the share mode doesn't
603          * exist.
604          */
605
606         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
607         if (lck) {
608                 NTTIME share_mtime = share_mode_changed_write_time(lck);
609                 /* On close if we're changing the real file time we
610                  * must update it in the open file db too. */
611                 (void)set_write_time(fsp->file_id, fsp->close_write_time);
612
613                 /* Close write times overwrite sticky write times
614                    so we must replace any sticky write time here. */
615                 if (!null_nttime(share_mtime)) {
616                         (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
617                 }
618                 TALLOC_FREE(lck);
619         }
620
621         ft.mtime = fsp->close_write_time;
622         /* As this is a close based update, we are not directly changing the
623            file attributes from a client call, but indirectly from a write. */
624         status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
625         if (!NT_STATUS_IS_OK(status)) {
626                 DEBUG(10,("update_write_time_on_close: smb_set_file_time "
627                         "on file %s returned %s\n",
628                         fsp_str_dbg(fsp),
629                         nt_errstr(status)));
630                 return status;
631         }
632
633         return status;
634 }
635
636 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
637 {
638         if (!NT_STATUS_IS_OK(s1)) {
639                 return s1;
640         }
641         return s2;
642 }
643
644 static void assert_no_pending_aio(struct files_struct *fsp,
645                                   enum file_close_type close_type)
646 {
647         struct smbXsrv_client *client = global_smbXsrv_client;
648         size_t num_connections_alive;
649         unsigned num_requests = fsp->num_aio_requests;
650
651         if (num_requests == 0) {
652                 return;
653         }
654
655         num_connections_alive = smbXsrv_client_valid_connections(client);
656
657         if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
658                 /*
659                  * fsp->aio_requests and the contents (fsp->aio_requests[x])
660                  * are both independently owned by fsp and are not in a
661                  * talloc heirarchy. This allows the fsp->aio_requests array to
662                  * be reallocated independently of the array contents so it can
663                  * grow on demand.
664                  *
665                  * This means we must ensure order of deallocation
666                  * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
667                  * contents first, as their destructors access the
668                  * fsp->aio_request array. If we don't deallocate them
669                  * first, when fsp is deallocated fsp->aio_requests
670                  * could have been deallocated *before* its contents
671                  * fsp->aio_requests[x], causing a crash.
672                  */
673                 while (fsp->num_aio_requests != 0) {
674                         /*
675                          * NB. We *MUST* use
676                          * talloc_free(fsp->aio_requests[0]),
677                          * and *NOT* TALLOC_FREE() here, as
678                          * TALLOC_FREE(fsp->aio_requests[0])
679                          * will overwrite any new contents of
680                          * fsp->aio_requests[0] that were
681                          * copied into it via the destructor
682                          * aio_del_req_from_fsp().
683                          *
684                          * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
685                          */
686                         talloc_free(fsp->aio_requests[0]);
687                 }
688                 return;
689         }
690
691         DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
692         smb_panic("can not close with outstanding aio requests");
693         return;
694 }
695
696 /****************************************************************************
697  Close a file.
698
699  close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
700  printing and magic scripts are only run on normal close.
701  delete on close is done on normal and shutdown close.
702 ****************************************************************************/
703
704 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
705                                   enum file_close_type close_type)
706 {
707         NTSTATUS status = NT_STATUS_OK;
708         NTSTATUS tmp;
709         connection_struct *conn = fsp->conn;
710         bool is_durable = false;
711
712         SMB_ASSERT(fsp->fsp_flags.is_fsa);
713
714         assert_no_pending_aio(fsp, close_type);
715
716         while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
717                 smbd_smb1_brl_finish_by_req(
718                         fsp->blocked_smb1_lock_reqs[0],
719                         NT_STATUS_RANGE_NOT_LOCKED);
720         }
721
722         /*
723          * If we're flushing on a close we can get a write
724          * error here, we must remember this.
725          */
726
727         if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
728                 is_durable = fsp->op->global->durable;
729         }
730
731         if (close_type != SHUTDOWN_CLOSE) {
732                 is_durable = false;
733         }
734
735         if (is_durable) {
736                 DATA_BLOB new_cookie = data_blob_null;
737
738                 tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
739                                         fsp->op->global->backend_cookie,
740                                         fsp->op,
741                                         &new_cookie);
742                 if (NT_STATUS_IS_OK(tmp)) {
743                         struct timeval tv;
744                         NTTIME now;
745
746                         if (req != NULL) {
747                                 tv = req->request_time;
748                         } else {
749                                 tv = timeval_current();
750                         }
751                         now = timeval_to_nttime(&tv);
752
753                         data_blob_free(&fsp->op->global->backend_cookie);
754                         fsp->op->global->backend_cookie = new_cookie;
755
756                         fsp->op->compat = NULL;
757                         tmp = smbXsrv_open_close(fsp->op, now);
758                         if (!NT_STATUS_IS_OK(tmp)) {
759                                 DEBUG(1, ("Failed to update smbXsrv_open "
760                                           "record when disconnecting durable "
761                                           "handle for file %s: %s - "
762                                           "proceeding with normal close\n",
763                                           fsp_str_dbg(fsp), nt_errstr(tmp)));
764                         }
765                         scavenger_schedule_disconnected(fsp);
766                 } else {
767                         DEBUG(1, ("Failed to disconnect durable handle for "
768                                   "file %s: %s - proceeding with normal "
769                                   "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
770                 }
771                 if (!NT_STATUS_IS_OK(tmp)) {
772                         is_durable = false;
773                 }
774         }
775
776         if (is_durable) {
777                 /*
778                  * This is the case where we successfully disconnected
779                  * a durable handle and closed the underlying file.
780                  * In all other cases, we proceed with a genuine close.
781                  */
782                 DEBUG(10, ("%s disconnected durable handle for file %s\n",
783                            conn->session_info->unix_info->unix_name,
784                            fsp_str_dbg(fsp)));
785                 return NT_STATUS_OK;
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         return status;
836 }
837 /****************************************************************************
838  Function used by reply_rmdir to delete an entire directory
839  tree recursively. Return True on ok, False on fail.
840 ****************************************************************************/
841
842 bool recursive_rmdir(TALLOC_CTX *ctx,
843                      connection_struct *conn,
844                      struct smb_filename *smb_dname)
845 {
846         const char *dname = NULL;
847         char *talloced = NULL;
848         bool ret = True;
849         long offset = 0;
850         SMB_STRUCT_STAT st;
851         struct smb_Dir *dir_hnd;
852         struct files_struct *dirfsp = NULL;
853         int retval;
854         NTSTATUS status;
855
856         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
857
858         dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0);
859         if (dir_hnd == NULL)
860                 return False;
861
862         dirfsp = dir_hnd_fetch_fsp(dir_hnd);
863
864         while ((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
865                 struct smb_filename *atname = NULL;
866                 struct smb_filename *smb_dname_full = NULL;
867                 char *fullname = NULL;
868                 bool do_break = true;
869                 int unlink_flags = 0;
870
871                 if (ISDOT(dname) || ISDOTDOT(dname)) {
872                         TALLOC_FREE(talloced);
873                         continue;
874                 }
875
876                 /* Construct the full name. */
877                 fullname = talloc_asprintf(ctx,
878                                 "%s/%s",
879                                 smb_dname->base_name,
880                                 dname);
881                 if (!fullname) {
882                         errno = ENOMEM;
883                         goto err_break;
884                 }
885
886                 smb_dname_full = synthetic_smb_fname(talloc_tos(),
887                                                 fullname,
888                                                 NULL,
889                                                 NULL,
890                                                 smb_dname->twrp,
891                                                 smb_dname->flags);
892                 if (smb_dname_full == NULL) {
893                         errno = ENOMEM;
894                         goto err_break;
895                 }
896
897                 if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
898                         goto err_break;
899                 }
900
901                 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
902                         if (!recursive_rmdir(ctx, conn, smb_dname_full)) {
903                                 goto err_break;
904                         }
905                         unlink_flags = AT_REMOVEDIR;
906                 }
907
908                 status = synthetic_pathref(talloc_tos(),
909                                            dirfsp,
910                                            dname,
911                                            NULL,
912                                            &smb_dname_full->st,
913                                            smb_dname_full->twrp,
914                                            smb_dname_full->flags,
915                                            &atname);
916                 if (!NT_STATUS_IS_OK(status)) {
917                         errno = map_errno_from_nt_status(status);
918                         goto err_break;
919                 }
920
921                 if (!is_visible_fsp(atname->fsp)) {
922                         TALLOC_FREE(smb_dname_full);
923                         TALLOC_FREE(fullname);
924                         TALLOC_FREE(talloced);
925                         TALLOC_FREE(atname);
926                         continue;
927                 }
928
929                 retval = SMB_VFS_UNLINKAT(conn,
930                                           dirfsp,
931                                           atname,
932                                           unlink_flags);
933                 if (retval != 0) {
934                         goto err_break;
935                 }
936
937                 /* Successful iteration. */
938                 do_break = false;
939
940          err_break:
941                 TALLOC_FREE(smb_dname_full);
942                 TALLOC_FREE(fullname);
943                 TALLOC_FREE(talloced);
944                 TALLOC_FREE(atname);
945                 if (do_break) {
946                         ret = false;
947                         break;
948                 }
949         }
950         TALLOC_FREE(dir_hnd);
951         return ret;
952 }
953
954 /****************************************************************************
955  The internals of the rmdir code - called elsewhere.
956 ****************************************************************************/
957
958 static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
959 {
960         struct connection_struct *conn = fsp->conn;
961         struct smb_filename *smb_dname = fsp->fsp_name;
962         struct smb_filename *parent_fname = NULL;
963         struct smb_filename *at_fname = NULL;
964         SMB_STRUCT_STAT st;
965         const char *dname = NULL;
966         char *talloced = NULL;
967         long dirpos = 0;
968         struct smb_Dir *dir_hnd = NULL;
969         struct files_struct *dirfsp = NULL;
970         int unlink_flags = 0;
971         NTSTATUS status;
972         int ret;
973
974         SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
975
976         status = parent_pathref(talloc_tos(),
977                                 conn->cwd_fsp,
978                                 fsp->fsp_name,
979                                 &parent_fname,
980                                 &at_fname);
981         if (!NT_STATUS_IS_OK(status)) {
982                 return status;
983         }
984
985         /*
986          * Todo: use SMB_VFS_STATX() once it's available.
987          */
988
989         /* Might be a symlink. */
990         ret = SMB_VFS_LSTAT(conn, smb_dname);
991         if (ret != 0) {
992                 TALLOC_FREE(parent_fname);
993                 return map_nt_error_from_unix(errno);
994         }
995
996         if (S_ISLNK(smb_dname->st.st_ex_mode)) {
997                 /* Is what it points to a directory ? */
998                 ret = SMB_VFS_STAT(conn, smb_dname);
999                 if (ret != 0) {
1000                         TALLOC_FREE(parent_fname);
1001                         return map_nt_error_from_unix(errno);
1002                 }
1003                 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
1004                         TALLOC_FREE(parent_fname);
1005                         return NT_STATUS_NOT_A_DIRECTORY;
1006                 }
1007         } else {
1008                 unlink_flags = AT_REMOVEDIR;
1009         }
1010
1011         ret = SMB_VFS_UNLINKAT(conn,
1012                                parent_fname->fsp,
1013                                at_fname,
1014                                unlink_flags);
1015         if (ret == 0) {
1016                 TALLOC_FREE(parent_fname);
1017                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1018                              FILE_NOTIFY_CHANGE_DIR_NAME,
1019                              smb_dname->base_name);
1020                 return NT_STATUS_OK;
1021         }
1022
1023         if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1024                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1025                          "%s\n", smb_fname_str_dbg(smb_dname),
1026                          strerror(errno)));
1027                 TALLOC_FREE(parent_fname);
1028                 return map_nt_error_from_unix(errno);
1029         }
1030
1031         /*
1032          * Here we know the initial directory unlink failed with
1033          * ENOTEMPTY or EEXIST so we know there are objects within.
1034          * If we don't have permission to delete files non
1035          * visible to the client just fail the directory delete.
1036          */
1037
1038         if (!lp_delete_veto_files(SNUM(conn))) {
1039                 errno = ENOTEMPTY;
1040                 goto err;
1041         }
1042
1043         /*
1044          * Check to see if the only thing in this directory are
1045          * files non-visible to the client. If not, fail the delete.
1046          */
1047
1048         dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0);
1049         if (dir_hnd == NULL) {
1050                 errno = ENOTEMPTY;
1051                 goto err;
1052         }
1053
1054         dirfsp = dir_hnd_fetch_fsp(dir_hnd);
1055
1056         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
1057                 struct smb_filename *smb_dname_full = NULL;
1058                 struct smb_filename *direntry_fname = NULL;
1059                 char *fullname = NULL;
1060                 int retval;
1061
1062                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1063                         TALLOC_FREE(talloced);
1064                         continue;
1065                 }
1066                 if (IS_VETO_PATH(conn, dname)) {
1067                         TALLOC_FREE(talloced);
1068                         continue;
1069                 }
1070
1071                 fullname = talloc_asprintf(talloc_tos(),
1072                                            "%s/%s",
1073                                            smb_dname->base_name,
1074                                            dname);
1075
1076                 if (fullname == NULL) {
1077                         TALLOC_FREE(talloced);
1078                         errno = ENOMEM;
1079                         goto err;
1080                 }
1081
1082                 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1083                                                      fullname,
1084                                                      NULL,
1085                                                      NULL,
1086                                                      smb_dname->twrp,
1087                                                      smb_dname->flags);
1088                 if (smb_dname_full == NULL) {
1089                         TALLOC_FREE(talloced);
1090                         TALLOC_FREE(fullname);
1091                         errno = ENOMEM;
1092                         goto err;
1093                 }
1094
1095                 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1096                 if (retval != 0) {
1097                         int saved_errno = errno;
1098                         TALLOC_FREE(talloced);
1099                         TALLOC_FREE(fullname);
1100                         TALLOC_FREE(smb_dname_full);
1101                         errno = saved_errno;
1102                         goto err;
1103                 }
1104
1105                 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1106                         /* Could it be an msdfs link ? */
1107                         if (lp_host_msdfs() &&
1108                             lp_msdfs_root(SNUM(conn))) {
1109                                 struct smb_filename *smb_atname;
1110                                 smb_atname = synthetic_smb_fname(talloc_tos(),
1111                                                         dname,
1112                                                         NULL,
1113                                                         &smb_dname_full->st,
1114                                                         fsp->fsp_name->twrp,
1115                                                         fsp->fsp_name->flags);
1116                                 if (smb_atname == NULL) {
1117                                         TALLOC_FREE(talloced);
1118                                         TALLOC_FREE(fullname);
1119                                         TALLOC_FREE(smb_dname_full);
1120                                         errno = ENOMEM;
1121                                         goto err;
1122                                 }
1123                                 if (is_msdfs_link(fsp, smb_atname)) {
1124                                         TALLOC_FREE(talloced);
1125                                         TALLOC_FREE(fullname);
1126                                         TALLOC_FREE(smb_dname_full);
1127                                         TALLOC_FREE(smb_atname);
1128                                         DBG_DEBUG("got msdfs link name %s "
1129                                                 "- can't delete directory %s\n",
1130                                                 dname,
1131                                                 fsp_str_dbg(fsp));
1132                                         errno = ENOTEMPTY;
1133                                         goto err;
1134                                 }
1135                                 TALLOC_FREE(smb_atname);
1136                         }
1137
1138                         /* Not a DFS link - could it be a dangling symlink ? */
1139                         retval = SMB_VFS_STAT(conn, smb_dname_full);
1140                         if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
1141                                 /*
1142                                  * Dangling symlink.
1143                                  * Allow delete as "delete veto files = yes"
1144                                  */
1145                                 TALLOC_FREE(talloced);
1146                                 TALLOC_FREE(fullname);
1147                                 TALLOC_FREE(smb_dname_full);
1148                                 continue;
1149                         }
1150
1151                         DBG_DEBUG("got symlink name %s - "
1152                                 "can't delete directory %s\n",
1153                                 dname,
1154                                 fsp_str_dbg(fsp));
1155                         TALLOC_FREE(talloced);
1156                         TALLOC_FREE(fullname);
1157                         TALLOC_FREE(smb_dname_full);
1158                         errno = ENOTEMPTY;
1159                         goto err;
1160                 }
1161
1162                 /* Not a symlink, get a pathref. */
1163                 status = synthetic_pathref(talloc_tos(),
1164                                            dirfsp,
1165                                            dname,
1166                                            NULL,
1167                                            &smb_dname_full->st,
1168                                            smb_dname->twrp,
1169                                            smb_dname->flags,
1170                                            &direntry_fname);
1171                 if (!NT_STATUS_IS_OK(status)) {
1172                         TALLOC_FREE(talloced);
1173                         TALLOC_FREE(fullname);
1174                         TALLOC_FREE(smb_dname_full);
1175                         errno = map_errno_from_nt_status(status);
1176                         goto err;
1177                 }
1178
1179                 if (!is_visible_fsp(direntry_fname->fsp)) {
1180                         TALLOC_FREE(talloced);
1181                         TALLOC_FREE(fullname);
1182                         TALLOC_FREE(smb_dname_full);
1183                         TALLOC_FREE(direntry_fname);
1184                         continue;
1185                 }
1186
1187                 /*
1188                  * We found a client visible name.
1189                  * We cannot delete this directory.
1190                  */
1191                 DBG_DEBUG("got name %s - "
1192                         "can't delete directory %s\n",
1193                         dname,
1194                         fsp_str_dbg(fsp));
1195                 TALLOC_FREE(talloced);
1196                 TALLOC_FREE(fullname);
1197                 TALLOC_FREE(smb_dname_full);
1198                 TALLOC_FREE(direntry_fname);
1199                 errno = ENOTEMPTY;
1200                 goto err;
1201         }
1202
1203         /* Do a recursive delete. */
1204         RewindDir(dir_hnd,&dirpos);
1205
1206         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
1207                 struct smb_filename *direntry_fname = NULL;
1208                 struct smb_filename *smb_dname_full = NULL;
1209                 char *fullname = NULL;
1210                 bool do_break = true;
1211                 int retval;
1212
1213                 if (ISDOT(dname) || ISDOTDOT(dname)) {
1214                         TALLOC_FREE(talloced);
1215                         continue;
1216                 }
1217
1218                 fullname = talloc_asprintf(ctx,
1219                                            "%s/%s",
1220                                            smb_dname->base_name,
1221                                            dname);
1222
1223                 if (fullname == NULL) {
1224                         errno = ENOMEM;
1225                         goto err_break;
1226                 }
1227
1228                 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1229                                                      fullname,
1230                                                      NULL,
1231                                                      NULL,
1232                                                      smb_dname->twrp,
1233                                                      smb_dname->flags);
1234                 if (smb_dname_full == NULL) {
1235                         errno = ENOMEM;
1236                         goto err_break;
1237                 }
1238
1239                 /*
1240                  * Todo: use SMB_VFS_STATX() once that's available.
1241                  */
1242
1243                 retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1244                 if (retval != 0) {
1245                         goto err_break;
1246                 }
1247
1248                 /*
1249                  * We are only dealing with VETO'ed objects
1250                  * here. If it's a symlink, just delete the
1251                  * link without caring what it is pointing
1252                  * to.
1253                  */
1254                 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1255                         direntry_fname = synthetic_smb_fname(talloc_tos(),
1256                                                         dname,
1257                                                         NULL,
1258                                                         &smb_dname_full->st,
1259                                                         smb_dname->twrp,
1260                                                         smb_dname->flags);
1261                         if (direntry_fname == NULL) {
1262                                 errno = ENOMEM;
1263                                 goto err_break;
1264                         }
1265                 } else {
1266                         status = synthetic_pathref(talloc_tos(),
1267                                                    dirfsp,
1268                                                    dname,
1269                                                    NULL,
1270                                                    &smb_dname_full->st,
1271                                                    smb_dname->twrp,
1272                                                    smb_dname->flags,
1273                                                    &direntry_fname);
1274                         if (!NT_STATUS_IS_OK(status)) {
1275                                 errno = map_errno_from_nt_status(status);
1276                                 goto err_break;
1277                         }
1278
1279                         if (!is_visible_fsp(direntry_fname->fsp)) {
1280                                 TALLOC_FREE(fullname);
1281                                 TALLOC_FREE(smb_dname_full);
1282                                 TALLOC_FREE(talloced);
1283                                 TALLOC_FREE(direntry_fname);
1284                                 continue;
1285                         }
1286                 }
1287
1288                 unlink_flags = 0;
1289
1290                 if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1291                         if (!recursive_rmdir(ctx, conn,
1292                                              smb_dname_full))
1293                         {
1294                                 goto err_break;
1295                         }
1296                         unlink_flags = AT_REMOVEDIR;
1297                 }
1298
1299                 retval = SMB_VFS_UNLINKAT(conn,
1300                                           dirfsp,
1301                                           direntry_fname,
1302                                           unlink_flags);
1303                 if (retval != 0) {
1304                         goto err_break;
1305                 }
1306
1307                 /* Successful iteration. */
1308                 do_break = false;
1309
1310         err_break:
1311                 TALLOC_FREE(fullname);
1312                 TALLOC_FREE(smb_dname_full);
1313                 TALLOC_FREE(talloced);
1314                 TALLOC_FREE(direntry_fname);
1315                 if (do_break) {
1316                         break;
1317                 }
1318         }
1319
1320         /* Retry the rmdir */
1321         ret = SMB_VFS_UNLINKAT(conn,
1322                                parent_fname->fsp,
1323                                at_fname,
1324                                AT_REMOVEDIR);
1325
1326
1327   err:
1328
1329         TALLOC_FREE(dir_hnd);
1330         TALLOC_FREE(parent_fname);
1331
1332         if (ret != 0) {
1333                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1334                          "%s\n", smb_fname_str_dbg(smb_dname),
1335                          strerror(errno)));
1336                 return map_nt_error_from_unix(errno);
1337         }
1338
1339         notify_fname(conn, NOTIFY_ACTION_REMOVED,
1340                      FILE_NOTIFY_CHANGE_DIR_NAME,
1341                      smb_dname->base_name);
1342
1343         return NT_STATUS_OK;
1344 }
1345
1346 /****************************************************************************
1347  Close a directory opened by an NT SMB call. 
1348 ****************************************************************************/
1349   
1350 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1351                                 enum file_close_type close_type)
1352 {
1353         struct share_mode_lock *lck = NULL;
1354         bool delete_dir = False;
1355         NTSTATUS status = NT_STATUS_OK;
1356         NTSTATUS status1 = NT_STATUS_OK;
1357         const struct security_token *del_nt_token = NULL;
1358         const struct security_unix_token *del_token = NULL;
1359         NTSTATUS notify_status;
1360
1361         SMB_ASSERT(fsp->fsp_flags.is_fsa);
1362
1363         if (fsp->conn->sconn->using_smb2) {
1364                 notify_status = NT_STATUS_NOTIFY_CLEANUP;
1365         } else {
1366                 notify_status = NT_STATUS_OK;
1367         }
1368
1369         assert_no_pending_aio(fsp, close_type);
1370
1371         /*
1372          * NT can set delete_on_close of the last open
1373          * reference to a directory also.
1374          */
1375
1376         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1377         if (lck == NULL) {
1378                 DEBUG(0, ("close_directory: Could not get share mode lock for "
1379                           "%s\n", fsp_str_dbg(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                                 /* unbecome user. */
1430                                 pop_sec_ctx();
1431                                 return status;
1432                         }
1433                 }
1434
1435                 status = rmdir_internals(talloc_tos(), fsp);
1436
1437                 DEBUG(5,("close_directory: %s. Delete on close was set - "
1438                          "deleting directory returned %s.\n",
1439                          fsp_str_dbg(fsp), nt_errstr(status)));
1440
1441                 /* unbecome user. */
1442                 pop_sec_ctx();
1443
1444                 /*
1445                  * Ensure we remove any change notify requests that would
1446                  * now fail as the directory has been deleted.
1447                  */
1448
1449                 if (NT_STATUS_IS_OK(status)) {
1450                         notify_status = NT_STATUS_DELETE_PENDING;
1451                 }
1452         } else {
1453                 if (!del_share_mode(lck, fsp)) {
1454                         DEBUG(0, ("close_directory: Could not delete share entry for "
1455                                   "%s\n", fsp_str_dbg(fsp)));
1456                 }
1457
1458                 TALLOC_FREE(lck);
1459         }
1460
1461         remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1462
1463         status1 = fd_close(fsp);
1464
1465         if (!NT_STATUS_IS_OK(status1)) {
1466                 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1467                           fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1468                           strerror(errno)));
1469         }
1470
1471         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1472                 status = status1;
1473         }
1474         return status;
1475 }
1476
1477 /****************************************************************************
1478  Close a files_struct.
1479 ****************************************************************************/
1480   
1481 NTSTATUS close_file_free(struct smb_request *req,
1482                          struct files_struct **_fsp,
1483                          enum file_close_type close_type)
1484 {
1485         NTSTATUS status;
1486         struct files_struct *fsp = *_fsp;
1487         struct files_struct *base_fsp = fsp->base_fsp;
1488         bool close_base_fsp = false;
1489
1490         /*
1491          * This fsp can never be an internal dirfsp. They must
1492          * be explicitly closed by TALLOC_FREE of the dir handle.
1493          */
1494         SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1495
1496         if (fsp->stream_fsp != NULL) {
1497                 /*
1498                  * fsp is the base for a stream.
1499                  *
1500                  * We're called with SHUTDOWN_CLOSE from files.c which walks the
1501                  * complete list of files.
1502                  *
1503                  * We need to wait until the stream is closed.
1504                  */
1505                 SMB_ASSERT(close_type == SHUTDOWN_CLOSE);
1506                 return NT_STATUS_OK;
1507         }
1508
1509         if (base_fsp != NULL) {
1510                 /*
1511                  * We need to remove the link in order to
1512                  * recurse for the base fsp below.
1513                  */
1514                 SMB_ASSERT(base_fsp->base_fsp == NULL);
1515                 SMB_ASSERT(base_fsp->stream_fsp == fsp);
1516                 base_fsp->stream_fsp = NULL;
1517
1518                 if (close_type == SHUTDOWN_CLOSE) {
1519                         /*
1520                          * We're called with SHUTDOWN_CLOSE from files.c
1521                          * which walks the complete list of files.
1522                          *
1523                          * We may need to defer the SHUTDOWN_CLOSE
1524                          * if it's the next in the linked list.
1525                          *
1526                          * So we only close if the base is *not* the
1527                          * next in the list.
1528                          */
1529                         close_base_fsp = (fsp->next != base_fsp);
1530                 } else {
1531                         close_base_fsp = true;
1532                 }
1533         }
1534
1535         if (fsp->fake_file_handle != NULL) {
1536                 status = close_fake_file(req, fsp);
1537         } else if (fsp->print_file != NULL) {
1538                 /* FIXME: return spool errors */
1539                 print_spool_end(fsp, close_type);
1540                 fd_close(fsp);
1541                 status = NT_STATUS_OK;
1542         } else if (!fsp->fsp_flags.is_fsa) {
1543                 if (close_type == NORMAL_CLOSE) {
1544                         DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1545                                 "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1546                                 fsp_str_dbg(fsp),
1547                                 fsp->fsp_flags.is_fsa,
1548                                 fsp->fsp_flags.is_pathref,
1549                                 fsp->fsp_flags.is_directory);
1550                 }
1551                 SMB_ASSERT(close_type != NORMAL_CLOSE);
1552                 fd_close(fsp);
1553                 status = NT_STATUS_OK;
1554         } else if (fsp->fsp_flags.is_directory) {
1555                 status = close_directory(req, fsp, close_type);
1556         } else {
1557                 status = close_normal_file(req, fsp, close_type);
1558         }
1559
1560         file_free(req, fsp);
1561
1562         if (close_base_fsp) {
1563
1564                 /*
1565                  * fsp was a stream, the base fsp can't be a stream as well
1566                  *
1567                  * For SHUTDOWN_CLOSE this is not possible here
1568                  * (if the base_fsp was the next in the linked list), because
1569                  * SHUTDOWN_CLOSE only happens from files.c which walks the
1570                  * complete list of files. If we mess with more than one fsp
1571                  * those loops will become confused.
1572                  */
1573
1574                 close_file_free(req, &base_fsp, close_type);
1575         }
1576
1577         *_fsp = NULL;
1578
1579         return status;
1580 }
1581
1582 /****************************************************************************
1583  Deal with an (authorized) message to close a file given the share mode
1584  entry.
1585 ****************************************************************************/
1586
1587 void msg_close_file(struct messaging_context *msg_ctx,
1588                         void *private_data,
1589                         uint32_t msg_type,
1590                         struct server_id server_id,
1591                         DATA_BLOB *data)
1592 {
1593         files_struct *fsp = NULL;
1594         struct file_id id;
1595         struct share_mode_entry e;
1596         struct smbd_server_connection *sconn =
1597                 talloc_get_type_abort(private_data,
1598                 struct smbd_server_connection);
1599
1600         message_to_share_mode_entry(&id, &e, (char *)data->data);
1601
1602         if(DEBUGLVL(10)) {
1603                 char *sm_str = share_mode_str(NULL, 0, &id, &e);
1604                 if (!sm_str) {
1605                         smb_panic("talloc failed");
1606                 }
1607                 DEBUG(10,("msg_close_file: got request to close share mode "
1608                         "entry %s\n", sm_str));
1609                 TALLOC_FREE(sm_str);
1610         }
1611
1612         fsp = file_find_dif(sconn, id, e.share_file_id);
1613         if (!fsp) {
1614                 DEBUG(10,("msg_close_file: failed to find file.\n"));
1615                 return;
1616         }
1617         close_file_free(NULL, &fsp, NORMAL_CLOSE);
1618 }