r21191: Add in the POSIX open/mkdir/unlink calls.
[Samba/nascimento.git] / source / smbd / close.c
blob05a45cc14fa85d91ddec6fd4f95f35c0f68c1e91
1 /*
2 Unix SMB/CIFS implementation.
3 file closing
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1992-2007.
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 extern struct current_user current_user;
27 /****************************************************************************
28 Run a file if it is a magic script.
29 ****************************************************************************/
31 static void check_magic(files_struct *fsp,connection_struct *conn)
33 if (!*lp_magicscript(SNUM(conn)))
34 return;
36 DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
39 char *p;
40 if (!(p = strrchr_m(fsp->fsp_name,'/')))
41 p = fsp->fsp_name;
42 else
43 p++;
45 if (!strequal(lp_magicscript(SNUM(conn)),p))
46 return;
50 int ret;
51 pstring magic_output;
52 pstring fname;
53 SMB_STRUCT_STAT st;
54 int tmp_fd, outfd;
56 pstrcpy(fname,fsp->fsp_name);
57 if (*lp_magicoutput(SNUM(conn)))
58 pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
59 else
60 slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
62 chmod(fname,0755);
63 ret = smbrun(fname,&tmp_fd);
64 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
65 unlink(fname);
66 if (ret != 0 || tmp_fd == -1) {
67 if (tmp_fd != -1)
68 close(tmp_fd);
69 return;
71 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
72 if (outfd == -1) {
73 close(tmp_fd);
74 return;
77 if (sys_fstat(tmp_fd,&st) == -1) {
78 close(tmp_fd);
79 close(outfd);
80 return;
83 transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
84 close(tmp_fd);
85 close(outfd);
89 /****************************************************************************
90 Common code to close a file or a directory.
91 ****************************************************************************/
93 static NTSTATUS close_filestruct(files_struct *fsp)
95 NTSTATUS status = NT_STATUS_OK;
96 connection_struct *conn = fsp->conn;
98 if (fsp->fh->fd != -1) {
99 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
100 status = map_nt_error_from_unix(errno);
102 delete_write_cache(fsp);
105 conn->num_files_open--;
106 SAFE_FREE(fsp->wbmpx_ptr);
107 return status;
110 /****************************************************************************
111 If any deferred opens are waiting on this close, notify them.
112 ****************************************************************************/
114 static void notify_deferred_opens(struct share_mode_lock *lck)
116 int i;
118 for (i=0; i<lck->num_share_modes; i++) {
119 struct share_mode_entry *e = &lck->share_modes[i];
121 if (!is_deferred_open_entry(e)) {
122 continue;
125 if (procid_is_me(&e->pid)) {
127 * We need to notify ourself to retry the open. Do
128 * this by finding the queued SMB record, moving it to
129 * the head of the queue and changing the wait time to
130 * zero.
132 schedule_deferred_open_smb_message(e->op_mid);
133 } else {
134 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
136 share_mode_entry_to_message(msg, e);
138 message_send_pid(e->pid, MSG_SMB_OPEN_RETRY,
139 msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
144 /****************************************************************************
145 Deal with removing a share mode on last close.
146 ****************************************************************************/
148 static NTSTATUS close_remove_share_mode(files_struct *fsp,
149 enum file_close_type close_type)
151 connection_struct *conn = fsp->conn;
152 BOOL delete_file = False;
153 struct share_mode_lock *lck;
154 SMB_STRUCT_STAT sbuf;
155 NTSTATUS status = NT_STATUS_OK;
158 * Lock the share entries, and determine if we should delete
159 * on close. If so delete whilst the lock is still in effect.
160 * This prevents race conditions with the file being created. JRA.
163 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
165 if (lck == NULL) {
166 DEBUG(0, ("close_remove_share_mode: Could not get share mode "
167 "lock for file %s\n", fsp->fsp_name));
168 return NT_STATUS_INVALID_PARAMETER;
171 if (!del_share_mode(lck, fsp)) {
172 DEBUG(0, ("close_remove_share_mode: Could not delete share "
173 "entry for file %s\n", fsp->fsp_name));
176 if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
177 BOOL became_user = False;
179 /* Initial delete on close was set and no one else
180 * wrote a real delete on close. */
182 if (current_user.vuid != fsp->vuid) {
183 become_user(conn, fsp->vuid);
184 became_user = True;
186 set_delete_on_close_lck(lck, True, &current_user.ut);
187 if (became_user) {
188 unbecome_user();
192 delete_file = lck->delete_on_close;
194 if (delete_file) {
195 int i;
196 /* See if others still have the file open. If this is the
197 * case, then don't delete. If all opens are POSIX delete now. */
198 for (i=0; i<lck->num_share_modes; i++) {
199 struct share_mode_entry *e = &lck->share_modes[i];
200 if (is_valid_share_mode_entry(e)) {
201 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
202 continue;
204 delete_file = False;
205 break;
210 /* Notify any deferred opens waiting on this close. */
211 notify_deferred_opens(lck);
212 reply_to_oplock_break_requests(fsp);
215 * NT can set delete_on_close of the last open
216 * reference to a file.
219 if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE)
220 || !delete_file
221 || (lck->delete_token == NULL)) {
222 TALLOC_FREE(lck);
223 return NT_STATUS_OK;
227 * Ok, we have to delete the file
230 DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
231 "- deleting file.\n", fsp->fsp_name));
233 /* Become the user who requested the delete. */
235 if (!push_sec_ctx()) {
236 smb_panic("close_remove_share_mode: file %s. failed to push "
237 "sec_ctx.\n");
240 set_sec_ctx(lck->delete_token->uid,
241 lck->delete_token->gid,
242 lck->delete_token->ngroups,
243 lck->delete_token->groups,
244 NULL);
246 /* We can only delete the file if the name we have is still valid and
247 hasn't been renamed. */
249 if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) {
250 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
251 "was set and stat failed with error %s\n",
252 fsp->fsp_name, strerror(errno) ));
254 * Don't save the errno here, we ignore this error
256 goto done;
259 if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) {
260 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
261 "was set and dev and/or inode does not match\n",
262 fsp->fsp_name ));
263 DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, "
264 "inode = %.0f stat dev = %x, inode = %.0f\n",
265 fsp->fsp_name,
266 (unsigned int)fsp->dev, (double)fsp->inode,
267 (unsigned int)sbuf.st_dev, (double)sbuf.st_ino ));
269 * Don't save the errno here, we ignore this error
271 goto done;
274 if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
276 * This call can potentially fail as another smbd may
277 * have had the file open with delete on close set and
278 * deleted it when its last reference to this file
279 * went away. Hence we log this but not at debug level
280 * zero.
283 DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
284 "was set and unlink failed with error %s\n",
285 fsp->fsp_name, strerror(errno) ));
287 status = map_nt_error_from_unix(errno);
290 done:
292 /* unbecome user. */
293 pop_sec_ctx();
295 TALLOC_FREE(lck);
296 return status;
299 /****************************************************************************
300 Close a file.
302 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
303 printing and magic scripts are only run on normal close.
304 delete on close is done on normal and shutdown close.
305 ****************************************************************************/
307 static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type)
309 NTSTATUS status = NT_STATUS_OK;
310 NTSTATUS saved_status1 = NT_STATUS_OK;
311 NTSTATUS saved_status2 = NT_STATUS_OK;
312 NTSTATUS saved_status3 = NT_STATUS_OK;
313 connection_struct *conn = fsp->conn;
315 if (fsp->aio_write_behind) {
317 * If we're finishing write behind on a close we can get a write
318 * error here, we must remember this.
320 int ret = wait_for_aio_completion(fsp);
321 if (ret) {
322 saved_status1 = map_nt_error_from_unix(ret);
324 } else {
325 cancel_aio_by_fsp(fsp);
329 * If we're flushing on a close we can get a write
330 * error here, we must remember this.
333 saved_status2 = close_filestruct(fsp);
335 if (fsp->print_file) {
336 print_fsp_end(fsp, close_type);
337 file_free(fsp);
338 return NT_STATUS_OK;
341 /* If this is an old DOS or FCB open and we have multiple opens on
342 the same handle we only have one share mode. Ensure we only remove
343 the share mode on the last close. */
345 if (fsp->fh->ref_count == 1) {
346 /* Should we return on error here... ? */
347 saved_status3 = close_remove_share_mode(fsp, close_type);
350 if(fsp->oplock_type) {
351 release_file_oplock(fsp);
354 locking_close_file(fsp);
356 status = fd_close(conn, fsp);
358 /* check for magic scripts */
359 if (close_type == NORMAL_CLOSE) {
360 check_magic(fsp,conn);
364 * Ensure pending modtime is set after close.
367 if(fsp->pending_modtime && fsp->pending_modtime_owner) {
368 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
369 } else if (fsp->last_write_time) {
370 set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
373 if (NT_STATUS_IS_OK(status)) {
374 if (!NT_STATUS_IS_OK(saved_status1)) {
375 status = saved_status1;
376 } else if (!NT_STATUS_IS_OK(saved_status2)) {
377 status = saved_status2;
378 } else if (!NT_STATUS_IS_OK(saved_status3)) {
379 status = saved_status3;
383 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
384 conn->user,fsp->fsp_name,
385 conn->num_files_open,
386 nt_errstr(status) ));
388 file_free(fsp);
389 return status;
392 /****************************************************************************
393 Close a directory opened by an NT SMB call.
394 ****************************************************************************/
396 static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type)
398 struct share_mode_lock *lck = 0;
399 BOOL delete_dir = False;
400 NTSTATUS status = NT_STATUS_OK;
403 * NT can set delete_on_close of the last open
404 * reference to a directory also.
407 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
409 if (lck == NULL) {
410 DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
411 return NT_STATUS_INVALID_PARAMETER;
414 if (!del_share_mode(lck, fsp)) {
415 DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
418 if (fsp->initial_delete_on_close) {
419 BOOL became_user = False;
421 /* Initial delete on close was set - for
422 * directories we don't care if anyone else
423 * wrote a real delete on close. */
425 if (current_user.vuid != fsp->vuid) {
426 become_user(fsp->conn, fsp->vuid);
427 became_user = True;
429 send_stat_cache_delete_message(fsp->fsp_name);
430 set_delete_on_close_lck(lck, True, &current_user.ut);
431 if (became_user) {
432 unbecome_user();
436 delete_dir = lck->delete_on_close;
438 if (delete_dir) {
439 int i;
440 /* See if others still have the dir open. If this is the
441 * case, then don't delete. If all opens are POSIX delete now. */
442 for (i=0; i<lck->num_share_modes; i++) {
443 struct share_mode_entry *e = &lck->share_modes[i];
444 if (is_valid_share_mode_entry(e)) {
445 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
446 continue;
448 delete_dir = False;
449 break;
454 if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
455 delete_dir &&
456 lck->delete_token) {
457 BOOL ok;
459 /* Become the user who requested the delete. */
461 if (!push_sec_ctx()) {
462 smb_panic("close_directory: failed to push sec_ctx.\n");
465 set_sec_ctx(lck->delete_token->uid,
466 lck->delete_token->gid,
467 lck->delete_token->ngroups,
468 lck->delete_token->groups,
469 NULL);
471 TALLOC_FREE(lck);
473 status = rmdir_internals(fsp->conn, fsp->fsp_name);
475 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
476 fsp->fsp_name, ok ? "succeeded" : "failed" ));
478 /* unbecome user. */
479 pop_sec_ctx();
482 * Ensure we remove any change notify requests that would
483 * now fail as the directory has been deleted.
486 if(NT_STATUS_IS_OK(status)) {
487 remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
489 } else {
490 TALLOC_FREE(lck);
491 remove_pending_change_notify_requests_by_fid(
492 fsp, NT_STATUS_OK);
496 * Do the code common to files and directories.
498 close_filestruct(fsp);
499 file_free(fsp);
500 return status;
503 /****************************************************************************
504 Close a 'stat file' opened internally.
505 ****************************************************************************/
507 NTSTATUS close_stat(files_struct *fsp)
510 * Do the code common to files and directories.
512 close_filestruct(fsp);
513 file_free(fsp);
514 return NT_STATUS_OK;
517 /****************************************************************************
518 Close a files_struct.
519 ****************************************************************************/
521 NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
523 if(fsp->is_directory) {
524 return close_directory(fsp, close_type);
525 } else if (fsp->is_stat) {
526 return close_stat(fsp);
527 } else if (fsp->fake_file_handle != NULL) {
528 return close_fake_file(fsp);
530 return close_normal_file(fsp, close_type);