Fix VFS layer:
[Samba/gebeck_regimport.git] / source / smbd / close.c
bloba5d74cedb1e3e339de2fc97d62286eaad4ace568
1 /*
2 Unix SMB/CIFS implementation.
3 file closing
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
21 #include "includes.h"
23 /****************************************************************************
24 Run a file if it is a magic script.
25 ****************************************************************************/
27 static void check_magic(files_struct *fsp,connection_struct *conn)
29 if (!*lp_magicscript(SNUM(conn)))
30 return;
32 DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
35 char *p;
36 if (!(p = strrchr_m(fsp->fsp_name,'/')))
37 p = fsp->fsp_name;
38 else
39 p++;
41 if (!strequal(lp_magicscript(SNUM(conn)),p))
42 return;
46 int ret;
47 pstring magic_output;
48 pstring fname;
49 SMB_STRUCT_STAT st;
50 int tmp_fd, outfd;
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);
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;
67 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
68 if (outfd == -1) {
69 close(tmp_fd);
70 return;
73 if (sys_fstat(tmp_fd,&st) == -1) {
74 close(tmp_fd);
75 close(outfd);
76 return;
79 transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
80 close(tmp_fd);
81 close(outfd);
85 /****************************************************************************
86 Common code to close a file or a directory.
87 ****************************************************************************/
89 static int close_filestruct(files_struct *fsp)
91 connection_struct *conn = fsp->conn;
92 int ret = 0;
94 if (fsp->fd != -1) {
95 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
96 ret = -1;
98 delete_write_cache(fsp);
101 conn->num_files_open--;
102 SAFE_FREE(fsp->wbmpx_ptr);
104 return ret;
107 /****************************************************************************
108 Close a file.
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 ****************************************************************************/
116 static int close_normal_file(files_struct *fsp, BOOL normal_close)
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;
125 remove_pending_lock_requests_by_fid(fsp);
128 * If we're flushing on a close we can get a write
129 * error here, we must remember this.
132 if (close_filestruct(fsp) == -1)
133 err1 = -1;
135 if (fsp->print_file) {
136 print_fsp_end(fsp, normal_close);
137 file_free(fsp);
138 return 0;
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.
147 lock_share_entry_fsp(fsp);
149 if (fsp->delete_on_close) {
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.
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 ));
164 share_entry_count = del_share_mode(fsp, &share_entry);
166 DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n",
167 share_entry_count, fsp->fsp_name ));
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.
174 if ((share_entry_count == 0) && share_entry &&
175 GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) )
176 delete_on_close = True;
178 SAFE_FREE(share_entry);
181 * NT can set delete_on_close of the last open
182 * reference to a file.
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(VFS_UNLINK(conn,fsp->fsp_name) != 0) {
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.
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) ));
199 process_pending_change_notify_queue((time_t)0);
202 unlock_share_entry_fsp(fsp);
204 if(fsp->oplock_type)
205 release_file_oplock(fsp);
207 locking_close_file(fsp);
209 err = fd_close(conn, fsp);
211 /* check for magic scripts */
212 if (normal_close) {
213 check_magic(fsp,conn);
217 * Ensure pending modtime is set after close.
220 if(fsp->pending_modtime) {
221 int saved_errno = errno;
222 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
223 errno = saved_errno;
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) : ""));
230 if (fsp->fsp_name)
231 string_free(&fsp->fsp_name);
233 file_free(fsp);
235 if (err == -1 || err1 == -1)
236 return -1;
237 else
238 return 0;
241 /****************************************************************************
242 Close a directory opened by an NT SMB call.
243 ****************************************************************************/
245 static int close_directory(files_struct *fsp, BOOL normal_close)
247 remove_pending_change_notify_requests_by_fid(fsp);
250 * NT can set delete_on_close of the last open
251 * reference to a directory also.
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" ));
260 * Ensure we remove any change notify requests that would
261 * now fail as the directory has been deleted.
264 if(ok)
265 remove_pending_change_notify_requests_by_filename(fsp);
266 process_pending_change_notify_queue((time_t)0);
270 * Do the code common to files and directories.
272 close_filestruct(fsp);
274 if (fsp->fsp_name)
275 string_free(&fsp->fsp_name);
277 file_free(fsp);
278 return 0;
281 /****************************************************************************
282 Close a 'stat file' opened internally.
283 ****************************************************************************/
285 static int close_stat(files_struct *fsp)
288 * Do the code common to files and directories.
290 close_filestruct(fsp);
292 if (fsp->fsp_name)
293 string_free(&fsp->fsp_name);
295 file_free(fsp);
296 return 0;
299 /****************************************************************************
300 Close a files_struct.
301 ****************************************************************************/
303 int close_file(files_struct *fsp, BOOL normal_close)
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);