Use VFS operations for file I/O.
[samba.git] / source3 / smbd / close.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    file closing
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 extern int32 global_oplocks_open;
27
28
29 /****************************************************************************
30 run a file if it is a magic script
31 ****************************************************************************/
32 static void check_magic(files_struct *fsp,connection_struct *conn)
33 {
34   if (!*lp_magicscript(SNUM(conn)))
35     return;
36
37   DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
38
39   {
40     char *p;
41     if (!(p = strrchr(fsp->fsp_name,'/')))
42       p = fsp->fsp_name;
43     else
44       p++;
45
46     if (!strequal(lp_magicscript(SNUM(conn)),p))
47       return;
48   }
49
50   {
51     int ret;
52     pstring magic_output;
53     pstring fname;
54     pstrcpy(fname,fsp->fsp_name);
55
56     if (*lp_magicoutput(SNUM(conn)))
57       pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
58     else
59       slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
60
61     chmod(fname,0755);
62     ret = smbrun(fname,magic_output,False);
63     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
64     unlink(fname);
65   }
66 }
67
68 /****************************************************************************
69   Common code to close a file or a directory.
70 ****************************************************************************/
71 static void close_filestruct(files_struct *fsp)
72 {   
73         connection_struct *conn = fsp->conn;
74     
75         fsp->open = False;
76         fsp->is_directory = False; 
77     
78         conn->num_files_open--;
79         if(fsp->wbmpx_ptr) {  
80                 free((char *)fsp->wbmpx_ptr);
81                 fsp->wbmpx_ptr = NULL; 
82         }  
83      
84 #if WITH_MMAP
85         if(fsp->mmap_ptr) {
86                 munmap(fsp->mmap_ptr,fsp->mmap_size);
87                 fsp->mmap_ptr = NULL;
88         }  
89 #endif 
90 }    
91
92 /****************************************************************************
93  Close a file - possibly invalidating the read prediction.
94
95  If normal_close is 1 then this came from a normal SMBclose (or equivalent)
96  operation otherwise it came as the result of some other operation such as
97  the closing of the connection. In the latter case printing and
98  magic scripts are not run.
99 ****************************************************************************/
100 void close_file(files_struct *fsp, BOOL normal_close)
101 {
102         SMB_DEV_T dev = fsp->fd_ptr->dev;
103         SMB_INO_T inode = fsp->fd_ptr->inode;
104         int token;
105     BOOL last_reference = False;
106     BOOL delete_on_close = fsp->fd_ptr->delete_on_close;
107         connection_struct *conn = fsp->conn;
108
109         remove_pending_lock_requests_by_fid(fsp);
110
111         close_filestruct(fsp);
112
113 #if USE_READ_PREDICTION
114         invalidate_read_prediction(fsp->fd_ptr->fd);
115 #endif
116
117         if (lp_share_modes(SNUM(conn))) {
118                 lock_share_entry(conn, dev, inode, &token);
119                 del_share_mode(token, fsp);
120         }
121
122         if(fd_attempt_close(fsp) == 0)
123                 last_reference = True;
124
125     fsp->fd_ptr = NULL;
126
127         if (lp_share_modes(SNUM(conn)))
128                 unlock_share_entry(conn, dev, inode, token);
129
130         /* NT uses smbclose to start a print - weird */
131         if (normal_close && fsp->print_file)
132                 print_file(conn, fsp);
133
134         /* check for magic scripts */
135         if (normal_close) {
136                 check_magic(fsp,conn);
137         }
138
139         /*
140          * NT can set delete_on_close of the last open
141          * reference to a file.
142          */
143
144     if (normal_close && last_reference && delete_on_close) {
145         DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
146             fsp->fsp_name));
147                 if(fsp->conn->vfs_ops.unlink(dos_to_unix(fsp->fsp_name, False)) != 0) {
148           /*
149            * This call can potentially fail as another smbd may have
150            * had the file open with delete on close set and deleted
151            * it when its last reference to this file went away. Hence
152            * we log this but not at debug level zero.
153            */
154
155           DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
156 with error %s\n", fsp->fsp_name, strerror(errno) ));
157         }
158     }
159
160         if(fsp->granted_oplock == True)
161                 global_oplocks_open--;
162
163         fsp->sent_oplock_break = False;
164
165         DEBUG(2,("%s closed file %s (numopen=%d)\n",
166                  conn->user,fsp->fsp_name,
167                  conn->num_files_open));
168
169         if (fsp->fsp_name) {
170                 string_free(&fsp->fsp_name);
171         }
172
173         file_free(fsp);
174 }
175
176 /****************************************************************************
177  Close a directory opened by an NT SMB call. 
178 ****************************************************************************/
179   
180 void close_directory(files_struct *fsp)
181 {
182         remove_pending_change_notify_requests_by_fid(fsp);
183
184         /*
185          * Do the code common to files and directories.
186          */
187         close_filestruct(fsp);
188         
189         if (fsp->fsp_name)
190                 string_free(&fsp->fsp_name);
191         
192         file_free(fsp);
193 }
194