s3: Plumb smb_filename through SMB_VFS_UNLINK
[metze/samba/wip.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
24 extern struct current_user current_user;
25
26 /****************************************************************************
27  Run a file if it is a magic script.
28 ****************************************************************************/
29
30 static NTSTATUS check_magic(struct files_struct *fsp)
31 {
32         int ret;
33         const char *magic_output = NULL;
34         SMB_STRUCT_STAT st;
35         int tmp_fd, outfd;
36         TALLOC_CTX *ctx = NULL;
37         const char *p;
38         struct connection_struct *conn = fsp->conn;
39
40         if (!*lp_magicscript(SNUM(conn))) {
41                 return NT_STATUS_OK;
42         }
43
44         DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
45
46         if (!(p = strrchr_m(fsp->fsp_name,'/'))) {
47                 p = fsp->fsp_name;
48         } else {
49                 p++;
50         }
51
52         if (!strequal(lp_magicscript(SNUM(conn)),p)) {
53                 return NT_STATUS_OK;
54         }
55
56         ctx = talloc_stackframe();
57
58         if (*lp_magicoutput(SNUM(conn))) {
59                 magic_output = lp_magicoutput(SNUM(conn));
60         } else {
61                 magic_output = talloc_asprintf(ctx,
62                                 "%s.out",
63                                 fsp->fsp_name);
64         }
65         if (!magic_output) {
66                 TALLOC_FREE(ctx);
67                 return NT_STATUS_NO_MEMORY;
68         }
69
70         /* Ensure we don't depend on user's PATH. */
71         p = talloc_asprintf(ctx, "./%s", fsp->fsp_name);
72         if (!p) {
73                 TALLOC_FREE(ctx);
74                 return NT_STATUS_NO_MEMORY;
75         }
76
77         if (chmod(fsp->fsp_name,0755) == -1) {
78                 TALLOC_FREE(ctx);
79                 return map_nt_error_from_unix(errno);
80         }
81         ret = smbrun(p,&tmp_fd);
82         DEBUG(3,("Invoking magic command %s gave %d\n",
83                 p,ret));
84
85         unlink(fsp->fsp_name);
86         if (ret != 0 || tmp_fd == -1) {
87                 if (tmp_fd != -1) {
88                         close(tmp_fd);
89                 }
90                 TALLOC_FREE(ctx);
91                 return NT_STATUS_UNSUCCESSFUL;
92         }
93         outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
94         if (outfd == -1) {
95                 int err = errno;
96                 close(tmp_fd);
97                 TALLOC_FREE(ctx);
98                 return map_nt_error_from_unix(err);
99         }
100
101         if (sys_fstat(tmp_fd,&st) == -1) {
102                 int err = errno;
103                 close(tmp_fd);
104                 close(outfd);
105                 TALLOC_FREE(ctx);
106                 return map_nt_error_from_unix(err);
107         }
108
109         if (transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_ex_size) == (SMB_OFF_T)-1) {
110                 int err = errno;
111                 close(tmp_fd);
112                 close(outfd);
113                 TALLOC_FREE(ctx);
114                 return map_nt_error_from_unix(err);
115         }
116         close(tmp_fd);
117         if (close(outfd) == -1) {
118                 TALLOC_FREE(ctx);
119                 return map_nt_error_from_unix(errno);
120         }
121         TALLOC_FREE(ctx);
122         return NT_STATUS_OK;
123 }
124
125 /****************************************************************************
126   Common code to close a file or a directory.
127 ****************************************************************************/
128
129 static NTSTATUS close_filestruct(files_struct *fsp)
130 {
131         NTSTATUS status = NT_STATUS_OK;
132
133         if (fsp->fh->fd != -1) {
134                 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
135                         status = map_nt_error_from_unix(errno);
136                 }
137                 delete_write_cache(fsp);
138         }
139
140         return status;
141 }
142
143 /****************************************************************************
144  If any deferred opens are waiting on this close, notify them.
145 ****************************************************************************/
146
147 static void notify_deferred_opens(struct share_mode_lock *lck)
148 {
149         int i;
150
151         if (!should_notify_deferred_opens()) {
152                 return;
153         }
154  
155         for (i=0; i<lck->num_share_modes; i++) {
156                 struct share_mode_entry *e = &lck->share_modes[i];
157  
158                 if (!is_deferred_open_entry(e)) {
159                         continue;
160                 }
161  
162                 if (procid_is_me(&e->pid)) {
163                         /*
164                          * We need to notify ourself to retry the open.  Do
165                          * this by finding the queued SMB record, moving it to
166                          * the head of the queue and changing the wait time to
167                          * zero.
168                          */
169                         schedule_deferred_open_smb_message(e->op_mid);
170                 } else {
171                         char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
172
173                         share_mode_entry_to_message(msg, e);
174
175                         messaging_send_buf(smbd_messaging_context(),
176                                            e->pid, MSG_SMB_OPEN_RETRY,
177                                            (uint8 *)msg,
178                                            MSG_SMB_SHARE_MODE_ENTRY_SIZE);
179                 }
180         }
181 }
182
183 /****************************************************************************
184  Delete all streams
185 ****************************************************************************/
186
187 NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
188 {
189         struct stream_struct *stream_info;
190         int i;
191         unsigned int num_streams;
192         TALLOC_CTX *frame = talloc_stackframe();
193         NTSTATUS status;
194
195         status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
196                                     &num_streams, &stream_info);
197
198         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
199                 DEBUG(10, ("no streams around\n"));
200                 TALLOC_FREE(frame);
201                 return NT_STATUS_OK;
202         }
203
204         if (!NT_STATUS_IS_OK(status)) {
205                 DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
206                            nt_errstr(status)));
207                 goto fail;
208         }
209
210         DEBUG(10, ("delete_all_streams found %d streams\n",
211                    num_streams));
212
213         if (num_streams == 0) {
214                 TALLOC_FREE(frame);
215                 return NT_STATUS_OK;
216         }
217
218         for (i=0; i<num_streams; i++) {
219                 int res;
220                 struct smb_filename *smb_fname_stream = NULL;
221
222                 if (strequal(stream_info[i].name, "::$DATA")) {
223                         continue;
224                 }
225
226                 status = create_synthetic_smb_fname(talloc_tos(), fname,
227                                                     stream_info[i].name, NULL,
228                                                     &smb_fname_stream);
229
230                 if (!NT_STATUS_IS_OK(status)) {
231                         DEBUG(0, ("talloc_aprintf failed\n"));
232                         goto fail;
233                 }
234
235                 res = SMB_VFS_UNLINK(conn, smb_fname_stream);
236
237                 if (res == -1) {
238                         status = map_nt_error_from_unix(errno);
239                         DEBUG(10, ("Could not delete stream %s: %s\n",
240                                    smb_fname_str_dbg(smb_fname_stream),
241                                    strerror(errno)));
242                         TALLOC_FREE(smb_fname_stream);
243                         break;
244                 }
245                 TALLOC_FREE(smb_fname_stream);
246         }
247
248  fail:
249         TALLOC_FREE(frame);
250         return status;
251 }
252
253 /****************************************************************************
254  Deal with removing a share mode on last close.
255 ****************************************************************************/
256
257 static NTSTATUS close_remove_share_mode(files_struct *fsp,
258                                         enum file_close_type close_type)
259 {
260         connection_struct *conn = fsp->conn;
261         bool delete_file = false;
262         bool changed_user = false;
263         struct share_mode_lock *lck = NULL;
264         struct smb_filename *smb_fname = NULL;
265         char *fname = NULL;
266         NTSTATUS status = NT_STATUS_OK;
267         int ret;
268         struct file_id id;
269
270         status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
271                                                   NULL, &smb_fname);
272         if (!NT_STATUS_IS_OK(status)) {
273                 goto done;
274         }
275
276         /*
277          * Lock the share entries, and determine if we should delete
278          * on close. If so delete whilst the lock is still in effect.
279          * This prevents race conditions with the file being created. JRA.
280          */
281
282         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
283                                   NULL);
284
285         if (lck == NULL) {
286                 DEBUG(0, ("close_remove_share_mode: Could not get share mode "
287                           "lock for file %s\n", smb_fname_str_dbg(smb_fname)));
288                 status = NT_STATUS_INVALID_PARAMETER;
289                 goto done;
290         }
291
292         if (fsp->write_time_forced) {
293                 set_close_write_time(fsp, lck->changed_write_time);
294         }
295
296         if (!del_share_mode(lck, fsp)) {
297                 DEBUG(0, ("close_remove_share_mode: Could not delete share "
298                           "entry for file %s\n",
299                           smb_fname_str_dbg(smb_fname)));
300         }
301
302         if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
303                 bool became_user = False;
304
305                 /* Initial delete on close was set and no one else
306                  * wrote a real delete on close. */
307
308                 if (current_user.vuid != fsp->vuid) {
309                         become_user(conn, fsp->vuid);
310                         became_user = True;
311                 }
312                 set_delete_on_close_lck(lck, True, &current_user.ut);
313                 if (became_user) {
314                         unbecome_user();
315                 }
316         }
317
318         delete_file = lck->delete_on_close;
319
320         if (delete_file) {
321                 int i;
322                 /* See if others still have the file open. If this is the
323                  * case, then don't delete. If all opens are POSIX delete now. */
324                 for (i=0; i<lck->num_share_modes; i++) {
325                         struct share_mode_entry *e = &lck->share_modes[i];
326                         if (is_valid_share_mode_entry(e)) {
327                                 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
328                                         continue;
329                                 }
330                                 delete_file = False;
331                                 break;
332                         }
333                 }
334         }
335
336         /* Notify any deferred opens waiting on this close. */
337         notify_deferred_opens(lck);
338         reply_to_oplock_break_requests(fsp);
339
340         /*
341          * NT can set delete_on_close of the last open
342          * reference to a file.
343          */
344
345         if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE)
346             || !delete_file
347             || (lck->delete_token == NULL)) {
348                 TALLOC_FREE(lck);
349                 return NT_STATUS_OK;
350         }
351
352         /*
353          * Ok, we have to delete the file
354          */
355
356         DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
357                  "- deleting file.\n", smb_fname_str_dbg(smb_fname)));
358
359         /*
360          * Don't try to update the write time when we delete the file
361          */
362         fsp->update_write_time_on_close = false;
363
364         if (!unix_token_equal(lck->delete_token, &current_user.ut)) {
365                 /* Become the user who requested the delete. */
366
367                 DEBUG(5,("close_remove_share_mode: file %s. "
368                         "Change user to uid %u\n",
369                         smb_fname_str_dbg(smb_fname),
370                         (unsigned int)lck->delete_token->uid));
371
372                 if (!push_sec_ctx()) {
373                         smb_panic("close_remove_share_mode: file %s. failed to push "
374                                   "sec_ctx.\n");
375                 }
376
377                 set_sec_ctx(lck->delete_token->uid,
378                             lck->delete_token->gid,
379                             lck->delete_token->ngroups,
380                             lck->delete_token->groups,
381                             NULL);
382
383                 changed_user = true;
384         }
385
386         /* We can only delete the file if the name we have is still valid and
387            hasn't been renamed. */
388
389         if (fsp->posix_open) {
390                 ret = SMB_VFS_LSTAT(conn, smb_fname);
391         } else {
392                 ret = SMB_VFS_STAT(conn, smb_fname);
393         }
394
395         if (ret != 0) {
396                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
397                          "was set and stat failed with error %s\n",
398                          smb_fname_str_dbg(smb_fname), strerror(errno)));
399                 /*
400                  * Don't save the errno here, we ignore this error
401                  */
402                 goto done;
403         }
404
405         id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
406
407         if (!file_id_equal(&fsp->file_id, &id)) {
408                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
409                          "was set and dev and/or inode does not match\n",
410                          smb_fname_str_dbg(smb_fname)));
411                 DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
412                          "stat file_id %s\n",
413                          smb_fname_str_dbg(smb_fname),
414                          file_id_string_tos(&fsp->file_id),
415                          file_id_string_tos(&id)));
416                 /*
417                  * Don't save the errno here, we ignore this error
418                  */
419                 goto done;
420         }
421
422         if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
423             && !is_ntfs_stream_smb_fname(smb_fname)) {
424
425                 status = delete_all_streams(conn, smb_fname->base_name);
426
427                 if (!NT_STATUS_IS_OK(status)) {
428                         DEBUG(5, ("delete_all_streams failed: %s\n",
429                                   nt_errstr(status)));
430                         goto done;
431                 }
432         }
433
434
435         if (SMB_VFS_UNLINK(conn, smb_fname) != 0) {
436                 /*
437                  * This call can potentially fail as another smbd may
438                  * have had the file open with delete on close set and
439                  * deleted it when its last reference to this file
440                  * went away. Hence we log this but not at debug level
441                  * zero.
442                  */
443
444                 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
445                          "was set and unlink failed with error %s\n",
446                          smb_fname_str_dbg(smb_fname), strerror(errno)));
447
448                 status = map_nt_error_from_unix(errno);
449         }
450
451         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
452         if (!NT_STATUS_IS_OK(status)) {
453                 goto done;
454         }
455
456         notify_fname(conn, NOTIFY_ACTION_REMOVED,
457                      FILE_NOTIFY_CHANGE_FILE_NAME,
458                      fname);
459
460         TALLOC_FREE(fname);
461
462         /* As we now have POSIX opens which can unlink
463          * with other open files we may have taken
464          * this code path with more than one share mode
465          * entry - ensure we only delete once by resetting
466          * the delete on close flag. JRA.
467          */
468
469         set_delete_on_close_lck(lck, False, NULL);
470
471  done:
472
473         if (changed_user) {
474                 /* unbecome user. */
475                 pop_sec_ctx();
476         }
477
478         TALLOC_FREE(lck);
479         TALLOC_FREE(smb_fname);
480         return status;
481 }
482
483 void set_close_write_time(struct files_struct *fsp, struct timespec ts)
484 {
485         DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
486
487         if (null_timespec(ts)) {
488                 return;
489         }
490         /*
491          * if the write time on close is explict set, then don't
492          * need to fix it up to the value in the locking db
493          */
494         fsp->write_time_forced = false;
495
496         fsp->update_write_time_on_close = true;
497         fsp->close_write_time = ts;
498 }
499
500 static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
501 {
502         SMB_STRUCT_STAT sbuf;
503         struct smb_file_time ft;
504         NTSTATUS status;
505         int ret = -1;
506
507         ZERO_STRUCT(sbuf);
508         ZERO_STRUCT(ft);
509
510         if (!fsp->update_write_time_on_close) {
511                 return NT_STATUS_OK;
512         }
513
514         if (null_timespec(fsp->close_write_time)) {
515                 fsp->close_write_time = timespec_current();
516         }
517
518         /* Ensure we have a valid stat struct for the source. */
519         if (fsp->fh->fd != -1) {
520                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
521         } else {
522                 if (fsp->posix_open) {
523                         ret = vfs_lstat_smb_fname(fsp->conn, fsp->fsp_name,
524                                                  &sbuf);
525                 } else {
526                         ret = vfs_stat_smb_fname(fsp->conn, fsp->fsp_name,
527                                                  &sbuf);
528                 }
529         }
530
531         if (ret == -1) {
532                 return map_nt_error_from_unix(errno);
533         }
534
535         if (!VALID_STAT(sbuf)) {
536                 /* if it doesn't seem to be a real file */
537                 return NT_STATUS_OK;
538         }
539
540         ft.mtime = fsp->close_write_time;
541         status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name,
542                                    &sbuf, &ft, true);
543         if (!NT_STATUS_IS_OK(status)) {
544                 return status;
545         }
546
547         return NT_STATUS_OK;
548 }
549
550 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
551 {
552         if (!NT_STATUS_IS_OK(s1)) {
553                 return s1;
554         }
555         return s2;
556 }
557
558 /****************************************************************************
559  Close a file.
560
561  close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
562  printing and magic scripts are only run on normal close.
563  delete on close is done on normal and shutdown close.
564 ****************************************************************************/
565
566 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
567                                   enum file_close_type close_type)
568 {
569         NTSTATUS status = NT_STATUS_OK;
570         NTSTATUS tmp;
571         connection_struct *conn = fsp->conn;
572
573         if (fsp->aio_write_behind) {
574                 /*
575                  * If we're finishing write behind on a close we can get a write
576                  * error here, we must remember this.
577                  */
578                 int ret = wait_for_aio_completion(fsp);
579                 if (ret) {
580                         status = ntstatus_keeperror(
581                                 status, map_nt_error_from_unix(ret));
582                 }
583         } else {
584                 cancel_aio_by_fsp(fsp);
585         }
586  
587         /*
588          * If we're flushing on a close we can get a write
589          * error here, we must remember this.
590          */
591
592         tmp = close_filestruct(fsp);
593         status = ntstatus_keeperror(status, tmp);
594
595         if (fsp->print_file) {
596                 print_fsp_end(fsp, close_type);
597                 file_free(req, fsp);
598                 return NT_STATUS_OK;
599         }
600
601         /* Remove the oplock before potentially deleting the file. */
602         if(fsp->oplock_type) {
603                 release_file_oplock(fsp);
604         }
605
606         /* If this is an old DOS or FCB open and we have multiple opens on
607            the same handle we only have one share mode. Ensure we only remove
608            the share mode on the last close. */
609
610         if (fsp->fh->ref_count == 1) {
611                 /* Should we return on error here... ? */
612                 tmp = close_remove_share_mode(fsp, close_type);
613                 status = ntstatus_keeperror(status, tmp);
614         }
615
616         locking_close_file(smbd_messaging_context(), fsp);
617
618         tmp = fd_close(fsp);
619         status = ntstatus_keeperror(status, tmp);
620
621         /* check for magic scripts */
622         if (close_type == NORMAL_CLOSE) {
623                 tmp = check_magic(fsp);
624                 status = ntstatus_keeperror(status, tmp);
625         }
626
627         /*
628          * Ensure pending modtime is set after close.
629          */
630
631         tmp = update_write_time_on_close(fsp);
632         if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
633                 /* Someone renamed the file or a parent directory containing
634                  * this file. We can't do anything about this, we don't have
635                  * an "update timestamp by fd" call in POSIX. Eat the error. */
636
637                 tmp = NT_STATUS_OK;
638         }
639
640         status = ntstatus_keeperror(status, tmp);
641
642         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
643                 conn->server_info->unix_name,fsp->fsp_name,
644                 conn->num_files_open - 1,
645                 nt_errstr(status) ));
646
647         file_free(req, fsp);
648         return status;
649 }
650
651 /****************************************************************************
652  Close a directory opened by an NT SMB call. 
653 ****************************************************************************/
654   
655 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
656                                 enum file_close_type close_type)
657 {
658         struct share_mode_lock *lck = NULL;
659         struct smb_filename *smb_dname = NULL;
660         bool delete_dir = False;
661         NTSTATUS status = NT_STATUS_OK;
662
663         status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
664                                                   NULL, &smb_dname);
665         if (!NT_STATUS_IS_OK(status)) {
666                 goto out;
667         }
668
669         /*
670          * NT can set delete_on_close of the last open
671          * reference to a directory also.
672          */
673
674         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
675                                   NULL);
676
677         if (lck == NULL) {
678                 DEBUG(0, ("close_directory: Could not get share mode lock for "
679                           "%s\n", smb_fname_str_dbg(smb_dname)));
680                 status = NT_STATUS_INVALID_PARAMETER;
681                 goto out;
682         }
683
684         if (!del_share_mode(lck, fsp)) {
685                 DEBUG(0, ("close_directory: Could not delete share entry for "
686                           "%s\n", smb_fname_str_dbg(smb_dname)));
687         }
688
689         if (fsp->initial_delete_on_close) {
690                 bool became_user = False;
691
692                 /* Initial delete on close was set - for
693                  * directories we don't care if anyone else
694                  * wrote a real delete on close. */
695
696                 if (current_user.vuid != fsp->vuid) {
697                         become_user(fsp->conn, fsp->vuid);
698                         became_user = True;
699                 }
700                 send_stat_cache_delete_message(fsp->fsp_name);
701                 set_delete_on_close_lck(lck, True, &current_user.ut);
702                 if (became_user) {
703                         unbecome_user();
704                 }
705         }
706
707         delete_dir = lck->delete_on_close;
708
709         if (delete_dir) {
710                 int i;
711                 /* See if others still have the dir open. If this is the
712                  * case, then don't delete. If all opens are POSIX delete now. */
713                 for (i=0; i<lck->num_share_modes; i++) {
714                         struct share_mode_entry *e = &lck->share_modes[i];
715                         if (is_valid_share_mode_entry(e)) {
716                                 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
717                                         continue;
718                                 }
719                                 delete_dir = False;
720                                 break;
721                         }
722                 }
723         }
724
725         if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
726                                 delete_dir &&
727                                 lck->delete_token) {
728         
729                 /* Become the user who requested the delete. */
730
731                 if (!push_sec_ctx()) {
732                         smb_panic("close_directory: failed to push sec_ctx.\n");
733                 }
734
735                 set_sec_ctx(lck->delete_token->uid,
736                                 lck->delete_token->gid,
737                                 lck->delete_token->ngroups,
738                                 lck->delete_token->groups,
739                                 NULL);
740
741                 TALLOC_FREE(lck);
742
743                 status = rmdir_internals(talloc_tos(), fsp->conn, smb_dname);
744
745                 DEBUG(5,("close_directory: %s. Delete on close was set - "
746                          "deleting directory returned %s.\n",
747                          smb_fname_str_dbg(smb_dname), nt_errstr(status)));
748
749                 /* unbecome user. */
750                 pop_sec_ctx();
751
752                 /*
753                  * Ensure we remove any change notify requests that would
754                  * now fail as the directory has been deleted.
755                  */
756
757                 if(NT_STATUS_IS_OK(status)) {
758                         remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
759                 }
760         } else {
761                 TALLOC_FREE(lck);
762                 remove_pending_change_notify_requests_by_fid(
763                         fsp, NT_STATUS_OK);
764         }
765
766         status = fd_close(fsp);
767
768         if (!NT_STATUS_IS_OK(status)) {
769                 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
770                           smb_fname_str_dbg(smb_dname), fsp->fh->fd, errno,
771                           strerror(errno)));
772         }
773
774         /*
775          * Do the code common to files and directories.
776          */
777         close_filestruct(fsp);
778         file_free(req, fsp);
779
780  out:
781         TALLOC_FREE(lck);
782         TALLOC_FREE(smb_dname);
783         return status;
784 }
785
786 /****************************************************************************
787  Close a files_struct.
788 ****************************************************************************/
789   
790 NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
791                     enum file_close_type close_type)
792 {
793         NTSTATUS status;
794         struct files_struct *base_fsp = fsp->base_fsp;
795
796         if(fsp->is_directory) {
797                 status = close_directory(req, fsp, close_type);
798         } else if (fsp->fake_file_handle != NULL) {
799                 status = close_fake_file(req, fsp);
800         } else {
801                 status = close_normal_file(req, fsp, close_type);
802         }
803
804         if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
805
806                 /*
807                  * fsp was a stream, the base fsp can't be a stream as well
808                  *
809                  * For SHUTDOWN_CLOSE this is not possible here, because
810                  * SHUTDOWN_CLOSE only happens from files.c which walks the
811                  * complete list of files. If we mess with more than one fsp
812                  * those loops will become confused.
813                  */
814
815                 SMB_ASSERT(base_fsp->base_fsp == NULL);
816                 close_file(req, base_fsp, close_type);
817         }
818
819         return status;
820 }
821
822 /****************************************************************************
823  Deal with an (authorized) message to close a file given the share mode
824  entry.
825 ****************************************************************************/
826
827 void msg_close_file(struct messaging_context *msg_ctx,
828                         void *private_data,
829                         uint32_t msg_type,
830                         struct server_id server_id,
831                         DATA_BLOB *data)
832 {
833         files_struct *fsp = NULL;
834         struct share_mode_entry e;
835
836         message_to_share_mode_entry(&e, (char *)data->data);
837
838         if(DEBUGLVL(10)) {
839                 char *sm_str = share_mode_str(NULL, 0, &e);
840                 if (!sm_str) {
841                         smb_panic("talloc failed");
842                 }
843                 DEBUG(10,("msg_close_file: got request to close share mode "
844                         "entry %s\n", sm_str));
845                 TALLOC_FREE(sm_str);
846         }
847
848         fsp = file_find_dif(e.id, e.share_file_id);
849         if (!fsp) {
850                 DEBUG(10,("msg_close_file: failed to find file.\n"));
851                 return;
852         }
853         close_file(NULL, fsp, NORMAL_CLOSE);
854 }