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