~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/smbd/close.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 3 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, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include "includes.h"
 
23
 
 
24
extern struct current_user current_user;
 
25
 
 
26
/****************************************************************************
 
27
 Run a file if it is a magic script.
 
28
****************************************************************************/
 
29
 
 
30
static void check_magic(struct files_struct *fsp)
 
31
{
 
32
        int ret;
 
33
        const char *magic_output = NULL;
 
34
        SMB_STRUCT_STAT st;
 
35
        int tmp_fd, outfd;
 
36
        TALLOC_CTX *ctx = NULL;
 
37
        const char *p;
 
38
        struct connection_struct *conn = fsp->conn;
 
39
 
 
40
        if (!*lp_magicscript(SNUM(conn))) {
 
41
                return;
 
42
        }
 
43
 
 
44
        DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
 
45
 
 
46
        if (!(p = strrchr_m(fsp->fsp_name,'/'))) {
 
47
                p = fsp->fsp_name;
 
48
        } else {
 
49
                p++;
 
50
        }
 
51
 
 
52
        if (!strequal(lp_magicscript(SNUM(conn)),p)) {
 
53
                return;
 
54
        }
 
55
 
 
56
        ctx = talloc_stackframe();
 
57
 
 
58
        if (*lp_magicoutput(SNUM(conn))) {
 
59
                magic_output = lp_magicoutput(SNUM(conn));
 
60
        } else {
 
61
                magic_output = talloc_asprintf(ctx,
 
62
                                "%s.out",
 
63
                                fsp->fsp_name);
 
64
        }
 
65
        if (!magic_output) {
 
66
                TALLOC_FREE(ctx);
 
67
                return;
 
68
        }
 
69
 
 
70
        /* Ensure we don't depend on user's PATH. */
 
71
        p = talloc_asprintf(ctx, "./%s", fsp->fsp_name);
 
72
        if (!p) {
 
73
                TALLOC_FREE(ctx);
 
74
                return;
 
75
        }
 
76
 
 
77
        if (chmod(fsp->fsp_name,0755) == -1) {
 
78
                TALLOC_FREE(ctx);
 
79
                return;
 
80
        }
 
81
        ret = smbrun(p,&tmp_fd);
 
82
        DEBUG(3,("Invoking magic command %s gave %d\n",
 
83
                p,ret));
 
84
 
 
85
        unlink(fsp->fsp_name);
 
86
        if (ret != 0 || tmp_fd == -1) {
 
87
                if (tmp_fd != -1) {
 
88
                        close(tmp_fd);
 
89
                }
 
90
                TALLOC_FREE(ctx);
 
91
                return;
 
92
        }
 
93
        outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
 
94
        if (outfd == -1) {
 
95
                close(tmp_fd);
 
96
                TALLOC_FREE(ctx);
 
97
                return;
 
98
        }
 
99
 
 
100
        if (sys_fstat(tmp_fd,&st) == -1) {
 
101
                close(tmp_fd);
 
102
                close(outfd);
 
103
                return;
 
104
        }
 
105
 
 
106
        transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
 
107
        close(tmp_fd);
 
108
        close(outfd);
 
109
        TALLOC_FREE(ctx);
 
110
}
 
111
 
 
112
/****************************************************************************
 
113
  Common code to close a file or a directory.
 
114
****************************************************************************/
 
115
 
 
116
static NTSTATUS close_filestruct(files_struct *fsp)
 
117
{
 
118
        NTSTATUS status = NT_STATUS_OK;
 
119
 
 
120
        if (fsp->fh->fd != -1) {
 
121
                if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
 
122
                        status = map_nt_error_from_unix(errno);
 
123
                }
 
124
                delete_write_cache(fsp);
 
125
        }
 
126
 
 
127
        return status;
 
128
}
 
129
 
 
130
/****************************************************************************
 
131
 If any deferred opens are waiting on this close, notify them.
 
132
****************************************************************************/
 
133
 
 
134
static void notify_deferred_opens(struct share_mode_lock *lck)
 
