Use canonical mappings for file controls. Fixes W2KSP2 profile problems (I
[Samba/ekacnet.git] / source / smbd / close.c
blob217c81228f7e5198b5e5884e526e35f7d4fabfbd
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 file closing
5 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
22 #include "includes.h"
24 extern int DEBUGLEVEL;
26 /****************************************************************************
27 run a file if it is a magic script
28 ****************************************************************************/
29 static void check_magic(files_struct *fsp,connection_struct *conn)
31 if (!*lp_magicscript(SNUM(conn)))
32 return;
34 DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
37 char *p;
38 if (!(p = strrchr(fsp->fsp_name,'/')))
39 p = fsp->fsp_name;
40 else
41 p++;
43 if (!strequal(lp_magicscript(SNUM(conn)),p))
44 return;
48 int ret;
49 pstring magic_output;
50 pstring fname;
51 SMB_STRUCT_STAT st;
52 int tmp_fd, outfd;
54 pstrcpy(fname,fsp->fsp_name);
55 if (*lp_magicoutput(SNUM(conn)))
56 pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
57 else
58 slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
60 chmod(fname,0755);
61 ret = smbrun(fname,&tmp_fd);
62 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
63 unlink(fname);
64 if (ret != 0 || tmp_fd == -1) {
65 if (tmp_fd != -1)
66 close(tmp_fd);
67 return;
69 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
70 if (outfd == -1) {
71 close(tmp_fd);
72 return;
75 if (sys_fstat(tmp_fd,&st) == -1) {
76 close(tmp_fd);
77 close(outfd);
78 return;
81 transfer_file(tmp_fd,outfd,st.st_size, NULL,0,0);
82 close(tmp_fd);
83 close(outfd);
87 /****************************************************************************
88 Common code to close a file or a directory.
89 ****************************************************************************/
91 static int close_filestruct(files_struct *fsp)
93 connection_struct *conn = fsp->conn;
94 int ret = 0;
96 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
97 ret = -1;
99 delete_write_cache(fsp);
101 fsp->is_directory = False;
102 fsp->stat_open = False;
104 conn->num_files_open--;
105 if(fsp->wbmpx_ptr) {
106 free((char *)fsp->wbmpx_ptr);
107 fsp->wbmpx_ptr = NULL;
110 return ret;
113 /****************************************************************************
114 Close a file.
116 If normal_close is 1 then this came from a normal SMBclose (or equivalent)
117 operation otherwise it came as the result of some other operation such as
118 the closing of the connection. In the latter case printing and
119 magic scripts are not run.
120 ****************************************************************************/
122 static int close_normal_file(files_struct *fsp, BOOL normal_close)
124 share_mode_entry *share_entry = NULL;
125 size_t share_entry_count = 0;
126 BOOL delete_on_close = False;
127 connection_struct *conn = fsp->conn;
128 int err = 0;
129 int err1 = 0;
131 remove_pending_lock_requests_by_fid(fsp);
134 * If we're flushing on a close we can get a write
135 * error here, we must remember this.
138 if (close_filestruct(fsp) == -1)
139 err1 = -1;
141 if (fsp->print_file) {
142 print_fsp_end(fsp, normal_close);
143 file_free(fsp);
144 return 0;
148 * Lock the share entries, and determine if we should delete
149 * on close. If so delete whilst the lock is still in effect.
150 * This prevents race conditions with the file being created. JRA.
153 lock_share_entry_fsp(fsp);
154 share_entry_count = del_share_mode(fsp, &share_entry);
157 * We delete on close if it's the last open, and the
158 * delete on close flag was set in the entry we just deleted.
161 if ((share_entry_count == 0) && share_entry &&
162 GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) )
163 delete_on_close = True;
165 safe_free(share_entry);
168 * NT can set delete_on_close of the last open
169 * reference to a file.
172 if (normal_close && delete_on_close) {
173 DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
174 fsp->fsp_name));
175 if(fsp->conn->vfs_ops.unlink(conn,dos_to_unix(fsp->fsp_name, False)) != 0) {
177 * This call can potentially fail as another smbd may have
178 * had the file open with delete on close set and deleted
179 * it when its last reference to this file went away. Hence
180 * we log this but not at debug level zero.
183 DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
184 with error %s\n", fsp->fsp_name, strerror(errno) ));
188 unlock_share_entry_fsp(fsp);
190 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
191 release_file_oplock(fsp);
193 locking_close_file(fsp);
195 err = fd_close(conn, fsp);
197 /* check for magic scripts */
198 if (normal_close) {
199 check_magic(fsp,conn);
203 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
204 conn->user,fsp->fsp_name,
205 conn->num_files_open, err ? strerror(err) : ""));
207 if (fsp->fsp_name) {
208 string_free(&fsp->fsp_name);
211 file_free(fsp);
213 if (err == -1 || err1 == -1)
214 return -1;
215 else
216 return 0;
219 /****************************************************************************
220 Close a directory opened by an NT SMB call.
221 ****************************************************************************/
223 static int close_directory(files_struct *fsp, BOOL normal_close)
225 remove_pending_change_notify_requests_by_fid(fsp);
228 * NT can set delete_on_close of the last open
229 * reference to a directory also.
232 if (normal_close && fsp->directory_delete_on_close) {
233 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
234 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
235 fsp->fsp_name, ok ? "succeeded" : "failed" ));
238 * Ensure we remove any change notify requests that would
239 * now fail as the directory has been deleted.
242 if(ok)
243 remove_pending_change_notify_requests_by_filename(fsp);
247 * Do the code common to files and directories.
249 close_filestruct(fsp);
251 if (fsp->fsp_name)
252 string_free(&fsp->fsp_name);
254 file_free(fsp);
256 return 0;
259 /****************************************************************************
260 Close a file opened with null permissions in order to read permissions.
261 ****************************************************************************/
263 static int close_statfile(files_struct *fsp, BOOL normal_close)
265 close_filestruct(fsp);
267 if (fsp->fsp_name)
268 string_free(&fsp->fsp_name);
270 file_free(fsp);
272 return 0;
275 /****************************************************************************
276 Close a directory opened by an NT SMB call.
277 ****************************************************************************/
279 int close_file(files_struct *fsp, BOOL normal_close)
281 if(fsp->is_directory)
282 return close_directory(fsp, normal_close);
283 else if(fsp->stat_open)
284 return close_statfile(fsp, normal_close);
285 return close_normal_file(fsp, normal_close);