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