135
{
 
136
        int i;
 
137
 
 
138
        if (!should_notify_deferred_opens()) {
 
139
                return;
 
140
        }
 
141
 
 
142
        for (i=0; i<lck->num_share_modes; i++) {
 
143
                struct share_mode_entry *e = &lck->share_modes[i];
 
144
 
 
145
                if (!is_deferred_open_entry(e)) {
 
146
                        continue;
 
147
                }
 
148
 
 
149
                if (procid_is_me(&e->pid)) {
 
150
                        /*
 
151
                         * We need to notify ourself to retry the open.  Do
 
152
                         * this by finding the queued SMB record, moving it to
 
153
                         * the head of the queue and changing the wait time to
 
154
                         * zero.
 
155
                         */
 
156
                        schedule_deferred_open_smb_message(e->op_mid);
 
157
                } else {
 
158
                        char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
 
159
 
 
160
                        share_mode_entry_to_message(msg, e);
 
161
 
 
162
                        messaging_send_buf(smbd_messaging_context(),
 
163
                                           e->pid, MSG_SMB_OPEN_RETRY,
 
164
                                           (uint8 *)msg,
 
165
                                           MSG_SMB_SHARE_MODE_ENTRY_SIZE);
 
166
                }
 
167
        }
 
168
}
 
169
 
 
170
/****************************************************************************
 
171
 Delete all streams
 
172
****************************************************************************/
 
173
 
 
174
NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
 
175
{
 
176
        struct stream_struct *stream_info;
 
177
        int i;
 
178
        unsigned int num_streams;
 
179
        TALLOC_CTX *frame = talloc_stackframe();
 
180
        NTSTATUS status;
 
181
 
 
182
        status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
 
183
                                    &num_streams, &stream_info);
 
184
 
 
185
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
 
186
                DEBUG(10, ("no streams around\n"));
 
187
                TALLOC_FREE(frame);
 
188
                return NT_STATUS_OK;
 
189
        }
 
190
 
 
191
        if (!NT_STATUS_IS_OK(status)) {
 
192
                DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
 
193
                           nt_errstr(status)));
 
194
                goto fail;
 
195
        }
 
196
 
 
197
        DEBUG(10, ("delete_all_streams found %d streams\n",
 
198
                   num_streams));
 
199
 
 
200
        if (num_streams == 0) {
 
201
                TALLOC_FREE(frame);
 
202
                return NT_STATUS_OK;
 
203
        }
 
204
 
 
205
        for (i=0; i<num_streams; i++) {
 
206
                int res;
 
207
                char *streamname;
 
208
 
 
209
                if (strequal(stream_info[i].name, "::$DATA")) {
 
210
                        continue;
 
211
                }
 
212
 
 
213
                streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
 
214
                                             stream_info[i].name);
 
215
 
 
216
                if (streamname == NULL) {
 
217
                        DEBUG(0, ("talloc_aprintf failed\n"));
 
218
                        status = NT_STATUS_NO_MEMORY;
 
219
                        goto fail;
 
220
                }
 
221
 
 
222
                res = SMB_VFS_UNLINK(conn, streamname);
 
223
 
 
224
                TALLOC_FREE(streamname);
 
225
 
 
226
                if (res == -1) {
 
227
                        status = map_nt_error_from_unix(errno);
 
228
                        DEBUG(10, ("Could not delete stream %s: %s\n",
 
229
                                   streamname, strerror(errno)));
 
230
                        break;
 
231
                }
 
232
        }
 
233
 
 
234
 fail:
 
235
        TALLOC_FREE(frame);
 
236
        return status;
 
237
}
 
238
 
 
239
/****************************************************************************
 
240
 Deal with removing a share mode on last close.
 
241
****************************************************************************/
 
242
 
 
243
static NTSTATUS close_remove_share_mode(files_struct *fsp,
 
244
                                        enum file_close_type close_type)
 
245
{
 
246
        connection_struct *conn = fsp->conn;
 
247
        bool delete_file = false;
 
248
        bool changed_user = false;
 
249
        struct share_mode_lock *lck;
 
250
        SMB_STRUCT_STAT sbuf;
 
251
        NTSTATUS status = NT_STATUS_OK;
 
252
        int ret;
 
253
        struct file_id id;
 
254
 
 
255
        /*
 
256
         * Lock the share entries, and determine if we should delete
 
257
         * on close. If so delete whilst the lock is still in effect.
 
258
         * This prevents race conditions with the file being created. JRA.
 
259
         */
 
260
 
 
261
        lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
 
262
                                  NULL);
 
