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