r11341: Put directory opens into the share mode db so we
[Samba/nascimento.git] / source3 / smbd / close.c
blob44ab168a3af721d2052f63ff5789eb482dd73d44
1 /*
2 Unix SMB/CIFS implementation.
3 file closing
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1992-2004.
6 Copyright (C) Volker Lendecke 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 /****************************************************************************
26 Run a file if it is a magic script.
27 ****************************************************************************/
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_m(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,(SMB_OFF_T)st.st_size);
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 (fsp->fh->fd != -1) {
97 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
98 ret = -1;
100 delete_write_cache(fsp);
103 conn->num_files_open--;
104 SAFE_FREE(fsp->wbmpx_ptr);
106 return ret;
109 /****************************************************************************
110 If any deferred opens are waiting on this close, notify them.
111 ****************************************************************************/
113 static void notify_deferred_opens(struct share_mode_lock *lck)
115 int i;
117 for (i=0; i<lck->num_share_modes; i++) {
118 struct share_mode_entry *e = &lck->share_modes[i];
120 if (!is_deferred_open_entry(e)) {
121 continue;
124 if (procid_is_me(&e->pid)) {
126 * We need to notify ourself to retry the open. Do
127 * this by finding the queued SMB record, moving it to
128 * the head of the queue and changing the wait time to
129 * zero.
131 schedule_deferred_open_smb_message(e->op_mid);
132 } else {
133 message_send_pid(e->pid, MSG_SMB_OPEN_RETRY,
134 e, sizeof(*e), True);
139 /****************************************************************************
140 Close a file.
142 If normal_close is 1 then this came from a normal SMBclose (or equivalent)
143 operation otherwise it came as the result of some other operation such as
144 the closing of the connection. In the latter case printing and
145 magic scripts are not run.
146 ****************************************************************************/
148 static int close_normal_file(files_struct *fsp, BOOL normal_close)
150 BOOL delete_file = False;
151 connection_struct *conn = fsp->conn;
152 int saved_errno = 0;
153 int err = 0;
154 int err1 = 0;
155 struct share_mode_lock *lck;
157 remove_pending_lock_requests_by_fid(fsp);
159 if (fsp->aio_write_behind) {
161 * If we're finishing write behind on a close we can get a write
162 * error here, we must remember this.
164 int ret = wait_for_aio_completion(fsp);
165 if (ret) {
166 saved_errno = ret;
167 err1 = -1;
169 } else {
170 cancel_aio_by_fsp(fsp);
174 * If we're flushing on a close we can get a write
175 * error here, we must remember this.
178 if (close_filestruct(fsp) == -1) {
179 saved_errno = errno;
180 err1 = -1;
183 if (fsp->print_file) {
184 print_fsp_end(fsp, normal_close);
185 file_free(fsp);
186 return 0;
190 * Lock the share entries, and determine if we should delete
191 * on close. If so delete whilst the lock is still in effect.
192 * This prevents race conditions with the file being created. JRA.
195 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name);
197 if (lck == NULL) {
198 DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name));
199 return EINVAL;
202 if (!del_share_mode(lck, fsp)) {
203 DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name));
206 delete_file = lck->delete_on_close;
208 if (delete_file) {
209 int i;
210 /* See if others still have the file open. If this is the
211 * case, then don't delete */
212 for (i=0; i<lck->num_share_modes; i++) {
213 if (is_valid_share_mode_entry(&lck->share_modes[i])) {
214 delete_file = False;
215 break;
220 /* Notify any deferred opens waiting on this close. */
221 notify_deferred_opens(lck);
222 reply_to_oplock_break_requests(fsp);
225 * NT can set delete_on_close of the last open
226 * reference to a file.
229 if (normal_close && delete_file) {
230 DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
231 fsp->fsp_name));
232 if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
234 * This call can potentially fail as another smbd may have
235 * had the file open with delete on close set and deleted
236 * it when its last reference to this file went away. Hence
237 * we log this but not at debug level zero.
240 DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
241 with error %s\n", fsp->fsp_name, strerror(errno) ));
243 process_pending_change_notify_queue((time_t)0);
246 talloc_free(lck);
248 if(fsp->oplock_type)
249 release_file_oplock(fsp);
251 locking_close_file(fsp);
253 err = fd_close(conn, fsp);
255 /* Only save errno if fd_close failed and we don't already
256 have an errno saved from a flush call. */
257 if ((err1 != -1) && (err == -1)) {
258 saved_errno = errno;
261 /* check for magic scripts */
262 if (normal_close) {
263 check_magic(fsp,conn);
267 * Ensure pending modtime is set after close.
270 if(fsp->pending_modtime && fsp->pending_modtime_owner) {
271 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
272 } else if (fsp->last_write_time) {
273 set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
276 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
277 conn->user,fsp->fsp_name,
278 conn->num_files_open,
279 (err == -1 || err1 == -1) ? strerror(saved_errno) : ""));
281 if (fsp->fsp_name)
282 string_free(&fsp->fsp_name);
284 file_free(fsp);
286 if (err == -1 || err1 == -1) {
287 errno = saved_errno;
288 return saved_errno;
289 } else {
290 return 0;
294 /****************************************************************************
295 Close a directory opened by an NT SMB call.
296 ****************************************************************************/
298 static int close_directory(files_struct *fsp, BOOL normal_close)
300 struct share_mode_lock *lck = 0;
301 BOOL delete_dir = False;
303 remove_pending_change_notify_requests_by_fid(fsp);
306 * NT can set delete_on_close of the last open
307 * reference to a directory also.
310 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name);
312 if (lck == NULL) {
313 DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
314 return EINVAL;
317 if (!del_share_mode(lck, fsp)) {
318 DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
321 delete_dir = lck->delete_on_close;
323 if (delete_dir) {
324 int i;
325 /* See if others still have the file open. If this is the
326 * case, then don't delete */
327 for (i=0; i<lck->num_share_modes; i++) {
328 if (is_valid_share_mode_entry(&lck->share_modes[i])) {
329 delete_dir = False;
330 break;
336 if (normal_close && delete_dir) {
337 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
338 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
339 fsp->fsp_name, ok ? "succeeded" : "failed" ));
342 * Ensure we remove any change notify requests that would
343 * now fail as the directory has been deleted.
346 if(ok) {
347 remove_pending_change_notify_requests_by_filename(fsp);
349 process_pending_change_notify_queue((time_t)0);
352 talloc_free(lck);
355 * Do the code common to files and directories.
357 close_filestruct(fsp);
359 if (fsp->fsp_name) {
360 string_free(&fsp->fsp_name);
363 file_free(fsp);
364 return 0;
367 /****************************************************************************
368 Close a 'stat file' opened internally.
369 ****************************************************************************/
371 static int close_stat(files_struct *fsp)
374 * Do the code common to files and directories.
376 close_filestruct(fsp);
378 if (fsp->fsp_name)
379 string_free(&fsp->fsp_name);
381 file_free(fsp);
382 return 0;
385 /****************************************************************************
386 Close a files_struct.
387 ****************************************************************************/
389 int close_file(files_struct *fsp, BOOL normal_close)
391 if(fsp->is_directory)
392 return close_directory(fsp, normal_close);
393 else if (fsp->is_stat)
394 return close_stat(fsp);
395 else
396 return close_normal_file(fsp, normal_close);