263
 
 
264
        if (lck == NULL) {
 
265
                DEBUG(0, ("close_remove_share_mode: Could not get share mode "
 
266
                          "lock for file %s\n", fsp->fsp_name));
 
267
                return NT_STATUS_INVALID_PARAMETER;
 
268
        }
 
269
 
 
270
        if (fsp->write_time_forced) {
 
271
                set_close_write_time(fsp, lck->changed_write_time);
 
272
        }
 
273
 
 
274
        if (!del_share_mode(lck, fsp)) {
 
275
                DEBUG(0, ("close_remove_share_mode: Could not delete share "
 
276
                          "entry for file %s\n", fsp->fsp_name));
 
277
        }
 
278
 
 
279
        if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
 
280
                bool became_user = False;
 
281
 
 
282
                /* Initial delete on close was set and no one else
 
283
                 * wrote a real delete on close. */
 
284
 
 
285
                if (current_user.vuid != fsp->vuid) {
 
286
                        become_user(conn, fsp->vuid);
 
287
                        became_user = True;
 
288
                }
 
289
                set_delete_on_close_lck(lck, True, &current_user.ut);
 
290
                if (became_user) {
 
291
                        unbecome_user();
 
292
                }
 
293
        }
 
294
 
 
295
        delete_file = lck->delete_on_close;
 
296
 
 
297
        if (delete_file) {
 
298
                int i;
 
299
                /* See if others still have the file open. If this is the
 
300
                 * case, then don't delete. If all opens are POSIX delete now. */
 
301
                for (i=0; i<lck->num_share_modes; i++) {
 
302
                        struct share_mode_entry *e = &lck->share_modes[i];
 
303
                        if (is_valid_share_mode_entry(e)) {
 
304
                                if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
 
305
                                        continue;
 
306
                                }
 
307
                                delete_file = False;
 
308
                                break;
 
309
                        }
 
310
                }
 
311
        }
 
312
 
 
313
        /* Notify any deferred opens waiting on this close. */
 
314
        notify_deferred_opens(lck);
 
315
        reply_to_oplock_break_requests(fsp);
 
316
 
 
317
        /*
 
318
         * NT can set delete_on_close of the last open
 
319
         * reference to a file.
 
320
         */
 
321
 
 
322
        if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE)
 
323
            || !delete_file
 
324
            || (lck->delete_token == NULL)) {
 
325
                TALLOC_FREE(lck);
 
326
                return NT_STATUS_OK;
 
327
        }
 
328
 
 
329
        /*
 
330
         * Ok, we have to delete the file
 
331
         */
 
332
 
 
333
        DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
 
334
                 "- deleting file.\n", fsp->fsp_name));
 
335
 
 
336
        /*
 
337
         * Don't try to update the write time when we delete the file
 
338
         */
 
339
        fsp->update_write_time_on_close = false;
 
340
 
 
341
        if (!unix_token_equal(lck->delete_token, &current_user.ut)) {
 
342
                /* Become the user who requested the delete. */
 
343
 
 
344
                DEBUG(5,("close_remove_share_mode: file %s. "
 
345
                        "Change user to uid %u\n",
 
346
                        fsp->fsp_name,
 
347
                        (unsigned int)lck->delete_token->uid));
 
348
 
 
349
                if (!push_sec_ctx()) {
 
350
                        smb_panic("close_remove_share_mode: file %s. failed to push "
 
351
                                  "sec_ctx.\n");
 
352
                }
 
353
 
 
354
                set_sec_ctx(lck->delete_token->uid,
 
355
                            lck->delete_token->gid,
 
356
                            lck->delete_token->ngroups,
 
357
                            lck->delete_token->groups,
 
358
                            NULL);
 
359
 
 
360
                changed_user = true;
 
361
        }
 
