c2db901ea70fee0970fe815ac01693cb8f7a26b0
[tprouty/samba.git] / source / smbd / close.c
1 /* 
2    Unix SMB/CIFS implementation.
3    file closing
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /****************************************************************************
24  Run a file if it is a magic script.
25 ****************************************************************************/
26
27 static void check_magic(files_struct *fsp,connection_struct *conn)
28 {
29         if (!*lp_magicscript(SNUM(conn)))
30                 return;
31
32         DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
33
34         {
35                 char *p;
36                 if (!(p = strrchr_m(fsp->fsp_name,'/')))
37                         p = fsp->fsp_name;
38                 else
39                         p++;
40
41                 if (!strequal(lp_magicscript(SNUM(conn)),p))
42                         return;
43         }
44
45         {
46                 int ret;
47                 pstring magic_output;
48                 pstring fname;
49                 SMB_STRUCT_STAT st;
50                 int tmp_fd, outfd;
51
52                 pstrcpy(fname,fsp->fsp_name);
53                 if (*lp_magicoutput(SNUM(conn)))
54                         pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
55                 else
56                         slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
57
58                 chmod(fname,0755);
59                 ret = smbrun(fname,&tmp_fd);
60                 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
61                 unlink(fname);
62                 if (ret != 0 || tmp_fd == -1) {
63                         if (tmp_fd != -1)
64                                 close(tmp_fd);
65                         return;
66                 }
67                 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
68                 if (outfd == -1) {
69                         close(tmp_fd);
70                         return;
71                 }
72
73                 if (sys_fstat(tmp_fd,&st) == -1) {
74                         close(tmp_fd);
75                         close(outfd);
76                         return;
77                 }
78
79                 transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
80                 close(tmp_fd);
81                 close(outfd);
82         }
83 }
84
85 /****************************************************************************
86   Common code to close a file or a directory.
87 ****************************************************************************/
88
89 static int close_filestruct(files_struct *fsp)
90 {   
91         connection_struct *conn = fsp->conn;
92         int ret = 0;
93     
94         if (fsp->fd != -1) {
95                 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
96                         ret = -1;
97
98                 delete_write_cache(fsp);
99         }
100
101         conn->num_files_open--;
102         SAFE_FREE(fsp->wbmpx_ptr);
103
104         return ret;
105 }    
106
107 /****************************************************************************
108  Close a file.
109
110  If normal_close is 1 then this came from a normal SMBclose (or equivalent)
111  operation otherwise it came as the result of some other operation such as
112  the closing of the connection. In the latter case printing and
113  magic scripts are not run.
114 ****************************************************************************/
115
116 static int close_normal_file(files_struct *fsp, BOOL normal_close)
117 {
118         share_mode_entry *share_entry = NULL;
119         size_t share_entry_count = 0;
120         BOOL delete_on_close = False;
121         connection_struct *conn = fsp->conn;
122         int err = 0;
123         int err1 = 0;
124
125         remove_pending_lock_requests_by_fid(fsp);
126
127         /*
128          * If we're flushing on a close we can get a write
129          * error here, we must remember this.
130          */
131
132         if (close_filestruct(fsp) == -1)
133                 err1 = -1;
134
135         if (fsp->print_file) {
136                 print_fsp_end(fsp, normal_close);
137                 file_free(fsp);
138                 return 0;
139         }
140
141         /*
142          * Lock the share entries, and determine if we should delete
143          * on close. If so delete whilst the lock is still in effect.
144          * This prevents race conditions with the file being created. JRA.
145          */
146
147         lock_share_entry_fsp(fsp);
148
149         if (fsp->delete_on_close) {
150
151                 /*
152                  * Modify the share mode entry for all files open
153                  * on this device and inode to tell other smbds we have
154                  * changed the delete on close flag. The last closer will delete the file
155                  * if flag is set.
156                  */
157
158                 NTSTATUS status =set_delete_on_close_over_all(fsp, fsp->delete_on_close);
159                 if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
160                         DEBUG(0,("close_normal_file: failed to change delete on close flag for file %s\n",
161                                 fsp->fsp_name ));
162         }
163
164         share_entry_count = del_share_mode(fsp, &share_entry);
165
166         DEBUG(10,("close_normal_file: share_entry_count = %l for file %s\n",
167                 share_entry_count, fsp->fsp_name ));
168
169         /*
170          * We delete on close if it's the last open, and the
171          * delete on close flag was set in the entry we just deleted.
172          */
173
174         if ((share_entry_count == 0) && share_entry && 
175                         GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) )
176                 delete_on_close = True;
177
178         SAFE_FREE(share_entry);
179
180         /*
181          * NT can set delete_on_close of the last open
182          * reference to a file.
183          */
184
185         if (normal_close && delete_on_close) {
186                 DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
187                         fsp->fsp_name));
188                 if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
189                         /*
190                          * This call can potentially fail as another smbd may have
191                          * had the file open with delete on close set and deleted
192                          * it when its last reference to this file went away. Hence
193                          * we log this but not at debug level zero.
194                          */
195
196                 DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
197 with error %s\n", fsp->fsp_name, strerror(errno) ));
198                 }
199                 process_pending_change_notify_queue((time_t)0);
200         }
201
202         unlock_share_entry_fsp(fsp);
203
204         if(fsp->oplock_type)
205                 release_file_oplock(fsp);
206
207         locking_close_file(fsp);
208
209         err = fd_close(conn, fsp);
210
211         /* check for magic scripts */
212         if (normal_close) {
213                 check_magic(fsp,conn);
214         }
215
216         /*
217          * Ensure pending modtime is set after close.
218          */
219
220         if(fsp->pending_modtime) {
221                 int saved_errno = errno;
222                 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
223                 errno = saved_errno;
224         }
225
226         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
227                  conn->user,fsp->fsp_name,
228                  conn->num_files_open, err ? strerror(err) : ""));
229
230         if (fsp->fsp_name)
231                 string_free(&fsp->fsp_name);
232
233         file_free(fsp);
234
235         if (err == -1 || err1 == -1)
236                 return -1;
237         else
238                 return 0;
239 }
240
241 /****************************************************************************
242  Close a directory opened by an NT SMB call. 
243 ****************************************************************************/
244   
245 static int close_directory(files_struct *fsp, BOOL normal_close)
246 {
247         remove_pending_change_notify_requests_by_fid(fsp);
248
249         /*
250          * NT can set delete_on_close of the last open
251          * reference to a directory also.
252          */
253
254         if (normal_close && fsp->directory_delete_on_close) {
255                 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
256                 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
257                         fsp->fsp_name, ok ? "succeeded" : "failed" ));
258
259                 /*
260                  * Ensure we remove any change notify requests that would
261                  * now fail as the directory has been deleted.
262                  */
263
264                 if(ok)
265                         remove_pending_change_notify_requests_by_filename(fsp);
266                 process_pending_change_notify_queue((time_t)0);
267         }
268
269         /*
270          * Do the code common to files and directories.
271          */
272         close_filestruct(fsp);
273         
274         if (fsp->fsp_name)
275                 string_free(&fsp->fsp_name);
276         
277         file_free(fsp);
278         return 0;
279 }
280
281 /****************************************************************************
282  Close a 'stat file' opened internally.
283 ****************************************************************************/
284   
285 static int close_stat(files_struct *fsp)
286 {
287         /*
288          * Do the code common to files and directories.
289          */
290         close_filestruct(fsp);
291         
292         if (fsp->fsp_name)
293                 string_free(&fsp->fsp_name);
294         
295         file_free(fsp);
296         return 0;
297 }
298
299 /****************************************************************************
300  Close a files_struct.
301 ****************************************************************************/
302   
303 int close_file(files_struct *fsp, BOOL normal_close)
304 {
305         if(fsp->is_directory)
306                 return close_directory(fsp, normal_close);
307         else if (fsp->is_stat)
308                 return close_stat(fsp);
309         else
310                 return close_normal_file(fsp, normal_close);
311 }