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