362
 
 
363
        /* We can only delete the file if the name we have is still valid and
 
364
           hasn't been renamed. */
 
365
 
 
366
        if (fsp->posix_open) {
 
367
                ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
 
368
        } else {
 
369
                ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
 
370
        }
 
371
 
 
372
        if (ret != 0) {
 
373
                DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
 
374
                         "was set and stat failed with error %s\n",
 
375
                         fsp->fsp_name, strerror(errno) ));
 
376
                /*
 
377
                 * Don't save the errno here, we ignore this error
 
378
                 */
 
379
                goto done;
 
380
        }
 
381
 
 
382
        id = vfs_file_id_from_sbuf(conn, &sbuf);
 
383
 
 
384
        if (!file_id_equal(&fsp->file_id, &id)) {
 
385
                DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
 
386
                         "was set and dev and/or inode does not match\n",
 
387
                         fsp->fsp_name ));
 
388
                DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
 
389
                         "stat file_id %s\n",
 
390
                         fsp->fsp_name,
 
391
                         file_id_string_tos(&fsp->file_id),
 
392
                         file_id_string_tos(&id)));
 
393
                /*
 
394
                 * Don't save the errno here, we ignore this error
 
395
                 */
 
396
                goto done;
 
397
        }
 
398
 
 
399
        if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
 
400
            && !is_ntfs_stream_name(fsp->fsp_name)) {
 
401
 
 
402
                status = delete_all_streams(conn, fsp->fsp_name);
 
403
 
 
404
                if (!NT_STATUS_IS_OK(status)) {
 
405
                        DEBUG(5, ("delete_all_streams failed: %s\n",
 
406
                                  nt_errstr(status)));
 
407
                        goto done;
 
408
                }
 
409
        }
 
410
 
 
411
 
 
412
        if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
 
413
                /*
 
414
                 * This call can potentially fail as another smbd may
 
415
                 * have had the file open with delete on close set and
 
416
                 * deleted it when its last reference to this file
 
417
                 * went away. Hence we log this but not at debug level
 
418
                 * zero.
 
419
                 */
 
420
 
 
421
                DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
 
422
                         "was set and unlink failed with error %s\n",
 
423
                         fsp->fsp_name, strerror(errno) ));
 
424
 
 
425
                status = map_nt_error_from_unix(errno);
 
426
        }
 
427
 
 
428
        notify_fname(conn, NOTIFY_ACTION_REMOVED,
 
429
                     FILE_NOTIFY_CHANGE_FILE_NAME,
 
430
                     fsp->fsp_name);
 
431
 
 
432
        /* As we now have POSIX opens which can unlink
 
433
         * with other open files we may have taken
 
434
         * this code path with more than one share mode
 
435
         * entry - ensure we only delete once by resetting
 
436
         * the delete on close flag. JRA.
 
437
         */
 
438
 
 
439
        set_delete_on_close_lck(lck, False, NULL);
 
440
 
 
441
 done:
 
442
 
 
443
        if (changed_user) {
 
444
                /* unbecome user. */
 
445
                pop_sec_ctx();
 
446
        }
 
447
 
 
448
        TALLOC_FREE(lck);
 
449
        return status;
 
450
}
 
451
 
 
452
void set_close_write_time(struct files_struct *fsp, struct timespec ts)
 
453
{
 
454
        DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
 
455
 
 
456
        if (null_timespec(ts)) {
 
457
                return;
 
458
        }
 
459
        /*
 
460
         * if the write time on close is explict set, then don't
 
461
         * need to fix it up to the value in the locking db
 
462
         */
 
463
        fsp->write_time_forced = false;
 
464
 
 
465
        fsp->update_write_time_on_close = true;
 
466
        fsp->close_write_time = ts;
 
467
}
 
468
 
 
469
static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
 
