source: trunk/samba-3.0.25pre1/source/smbd/close.c@ 1

Last change on this file since 1 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 14.1 KB
Line 
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
7
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.
12
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.
17
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.
21*/
22
23#include "includes.h"
24
25extern struct current_user current_user;
26
27/****************************************************************************
28 Run a file if it is a magic script.
29****************************************************************************/
30
31static void check_magic(files_struct *fsp,connection_struct *conn)
32{
33 if (!*lp_magicscript(SNUM(conn)))
34 return;
35
36 DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
37
38 {
39 char *p;
40 if (!(p = strrchr_m(fsp->fsp_name,'/')))
41 p = fsp->fsp_name;
42 else
43 p++;
44
45 if (!strequal(lp_magicscript(SNUM(conn)),p))
46 return;
47 }
48
49 {
50 int ret;
51 pstring magic_output;
52 pstring fname;
53 SMB_STRUCT_STAT st;
54 int tmp_fd, outfd;
55
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);
61
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;
70 }
71 outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
72 if (outfd == -1) {
73 close(tmp_fd);
74 return;
75 }
76
77 if (sys_fstat(tmp_fd,&st) == -1) {
78 close(tmp_fd);
79 close(outfd);
80 return;
81 }
82
83 transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
84 close(tmp_fd);
85 close(outfd);
86 }
87}
88
89/****************************************************************************
90 Common code to close a file or a directory.
91****************************************************************************/
92
93static NTSTATUS close_filestruct(files_struct *fsp)
94{
95 NTSTATUS status = NT_STATUS_OK;
96 connection_struct *conn = fsp->conn;
97
98 if (fsp->fh->fd != -1) {
99 if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
100 status = map_nt_error_from_unix(errno);
101 }
102 delete_write_cache(fsp);
103 }
104
105 conn->num_files_open--;
106 SAFE_FREE(fsp->wbmpx_ptr);
107 return status;
108}
109
110/****************************************************************************
111 If any deferred opens are waiting on this close, notify them.
112****************************************************************************/
113
114static void notify_deferred_opens(struct share_mode_lock *lck)
115{
116 int i;
117
118 for (i=0; i<lck->num_share_modes; i++) {
119 struct share_mode_entry *e = &lck->share_modes[i];
120
121 if (!is_deferred_open_entry(e)) {
122 continue;
123 }
124
125 if (procid_is_me(&e->pid)) {
126 /*
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.
131 */
132 schedule_deferred_open_smb_message(e->op_mid);
133 } else {
134 char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
135
136 share_mode_entry_to_message(msg, e);
137
138 message_send_pid(e->pid, MSG_SMB_OPEN_RETRY,
139 msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
140 }
141 }
142}
143
144/****************************************************************************
145 Deal with removing a share mode on last close.
146****************************************************************************/
147
148static NTSTATUS close_remove_share_mode(files_struct *fsp,
149 enum file_close_type close_type)
150{
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;
156
157 /*
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.
161 */
162
163 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
164
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;
169 }
170
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));
174 }
175
176 if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
177 BOOL became_user = False;
178
179 /* Initial delete on close was set and no one else
180 * wrote a real delete on close. */
181
182 if (current_user.vuid != fsp->vuid) {
183 become_user(conn, fsp->vuid);
184 became_user = True;
185 }
186 set_delete_on_close_lck(lck, True, &current_user.ut);
187 if (became_user) {
188 unbecome_user();
189 }
190 }
191
192 delete_file = lck->delete_on_close;
193
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;
203 }
204 delete_file = False;
205 break;
206 }
207 }
208 }
209
210 /* Notify any deferred opens waiting on this close. */
211 notify_deferred_opens(lck);
212 reply_to_oplock_break_requests(fsp);
213
214 /*
215 * NT can set delete_on_close of the last open
216 * reference to a file.
217 */
218
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;
224 }
225
226 /*
227 * Ok, we have to delete the file
228 */
229
230 DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
231 "- deleting file.\n", fsp->fsp_name));
232
233 /* Become the user who requested the delete. */
234
235 if (!push_sec_ctx()) {
236 smb_panic("close_remove_share_mode: file %s. failed to push "
237 "sec_ctx.\n");
238 }
239
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);
245
246 /* We can only delete the file if the name we have is still valid and
247 hasn't been renamed. */
248
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) ));
253 /*
254 * Don't save the errno here, we ignore this error
255 */
256 goto done;
257 }
258
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 ));
268 /*
269 * Don't save the errno here, we ignore this error
270 */
271 goto done;
272 }
273
274 if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
275 /*
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.
281 */
282
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) ));
286
287 status = map_nt_error_from_unix(errno);
288 }
289
290 /* As we now have POSIX opens which can unlink
291 * with other open files we may have taken
292 * this code path with more than one share mode
293 * entry - ensure we only delete once by resetting
294 * the delete on close flag. JRA.
295 */
296
297 set_delete_on_close_lck(lck, False, NULL);
298
299 done:
300
301 /* unbecome user. */
302 pop_sec_ctx();
303
304 TALLOC_FREE(lck);
305 return status;
306}
307
308/****************************************************************************
309 Close a file.
310
311 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
312 printing and magic scripts are only run on normal close.
313 delete on close is done on normal and shutdown close.
314****************************************************************************/
315
316static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type)
317{
318 NTSTATUS status = NT_STATUS_OK;
319 NTSTATUS saved_status1 = NT_STATUS_OK;
320 NTSTATUS saved_status2 = NT_STATUS_OK;
321 NTSTATUS saved_status3 = NT_STATUS_OK;
322 connection_struct *conn = fsp->conn;
323
324 if (fsp->aio_write_behind) {
325 /*
326 * If we're finishing write behind on a close we can get a write
327 * error here, we must remember this.
328 */
329 int ret = wait_for_aio_completion(fsp);
330 if (ret) {
331 saved_status1 = map_nt_error_from_unix(ret);
332 }
333 } else {
334 cancel_aio_by_fsp(fsp);
335 }
336
337 /*
338 * If we're flushing on a close we can get a write
339 * error here, we must remember this.
340 */
341
342 saved_status2 = close_filestruct(fsp);
343
344 if (fsp->print_file) {
345 print_fsp_end(fsp, close_type);
346 file_free(fsp);
347 return NT_STATUS_OK;
348 }
349
350 /* If this is an old DOS or FCB open and we have multiple opens on
351 the same handle we only have one share mode. Ensure we only remove
352 the share mode on the last close. */
353
354 if (fsp->fh->ref_count == 1) {
355 /* Should we return on error here... ? */
356 saved_status3 = close_remove_share_mode(fsp, close_type);
357 }
358
359 if(fsp->oplock_type) {
360 release_file_oplock(fsp);
361 }
362
363 locking_close_file(fsp);
364
365 status = fd_close(conn, fsp);
366
367 /* check for magic scripts */
368 if (close_type == NORMAL_CLOSE) {
369 check_magic(fsp,conn);
370 }
371
372 /*
373 * Ensure pending modtime is set after close.
374 */
375
376 if(fsp->pending_modtime && fsp->pending_modtime_owner) {
377 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
378 } else if (fsp->last_write_time) {
379 set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
380 }
381
382 if (NT_STATUS_IS_OK(status)) {
383 if (!NT_STATUS_IS_OK(saved_status1)) {
384 status = saved_status1;
385 } else if (!NT_STATUS_IS_OK(saved_status2)) {
386 status = saved_status2;
387 } else if (!NT_STATUS_IS_OK(saved_status3)) {
388 status = saved_status3;
389 }
390 }
391
392 DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
393 conn->user,fsp->fsp_name,
394 conn->num_files_open,
395 nt_errstr(status) ));
396
397 file_free(fsp);
398 return status;
399}
400
401/****************************************************************************
402 Close a directory opened by an NT SMB call.
403****************************************************************************/
404
405static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type)
406{
407 struct share_mode_lock *lck = 0;
408 BOOL delete_dir = False;
409 NTSTATUS status = NT_STATUS_OK;
410
411 /*
412 * NT can set delete_on_close of the last open
413 * reference to a directory also.
414 */
415
416 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
417
418 if (lck == NULL) {
419 DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
420 return NT_STATUS_INVALID_PARAMETER;
421 }
422
423 if (!del_share_mode(lck, fsp)) {
424 DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
425 }
426
427 if (fsp->initial_delete_on_close) {
428 BOOL became_user = False;
429
430 /* Initial delete on close was set - for
431 * directories we don't care if anyone else
432 * wrote a real delete on close. */
433
434 if (current_user.vuid != fsp->vuid) {
435 become_user(fsp->conn, fsp->vuid);
436 became_user = True;
437 }
438 send_stat_cache_delete_message(fsp->fsp_name);
439 set_delete_on_close_lck(lck, True, &current_user.ut);
440 if (became_user) {
441 unbecome_user();
442 }
443 }
444
445 delete_dir = lck->delete_on_close;
446
447 if (delete_dir) {
448 int i;
449 /* See if others still have the dir open. If this is the
450 * case, then don't delete. If all opens are POSIX delete now. */
451 for (i=0; i<lck->num_share_modes; i++) {
452 struct share_mode_entry *e = &lck->share_modes[i];
453 if (is_valid_share_mode_entry(e)) {
454 if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
455 continue;
456 }
457 delete_dir = False;
458 break;
459 }
460 }
461 }
462
463 if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
464 delete_dir &&
465 lck->delete_token) {
466
467 /* Become the user who requested the delete. */
468
469 if (!push_sec_ctx()) {
470 smb_panic("close_directory: failed to push sec_ctx.\n");
471 }
472
473 set_sec_ctx(lck->delete_token->uid,
474 lck->delete_token->gid,
475 lck->delete_token->ngroups,
476 lck->delete_token->groups,
477 NULL);
478
479 TALLOC_FREE(lck);
480
481 status = rmdir_internals(fsp->conn, fsp->fsp_name);
482
483 DEBUG(5,("close_directory: %s. Delete on close was set - "
484 "deleting directory returned %s.\n",
485 fsp->fsp_name, nt_errstr(status)));
486
487 /* unbecome user. */
488 pop_sec_ctx();
489
490 /*
491 * Ensure we remove any change notify requests that would
492 * now fail as the directory has been deleted.
493 */
494
495 if(NT_STATUS_IS_OK(status)) {
496 remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
497 }
498 } else {
499 TALLOC_FREE(lck);
500 remove_pending_change_notify_requests_by_fid(
501 fsp, NT_STATUS_OK);
502 }
503
504 /*
505 * Do the code common to files and directories.
506 */
507 close_filestruct(fsp);
508 file_free(fsp);
509 return status;
510}
511
512/****************************************************************************
513 Close a 'stat file' opened internally.
514****************************************************************************/
515
516NTSTATUS close_stat(files_struct *fsp)
517{
518 /*
519 * Do the code common to files and directories.
520 */
521 close_filestruct(fsp);
522 file_free(fsp);
523 return NT_STATUS_OK;
524}
525
526/****************************************************************************
527 Close a files_struct.
528****************************************************************************/
529
530NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
531{
532 if(fsp->is_directory) {
533 return close_directory(fsp, close_type);
534 } else if (fsp->is_stat) {
535 return close_stat(fsp);
536 } else if (fsp->fake_file_handle != NULL) {
537 return close_fake_file(fsp);
538 }
539 return close_normal_file(fsp, close_type);
540}
Note: See TracBrowser for help on using the repository browser.