s3: Plumb smb_filename through SMB_VFS_NTIMES
[sfrench/samba-autobuild/.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         struct smb_filename *smb_fname = NULL;
503         struct smb_file_time ft;
504         NTSTATUS status;
505         int ret = -1;
506
507         ZERO_STRUCT(ft);
508
509         if (!fsp->update_write_time_on_close) {
510                 return NT_STATUS_OK;
511         }
512
513         if (null_timespec(fsp->close_write_time)) {
514                 fsp->close_write_time = timespec_current();
515         }
516
517         /* XXX: Remove when fsp->fsp_name is converted to smb_filename. */
518         status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
519                                                   NULL, &smb_fname);
520         if (!NT_STATUS_IS_OK(status)) {
521                 goto out;
522         }
523
524         /* Ensure we have a valid stat struct for the source. */
525         if (fsp->fh->fd != -1) {
526                 ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
527         } else {
528                 if (fsp->posix_open) {
529                         ret = SMB_VFS_LSTAT(fsp->conn, smb_fname);
530                 } else {
531                         ret = SMB_VFS_STAT(fsp->conn, smb_fname);
532                 }
533         }
534
535         if (ret == -1) {
536                 status = map_nt_error_from_unix(errno);
537                 goto out;
538         }
539
540         if (!VALID_STAT(smb_fname->st)) {
541                 /* if it doesn't seem to be a real file */
542                 status = NT_STATUS_OK;
543                 goto out;
544         }
545
546         ft.mtime = fsp->close_write_time;
547         status = smb_set_file_time(fsp->conn, fsp, smb_fname, &ft, true);
548         if (!NT_STATUS_IS_OK(status)) {
549                 goto out;
550         }
551
552  out:
553         TALLOC_FREE(smb_fname);
554         return status;
555 }
556
557 static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
558 {
559         if (!NT_STATUS_IS_OK(s1)) {
560                 return s1;
561         }
562         return s2;
563 }
564
565 /****************************************************************************
566  Close a file.
567
568  close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
569  printing and magic scripts are only run on normal close.
570  delete on close is done on normal and shutdown close.
571 ****************************************************************************/
572
573 static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
574                                   enum file_close_type close_type)
575 {
576         NTSTATUS status = NT_STATUS_OK;
577         NTSTATUS tmp;
578         connection_struct *conn = fsp->conn;
579
580         if (fsp->aio_write_behind) {
581                 /*
582                  * If we're finishing write behind on a close we can get a write
583                  * error here, we must remember this.
584                  */
585                 int ret = wait_for_aio_completion(fsp);
586                 if (ret) {
587                         status = ntstatus_keeperror(
588                                 status, map_nt_error_from_unix(ret));
589                 }
590         } else {
591                 cancel_aio_by_fsp(fsp);
592         }
593  
594         /*
595          * If we're flushing on a close we can get a write
596          * error here, we must remember this.
597          */
598
599         tmp = close_filestruct(fsp);
600         status = ntstatus_keeperror(status, tmp);
601
602         if (fsp->print_file) {
603                 print_fsp_end(fsp, close_type);
604                 file_free(req, fsp);
605                 return NT_STATUS_OK;
606         }
607
608         /* Remove the oplock before potentially deleting the file. */
609         if(fsp->oplock_type) {
610                 release_file_oplock(fsp);
611         }
612
613         /* If this is an old DOS or FCB open and we have multiple opens on
614            the same handle we only have one share mode. Ensure we only remove
615            the share mode on the last close. */
616
617         if (fsp->fh->ref_count == 1) {
618                 /* Should we return on error here... ? */
619                 tmp = close_remove_share_mode(fsp, close_type);
620                 status = ntstatus_keeperror(status, tmp);
621         }
622
623         locking_close_file(smbd_messaging_context(), fsp);
624
625         tmp = fd_close(fsp);
626         status = ntstatus_keeperror(status, tmp);
627
628         /* check for magic scripts */
629         if (close_type == NORMAL_CLOSE) {
630                 tmp = check_magic(fsp);
631                 status = ntstatus_keeperror(status, tmp);
632         }
633
634         /*
635          * Ensure pending modtime is set after close.
636          */
637
638         tmp = update_write_time_on_close(fsp);
639         if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
640                 /* Someone renamed the file or a parent directory containing
641                  * this file. We can't do anything about this, we don't have
642                  * an "update timestamp by fd" call in POSIX. Eat the error. */
643
644                 tmp = NT_STATUS_OK;
645         }
646
647         status = ntstatus_keeperror(status, tmp);
648
649         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
650                 conn->server_info->unix_name,fsp->fsp_name,
651                 conn->num_files_open - 1,
652                 nt_errstr(status) ));
653
654         file_free(req, fsp);
655         return status;
656 }
657
658 /****************************************************************************
659  Close a directory opened by an NT SMB call. 
660 ****************************************************************************/
661   
662 static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
663                                 enum file_close_type close_type)
664 {
665         struct share_mode_lock *lck = NULL;
666         struct smb_filename *smb_dname = NULL;
667         bool delete_dir = False;
668         NTSTATUS status = NT_STATUS_OK;
669
670         status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
671                                                   NULL, &smb_dname);
672         if (!NT_STATUS_IS_OK(status)) {
673                 goto out;
674         }
675
676         /*
677          * NT can set delete_on_close of the last open
678          * reference to a directory also.
679          */
680
681         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
682                                   NULL);
683
684         if (lck == NULL) {
685                 DEBUG(0, ("close_directory: Could not get share mode lock for "
686                           "%s\n", smb_fname_str_dbg(smb_dname)));
687                 status = NT_STATUS_INVALID_PARAMETER;
688                 goto out;
689         }
690
691         if (!del_share_mode(lck, fsp)) {
692                 DEBUG(0, ("close_directory: Could not delete share entry for "
693                           "%s\n", smb_fname_str_dbg(smb_dname)));
694         }
695
696         if (fsp->initial_delete_on_close) {
697                 bool became_user = False;
698
699                 /* Initial delete on close was set - for
700                  * directories we don't care if anyone else
701                  * wrote a real delete on close. */
702
703                 if (current_user.vuid != fsp->vuid) {
704                         become_user(fsp->conn, fsp->vuid);
705                         became_user = True;
706                 }
707                 send_stat_cache_delete_message(fsp->fsp_name);
708                 set_delete_on_close_lck(lck, True, &current_user.ut);
709                 if (became_user) {
710                         unbecome_user();
711                 }
712         }
713
714         delete_dir = lck->delete_on_close;
715
716         if (delete_dir) {
717                 int i;
718                 /* See if others still have the dir open. If this is the
719                  * case, then don't delete. If all opens are POSIX delete now. */
720                 for (i=0; i<lck->num_share_modes; i++) {
721                         struct share_mode_entry *e = &lck->share_modes[i];
722                         if (is_valid_share_mode_entry(e)) {
723                                 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
724                                         continue;
725                                 }
726                                 delete_dir = False;
727                                 break;
728                         }
729                 }
730         }
731
732         if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
733                                 delete_dir &&
734                                 lck->delete_token) {
735         
736                 /* Become the user who requested the delete. */
737
738                 if (!push_sec_ctx()) {
739                         smb_panic("close_directory: failed to push sec_ctx.\n");
740                 }
741
742                 set_sec_ctx(lck->delete_token->uid,
743                                 lck->delete_token->gid,
744                                 lck->delete_token->ngroups,
745                                 lck->delete_token->groups,
746                                 NULL);
747
748                 TALLOC_FREE(lck);
749
750                 status = rmdir_internals(talloc_tos(), fsp->conn, smb_dname);
751
752                 DEBUG(5,("close_directory: %s. Delete on close was set - "
753                          "deleting directory returned %s.\n",
754                          smb_fname_str_dbg(smb_dname), nt_errstr(status)));
755
756                 /* unbecome user. */
757                 pop_sec_ctx();
758
759                 /*
760                  * Ensure we remove any change notify requests that would
761                  * now fail as the directory has been deleted.
762                  */
763
764                 if(NT_STATUS_IS_OK(status)) {
765                         remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
766                 }
767         } else {
768                 TALLOC_FREE(lck);
769                 remove_pending_change_notify_requests_by_fid(
770                         fsp, NT_STATUS_OK);
771         }
772
773         status = fd_close(fsp);
774
775         if (!NT_STATUS_IS_OK(status)) {
776                 DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
777                           smb_fname_str_dbg(smb_dname), fsp->fh->fd, errno,
778                           strerror(errno)));
779         }
780
781         /*
782          * Do the code common to files and directories.
783          */
784         close_filestruct(fsp);
785         file_free(req, fsp);
786
787  out:
788         TALLOC_FREE(lck);
789         TALLOC_FREE(smb_dname);
790         return status;
791 }
792
793 /****************************************************************************
794  Close a files_struct.
795 ****************************************************************************/
796   
797 NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
798                     enum file_close_type close_type)
799 {
800         NTSTATUS status;
801         struct files_struct *base_fsp = fsp->base_fsp;
802
803         if(fsp->is_directory) {
804                 status = close_directory(req, fsp, close_type);
805         } else if (fsp->fake_file_handle != NULL) {
806                 status = close_fake_file(req, fsp);
807         } else {
808                 status = close_normal_file(req, fsp, close_type);
809         }
810
811         if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
812
813                 /*
814                  * fsp was a stream, the base fsp can't be a stream as well
815                  *
816                  * For SHUTDOWN_CLOSE this is not possible here, because
817                  * SHUTDOWN_CLOSE only happens from files.c which walks the
818                  * complete list of files. If we mess with more than one fsp
819                  * those loops will become confused.
820                  */
821
822                 SMB_ASSERT(base_fsp->base_fsp == NULL);
823                 close_file(req, base_fsp, close_type);
824         }
825
826         return status;
827 }
828
829 /****************************************************************************
830  Deal with an (authorized) message to close a file given the share mode
831  entry.
832 ****************************************************************************/
833
834 void msg_close_file(struct messaging_context *msg_ctx,
835                         void *private_data,
836                         uint32_t msg_type,
837                         struct server_id server_id,
838                         DATA_BLOB *data)
839 {
840         files_struct *fsp = NULL;
841         struct share_mode_entry e;
842
843         message_to_share_mode_entry(&e, (char *)data->data);
844
845         if(DEBUGLVL(10)) {
846                 char *sm_str = share_mode_str(NULL, 0, &e);
847                 if (!sm_str) {
848                         smb_panic("talloc failed");
849                 }
850                 DEBUG(10,("msg_close_file: got request to close share mode "
851                         "entry %s\n", sm_str));
852                 TALLOC_FREE(sm_str);
853         }
854
855         fsp = file_find_dif(e.id, e.share_file_id);
856         if (!fsp) {
857                 DEBUG(10,("msg_close_file: failed to find file.\n"));
858                 return;
859         }
860         close_file(NULL, fsp, NORMAL_CLOSE);
861 }