470
{
 
471
        SMB_STRUCT_STAT sbuf;
 
472
        struct smb_file_time ft;
 
473
        NTSTATUS status;
 
474
        int ret = -1;
 
475
 
 
476
        ZERO_STRUCT(sbuf);
 
477
        ZERO_STRUCT(ft);
 
478
 
 
479
        if (!fsp->update_write_time_on_close) {
 
480
                return NT_STATUS_OK;
 
481
        }
 
482
 
 
483
        if (null_timespec(fsp->close_write_time)) {
 
484
                fsp->close_write_time = timespec_current();
 
485
        }
 
486
 
 
487
        /* Ensure we have a valid stat struct for the source. */
 
488
        if (fsp->fh->fd != -1) {
 
489
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
 
490
        } else {
 
491
                if (fsp->posix_open) {
 
492
                        ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf);
 
493
                } else {
 
494
                        ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf);
 
495
                }
 
496
        }
 
497
 
 
498
        if (ret == -1) {
 
499
                return map_nt_error_from_unix(errno);
 
500
        }
 
501
 
 
502
        if (!VALID_STAT(sbuf)) {
 
503
                /* if it doesn't seem to be a real file */
 
504
                return NT_STATUS_OK;
 
505
        }
 
506
 
 
507
        ft.mtime = fsp->close_write_time;
 
508
        status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name,
 
509
                                   &sbuf, &ft, true);
 
510
        if (!NT_STATUS_IS_OK(status)) {
 
511
                return status;
 
512
        }
 
513
 
 
514
        return NT_STATUS_OK;
 
515
}
 
516
 
 
517
/****************************************************************************
 
518
 Close a file.
 
519
 
 
520
 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
 
521
 printing and magic scripts are only run on normal close.
 
522
 delete on close is done on normal and shutdown close.
 
523
****************************************************************************/
 
524
 
 
525
static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
 
526
                                  enum file_close_type close_type)
 
527
{
 
528
        NTSTATUS status = NT_STATUS_OK;
 
529
        NTSTATUS saved_status1 = NT_STATUS_OK;
 
530
        NTSTATUS saved_status2 = NT_STATUS_OK;
 
531
        NTSTATUS saved_status3 = NT_STATUS_OK;
 
532
        NTSTATUS saved_status4 = NT_STATUS_OK;
 
533
        connection_struct *conn = fsp->conn;
 
534
 
 
535
        if (fsp->aio_write_behind) {
 
536
                /*
 
537
                 * If we're finishing write behind on a close we can get a write
 
538
                 * error here, we must remember this.
 
539
                 */
 
540
                int ret = wait_for_aio_completion(fsp);
 
541
                if (ret) {
 
542
                        saved_status1 = map_nt_error_from_unix(ret);
 
543
                }
 
544
        } else {
 
545
                cancel_aio_by_fsp(fsp);
 
546
        }
 
547
 
 
548
        /*
 
549
         * If we're flushing on a close we can get a write
 
550
         * error here, we must remember this.
 
551
         */
 
552
 
 
553
        saved_status2 = close_filestruct(fsp);
 
554
 
 
555
        if (fsp->print_file) {
 
556
                print_fsp_end(fsp, close_type);
 
557
                file_free(req, fsp);
 
558
                return NT_STATUS_OK;
 
559
        }
 
560
 
 
561
        /* Remove the oplock before potentially deleting the file. */
 
562
        if(fsp->oplock_type) {
 
563
                release_file_oplock(fsp);
 
564
        }
 
565
 
 
566
        /* If this is an old DOS or FCB open and we have multiple opens on
 
567
           the same handle we only have one share mode. Ensure we only remove
 
568
           the share mode on the last close. */
 
569
 
 
570
        if (fsp->fh->ref_count == 1) {
 
571
                /* Should we return on error here... ? */
 
572
                saved_status3 = close_remove_share_mode(fsp, close_type);
 
573
        }
 
574
 
 
575
        locking_close_file(smbd_messaging_context(), fsp);
 
576
 
 
577
        status = fd_close(fsp);
 
578
 
 
579
        /* check for magic scripts */
 
580
        if (close_type == NORMAL_CLOSE) {
 
581
                check_magic(fsp);
 
582
        }
 
583
 
 
584
        /*
 
585
         * Ensure pending modtime is set after close.
 
586
         */
 
587
 
 
588
        saved_status4 = update_write_time_on_close(fsp);
 
589
        if (NT_STATUS_EQUAL(saved_status4, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
 
590
                /* Someone renamed the file or a parent directory containing
 
591
                 * this file. We can't do anything about this, we don't have
 
592
                 * an "update timestamp by fd" call in POSIX. Eat the error. */
 
593
 
 
594
                saved_status4 = NT_STATUS_OK;
 
595
        }
 
596
 
 
597
        if (NT_STATUS_IS_OK(status)) {
 
598
                if (!NT_STATUS_IS_OK(saved_status1)) {
 
599
                        status = saved_status1;
 
600
                } else if (!NT_STATUS_IS_OK(saved_status2)) {
 
601
                        status = saved_status2;
 
602
                } else if (!NT_STATUS_IS_OK(saved_status3)) {
 
603
                        status = saved_status3;
 
604
                } else if (!NT_STATUS_IS_OK(saved_status4)) {
 
605
                        status = saved_status4;
 
606
                }
 
607
        }
 
608
 
 
609
        DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
 
610
                conn->server_info->unix_name,fsp->fsp_name,
 
611
                conn->num_files_open - 1,
 
612
                nt_errstr(status) ));
 
