Removed version number from file header.
[ira/wip.git] / source3 / 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 static void check_magic(files_struct *fsp,connection_struct *conn)
27 {
28   if (!*lp_magicscript(SNUM(conn)))
29     return;
30
31   DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
32
33   {
34     char *p;
35     if (!(p = strrchr_m(fsp->fsp_name,'/')))
36       p = fsp->fsp_name;
37     else
38       p++;
39
40     if (!strequal(lp_magicscript(SNUM(conn)),p))
41       return;
42   }
43
44   {
45     int ret;
46     pstring magic_output;
47     pstring fname;
48         SMB_STRUCT_STAT st;
49         int tmp_fd, outfd;
50
51     pstrcpy(fname,fsp->fsp_name);
52     if (*lp_magicoutput(SNUM(conn)))
53       pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
54     else
55       slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
56
57     chmod(fname,0755);
58     ret = smbrun(fname,&tmp_fd);
59     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
60     unlink(fname);
61         if (ret != 0 || tmp_fd == -1) {
62                 if (tmp_fd != -1)
63                         close(tmp_fd);
64                 return;
65         }
66         outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
67         if (outfd == -1) {
68                 close(tmp_fd);
69                 return;
70         }
71
72         if (sys_fstat(tmp_fd,&st) == -1) {
73                 close(tmp_fd);
74                 close(outfd);
75                 return;
76         }
77
78         transfer_file(tmp_fd,outfd,st.st_size);
79         close(tmp_fd);
80         close(outfd);
81   }
82 }
83
84 /****************************************************************************
85   Common code to close a file or a directory.
86 ****************************************************************************/
87
88 static int close_filestruct(files_struct *fsp)
89 {   
90         connection_struct *conn = fsp->conn;
91         int ret = 0;
92     
93         if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
94                 ret = -1;
95
96         delete_write_cache(fsp);
97
98         fsp->is_directory = False; 
99         fsp->stat_open = False; 
100     
101         conn->num_files_open--;
102
103         return ret;
104 }    
105
106 /****************************************************************************
107  Close a file.
108
109  If normal_close is 1 then this came from a normal SMBclose (or equivalent)
110  operation otherwise it came as the result of some other operation such as
111  the closing of the connection. In the latter case printing and
112  magic scripts are not run.
113 ****************************************************************************/
114
115 static int close_normal_file(files_struct *fsp, BOOL normal_close)
116 {
117         share_mode_entry *share_entry = NULL;
118         size_t share_entry_count = 0;
119         BOOL delete_on_close = False;
120         connection_struct *conn = fsp->conn;
121         int err = 0;
122         int err1 = 0;
123
124         remove_pending_lock_requests_by_fid(fsp);
125
126         /*
127          * If we're flushing on a close we can get a write
128          * error here, we must remember this.
129          */
130
131         if (close_filestruct(fsp) == -1)
132                 err1 = -1;
133
134         if (fsp->print_file) {
135                 print_fsp_end(fsp, normal_close);
136                 file_free(fsp);
137                 return 0;
138         }
139
140         /*
141          * Lock the share entries, and determine if we should delete
142          * on close. If so delete whilst the lock is still in effect.
143          * This prevents race conditions with the file being created. JRA.
144          */
145
146         lock_share_entry_fsp(fsp);
147         share_entry_count = del_share_mode(fsp, &share_entry);
148
149         DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n",
150                 share_entry_count, fsp->fsp_name ));
151
152         /*
153          * We delete on close if it's the last open, and the
154          * delete on close flag was set in the entry we just deleted.
155          */
156
157         if ((share_entry_count == 0) && share_entry && 
158                         GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) )
159                 delete_on_close = True;
160
161         SAFE_FREE(share_entry);
162
163         /*
164          * NT can set delete_on_close of the last open
165          * reference to a file.
166          */
167
168         if (normal_close && delete_on_close) {
169                 DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
170                         fsp->fsp_name));
171                 if(fsp->conn->vfs_ops.unlink(conn,fsp->fsp_name) != 0) {
172                         /*
173                          * This call can potentially fail as another smbd may have
174                          * had the file open with delete on close set and deleted
175                          * it when its last reference to this file went away. Hence
176                          * we log this but not at debug level zero.
177                          */
178
179                 DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
180 with error %s\n", fsp->fsp_name, strerror(errno) ));
181                 }
182         }
183
184         unlock_share_entry_fsp(fsp);
185
186         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
187                 release_file_oplock(fsp);
188
189         locking_close_file(fsp);
190
191         err = fd_close(conn, fsp);
192
193         /* check for magic scripts */
194         if (normal_close) {
195                 check_magic(fsp,conn);
196         }
197
198         /*
199          * Ensure pending modtime is set after close.
200          */
201
202         if(fsp->pending_modtime) {
203                 int saved_errno = errno;
204                 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
205                 errno = saved_errno;
206         }
207
208         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
209                  conn->user,fsp->fsp_name,
210                  conn->num_files_open, err ? strerror(err) : ""));
211
212         if (fsp->fsp_name)
213                 string_free(&fsp->fsp_name);
214
215         file_free(fsp);
216
217         if (err == -1 || err1 == -1)
218                 return -1;
219         else
220                 return 0;
221 }
222
223 /****************************************************************************
224  Close a directory opened by an NT SMB call. 
225 ****************************************************************************/
226   
227 static int close_directory(files_struct *fsp, BOOL normal_close)
228 {
229         remove_pending_change_notify_requests_by_fid(fsp);
230
231         /*
232          * NT can set delete_on_close of the last open
233          * reference to a directory also.
234          */
235
236         if (normal_close && fsp->directory_delete_on_close) {
237                 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
238                 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
239                         fsp->fsp_name, ok ? "succeeded" : "failed" ));
240
241                 /*
242                  * Ensure we remove any change notify requests that would
243                  * now fail as the directory has been deleted.
244                  */
245
246                 if(ok)
247                         remove_pending_change_notify_requests_by_filename(fsp);
248         }
249
250         /*
251          * Do the code common to files and directories.
252          */
253         close_filestruct(fsp);
254         
255         if (fsp->fsp_name)
256                 string_free(&fsp->fsp_name);
257         
258         file_free(fsp);
259
260         return 0;
261 }
262
263 /****************************************************************************
264  Close a file opened with null permissions in order to read permissions.
265 ****************************************************************************/
266
267 static int close_statfile(files_struct *fsp, BOOL normal_close)
268 {
269         close_filestruct(fsp);
270         
271         if (fsp->fsp_name)
272                 string_free(&fsp->fsp_name);
273         
274         file_free(fsp);
275
276         return 0;
277 }
278
279 /****************************************************************************
280  Close a directory opened by an NT SMB call. 
281 ****************************************************************************/
282   
283 int close_file(files_struct *fsp, BOOL normal_close)
284 {
285         if(fsp->is_directory)
286                 return close_directory(fsp, normal_close);
287         else if(fsp->stat_open)
288                 return close_statfile(fsp, normal_close);
289         return close_normal_file(fsp, normal_close);
290 }