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