613
 
 
614
        file_free(req, fsp);
 
615
        return status;
 
616
}
 
617
 
 
618
/****************************************************************************
 
619
 Close a directory opened by an NT SMB call. 
 
620
****************************************************************************/
 
621
  
 
622
static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
 
623
                                enum file_close_type close_type)
 
624
{
 
625
        struct share_mode_lock *lck = 0;
 
626
        bool delete_dir = False;
 
627
        NTSTATUS status = NT_STATUS_OK;
 
628
 
 
629
        /*
 
630
         * NT can set delete_on_close of the last open
 
631
         * reference to a directory also.
 
632
         */
 
633
 
 
634
        lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
 
635
                                  NULL);
 
636
 
 
637
        if (lck == NULL) {
 
638
                DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
 
639
                return NT_STATUS_INVALID_PARAMETER;
 
640
        }
 
641
 
 
642
        if (!del_share_mode(lck, fsp)) {
 
643
                DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
 
644
        }
 
645
 
 
646
        if (fsp->initial_delete_on_close) {
 
647
                bool became_user = False;
 
648
 
 
649
                /* Initial delete on close was set - for
 
650
                 * directories we don't care if anyone else
 
651
                 * wrote a real delete on close. */
 
652
 
 
653
                if (current_user.vuid != fsp->vuid) {
 
654
                        become_user(fsp->conn, fsp->vuid);
 
655
                        became_user = True;
 
656
                }
 
657
                send_stat_cache_delete_message(fsp->fsp_name);
 
658
                set_delete_on_close_lck(lck, True, &current_user.ut);
 
659
                if (became_user) {
 
660
                        unbecome_user();
 
661
                }
 
662
        }
 
663
 
 
664
        delete_dir = lck->delete_on_close;
 
665
 
 
666
        if (delete_dir) {
 
667
                int i;
 
668
                /* See if others still have the dir open. If this is the
 
669
                 * case, then don't delete. If all opens are POSIX delete now. */
 
670
                for (i=0; i<lck->num_share_modes; i++) {
 
671
                        struct share_mode_entry *e = &lck->share_modes[i];
 
672
                        if (is_valid_share_mode_entry(e)) {
 
673
                                if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
 
674
                                        continue;
 
675
                                }
 
676
                                delete_dir = False;
 
677
                                break;
 
678
                        }
 
679
                }
 
680
        }
 
681
 
 
682
        if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
 
683
                                delete_dir &&
 
684
                                lck->delete_token) {
 
685
        
 
686
                /* Become the user who requested the delete. */
 
687
 
 
688
                if (!push_sec_ctx()) {
 
689
                        smb_panic("close_directory: failed to push sec_ctx.\n");
 
690
                }
 
691
 
 
692
                set_sec_ctx(lck->delete_token->uid,
 
693
                                lck->delete_token->gid,
 
694
                                lck->delete_token->ngroups,
 
695
                                lck->delete_token->groups,
 
696
                                NULL);
 
697
 
 
698
                TALLOC_FREE(lck);
 
699
 
 
700
                status = rmdir_internals(talloc_tos(),
 
701
                                fsp->conn, fsp->fsp_name);
 
702
 
 
703
                DEBUG(5,("close_directory: %s. Delete on close was set - "
 
704
                         "deleting directory returned %s.\n",
 
705
                         fsp->fsp_name, nt_errstr(status)));
 
706
 
 
707
                /* unbecome user. */
 
708
                pop_sec_ctx();
 
709
 
 
710
                /*
 
711
                 * Ensure we remove any change notify requests that would
 
712
                 * now fail as the directory has been deleted.
 
713
                 */
 
714
 
 
715
                if(NT_STATUS_IS_OK(status)) {
 
716
                        remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
 
717
                }
 
718
        } else {
 
719
                TALLOC_FREE(lck);
 
720
                remove_pending_change_notify_requests_by_fid(
 
721
                        fsp, NT_STATUS_OK);
 
722
        }
 
723
 
 
724
        status = fd_close(fsp);
 
725
 
 
726
        if (!NT_STATUS_IS_OK(status)) {
 
727
                DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
 
728
                          fsp->fsp_name, fsp->fh->fd, errno, strerror(errno)));
 
729
        }
 
730
 
 
731
        /*
 
732
         * Do the code common to files and directories.
 
733
         */
 
734
        close_filestruct(fsp);
 
735
        file_free(req, fsp);
 
736
        return status;
 
737
}
 
738
 
 
739
/****************************************************************************
 
740
 Close a files_struct.
 
741
****************************************************************************/
 
742
  
 
743
NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
 
744
                    enum file_close_type close_type)
 
745
{
 
746
        NTSTATUS status;
 
747
        struct files_struct *base_fsp = fsp->base_fsp;
 
748
 
 
749
        if(fsp->is_directory) {
 
750
                status = close_directory(req, fsp, close_type);
 
751
        } else if (fsp->fake_file_handle != NULL) {
 
752
                status = close_fake_file(req, fsp);
 
753
        } else {
 
754
                status = close_normal_file(req, fsp, close_type);
 
755
        }
 
756
 
 
757
        if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
 
758
 
 
759
                /*
 
760
                 * fsp was a stream, the base fsp can't be a stream as well
 
761
                 *
 
762
                 * For SHUTDOWN_CLOSE this is not possible here, because
 
763
                 * SHUTDOWN_CLOSE only happens from files.c which walks the
 
764
                 * complete list of files. If we mess with more than one fsp
 
765
                 * those loops will become confused.
 
766
                 */
 
767
 
 
768
                SMB_ASSERT(base_fsp->base_fsp == NULL);
 
769
                close_file(req, base_fsp, close_type);
 
770
        }
 
771
 
 
772
        return status;
 
773
}
 
774
 
 
775
/****************************************************************************
 
776
 Deal with an (authorized) message to close a file given the share mode
 
777
 entry.
 
778
****************************************************************************/
 
779
 
 
780
void msg_close_file(struct messaging_context *msg_ctx,
 
781
                        void *private_data,
 
782
                        uint32_t msg_type,
 
783
                        struct server_id server_id,
 
784
                        DATA_BLOB *data)
 
785
{
 
786
        files_struct *fsp = NULL;
 
787
        struct share_mode_entry e;
 
788
 
 
789
        message_to_share_mode_entry(&e, (char *)data->data);
 
790
 
 
791
        if(DEBUGLVL(10)) {
 
792
                char *sm_str = share_mode_str(NULL, 0, &e);
 
793
                if (!sm_str) {
 
794
                        smb_panic("talloc failed");
 
795
                }
 
796
                DEBUG(10,("msg_close_file: got request to close share mode "
 
797
                        "entry %s\n", sm_str));
 
798
                TALLOC_FREE(sm_str);
 
799
        }
 
800
 
 
801
        fsp = file_find_dif(e.id, e.share_file_id);
 
802
        if (!fsp) {
 
803
                DEBUG(10,("msg_close_file: failed to find file.\n"));
 
804
                return;
 
805
        }
 
806
        close_file(NULL, fsp, NORMAL_CLOSE);
 
807
}