~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/smbd/files.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
   Files[] structure handling
 
4
   Copyright (C) Andrew Tridgell 1998
 
5
   
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
 
10
   
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
   
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "smbd/globals.h"
 
22
 
 
23
#define VALID_FNUM(fnum)   (((fnum) >= 0) && ((fnum) < real_max_open_files))
 
24
 
 
25
#define FILE_HANDLE_OFFSET 0x1000
 
26
 
 
27
/****************************************************************************
 
28
 Return a unique number identifying this fsp over the life of this pid.
 
29
****************************************************************************/
 
30
 
 
31
static unsigned long get_gen_count(void)
 
32
{
 
33
        if ((++file_gen_counter) == 0)
 
34
                return ++file_gen_counter;
 
35
        return file_gen_counter;
 
36
}
 
37
 
 
38
/****************************************************************************
 
39
 Find first available file slot.
 
40
****************************************************************************/
 
41
 
 
42
NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
 
43
                  files_struct **result)
 
44
{
 
45
        int i;
 
46
        files_struct *fsp;
 
47
 
 
48
        /* we want to give out file handles differently on each new
 
49
           connection because of a common bug in MS clients where they try to
 
50
           reuse a file descriptor from an earlier smb connection. This code
 
51
           increases the chance that the errant client will get an error rather
 
52
           than causing corruption */
 
53
        if (first_file == 0) {
 
54
                first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
 
55
        }
 
56
 
 
57
        /* TODO: Port the id-tree implementation from Samba4 */
 
58
 
 
59
        i = bitmap_find(file_bmap, first_file);
 
60
        if (i == -1) {
 
61
                DEBUG(0,("ERROR! Out of file structures\n"));
 
62
                /* TODO: We have to unconditionally return a DOS error here,
 
63
                 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
 
64
                 * NTSTATUS negotiated */
 
65
                return NT_STATUS_TOO_MANY_OPENED_FILES;
 
66
        }
 
67
 
 
68
        fsp = SMB_MALLOC_P(files_struct);
 
69
        if (!fsp) {
 
70
                return NT_STATUS_NO_MEMORY;
 
71
        }
 
72
 
 
73
        ZERO_STRUCTP(fsp);
 
74
 
 
75
        fsp->fh = SMB_MALLOC_P(struct fd_handle);
 
76
        if (!fsp->fh) {
 
77
                SAFE_FREE(fsp);
 
78
                return NT_STATUS_NO_MEMORY;
 
79
        }
 
80
 
 
81
        ZERO_STRUCTP(fsp->fh);
 
82
 
 
83
        fsp->fh->ref_count = 1;
 
84
        fsp->fh->fd = -1;
 
85
 
 
86
        fsp->conn = conn;
 
87
        fsp->fh->gen_id = get_gen_count();
 
88
        GetTimeOfDay(&fsp->open_time);
 
89
 
 
90
        first_file = (i+1) % real_max_open_files;
 
91
 
 
92
        bitmap_set(file_bmap, i);
 
93
        files_used++;
 
94
 
 
95
        fsp->fnum = i + FILE_HANDLE_OFFSET;
 
96
        SMB_ASSERT(fsp->fnum < 65536);
 
97
 
 
98
        string_set(&fsp->fsp_name,"");
 
99
        
 
100
        DLIST_ADD(Files, fsp);
 
101
 
 
102
        DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
 
103
                 i, fsp->fnum, files_used));
 
104
 
 
105
        if (req != NULL) {
 
106
                req->chain_fsp = fsp;
 
107
        }
 
108
 
 
109
        /* A new fsp invalidates the positive and
 
110
          negative fsp_fi_cache as the new fsp is pushed
 
111
          at the start of the list and we search from
 
112
          a cache hit to the *end* of the list. */
 
113
 
 
114
        ZERO_STRUCT(fsp_fi_cache);
 
115
 
 
116
        conn->num_files_open++;
 
117
 
 
118
        *result = fsp;
 
119
        return NT_STATUS_OK;
 
120
}
 
121
 
 
122
/****************************************************************************
 
123
 Close all open files for a connection.
 
124
****************************************************************************/
 
125
 
 
126
void file_close_conn(connection_struct *conn)
 
127
{
 
128
        files_struct *fsp, *next;
 
129
        
 
130
        for (fsp=Files;fsp;fsp=next) {
 
131
                next = fsp->next;
 
132
                if (fsp->conn == conn) {
 
133
                        close_file(NULL, fsp, SHUTDOWN_CLOSE);
 
134
                }
 
135
        }
 
136
}
 
137
 
 
138
/****************************************************************************
 
139
 Close all open files for a pid and a vuid.
 
140
****************************************************************************/
 
141
 
 
142
void file_close_pid(uint16 smbpid, int vuid)
 
143
{
 
144
        files_struct *fsp, *next;
 
145
        
 
146
        for (fsp=Files;fsp;fsp=next) {
 
147
                next = fsp->next;
 
148
                if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
 
149
                        close_file(NULL, fsp, SHUTDOWN_CLOSE);
 
150
                }
 
151
        }
 
152
}
 
153
 
 
154
/****************************************************************************
 
155
 Initialise file structures.
 
156
****************************************************************************/
 
157
 
 
158
void file_init(void)
 
159
{
 
160
        int request_max_open_files = lp_max_open_files();
 
161
        int real_lim;
 
162
 
 
163
        /*
 
164
         * Set the max_open files to be the requested
 
165
         * max plus a fudgefactor to allow for the extra
 
166
         * fd's we need such as log files etc...
 
167
         */
 
168
        real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
 
169
 
 
170
        real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
 
171
 
 
172
        if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536)
 
173
                real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
 
174
 
 
175
        if(real_max_open_files != request_max_open_files) {
 
176
                DEBUG(1,("file_init: Information only: requested %d \
 
177
open files, %d are available.\n", request_max_open_files, real_max_open_files));
 
178
        }
 
179
 
 
180
        SMB_ASSERT(real_max_open_files > 100);
 
181
 
 
182
        file_bmap = bitmap_allocate(real_max_open_files);
 
183
        
 
184
        if (!file_bmap) {
 
185
                exit_server("out of memory in file_init");
 
186
        }
 
187
}
 
188
 
 
189
/****************************************************************************
 
190
 Close files open by a specified vuid.
 
191
****************************************************************************/
 
192
 
 
193
void file_close_user(int vuid)
 
194
{
 
195
        files_struct *fsp, *next;
 
196
 
 
197
        for (fsp=Files;fsp;fsp=next) {
 
198
                next=fsp->next;
 
199
                if (fsp->vuid == vuid) {
 
200
                        close_file(NULL, fsp, SHUTDOWN_CLOSE);
 
201
                }
 
202
        }
 
203
}
 
204
 
 
205
/*
 
206
 * Walk the files table until "fn" returns non-NULL
 
207
 */
 
208
 
 
209
struct files_struct *file_walk_table(
 
210
        struct files_struct *(*fn)(struct files_struct *fsp,
 
211
                                   void *private_data),
 
212
        void *private_data)
 
213
{
 
214
        struct files_struct *fsp, *next;
 
215
 
 
216
        for (fsp = Files; fsp; fsp = next) {
 
217
                struct files_struct *ret;
 
218
                next = fsp->next;
 
219
                ret = fn(fsp, private_data);
 
220
                if (ret != NULL) {
 
221
                        return ret;
 
222
                }
 
223
        }
 
224
        return NULL;
 
225
}
 
226
 
 
227
/****************************************************************************
 
228
 Debug to enumerate all open files in the smbd.
 
229
****************************************************************************/
 
230
 
 
231
void file_dump_open_table(void)
 
232
{
 
233
        int count=0;
 
234
        files_struct *fsp;
 
235
 
 
236
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
 
237
                DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n",
 
238
                        count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id,
 
239
                          file_id_string_tos(&fsp->file_id)));
 
240
        }
 
241
}
 
242
 
 
243
/****************************************************************************
 
244
 Find a fsp given a file descriptor.
 
245
****************************************************************************/
 
246
 
 
247
files_struct *file_find_fd(int fd)
 
248
{
 
249
        int count=0;
 
250
        files_struct *fsp;
 
251
 
 
252
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
 
253
                if (fsp->fh->fd == fd) {
 
254
                        if (count > 10) {
 
255
                                DLIST_PROMOTE(Files, fsp);
 
256
                        }
 
257
                        return fsp;
 
258
                }
 
259
        }
 
260
 
 
261
        return NULL;
 
262
}
 
263
 
 
264
/****************************************************************************
 
265
 Find a fsp given a device, inode and file_id.
 
266
****************************************************************************/
 
267
 
 
268
files_struct *file_find_dif(struct file_id id, unsigned long gen_id)
 
269
{
 
270
        int count=0;
 
271
        files_struct *fsp;
 
272
 
 
273
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
 
274
                /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
 
275
                if (file_id_equal(&fsp->file_id, &id) &&
 
276
                    fsp->fh->gen_id == gen_id ) {
 
277
                        if (count > 10) {
 
278
                                DLIST_PROMOTE(Files, fsp);
 
279
                        }
 
280
                        /* Paranoia check. */
 
281
                        if ((fsp->fh->fd == -1) &&
 
282
                            (fsp->oplock_type != NO_OPLOCK) &&
 
283
                            (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
 
284
                                DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \
 
285
oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, 
 
286
                                         file_id_string_tos(&fsp->file_id),
 
287
                                         (unsigned int)fsp->fh->gen_id,
 
288
                                         (unsigned int)fsp->oplock_type ));
 
289
                                smb_panic("file_find_dif");
 
290
                        }
 
291
                        return fsp;
 
292
                }
 
293
        }
 
294
 
 
295
        return NULL;
 
296
}
 
297
 
 
298
/****************************************************************************
 
299
 Check if an fsp still exists.
 
300
****************************************************************************/
 
301
 
 
302
files_struct *file_find_fsp(files_struct *orig_fsp)
 
303
{
 
304
        files_struct *fsp;
 
305
 
 
306
        for (fsp=Files;fsp;fsp=fsp->next) {
 
307
                if (fsp == orig_fsp)
 
308
                        return fsp;
 
309
        }
 
310
 
 
311
        return NULL;
 
312
}
 
313
 
 
314
/****************************************************************************
 
315
 Find the first fsp given a device and inode.
 
316
 We use a singleton cache here to speed up searching from getfilepathinfo
 
317
 calls.
 
318
****************************************************************************/
 
319
 
 
320
files_struct *file_find_di_first(struct file_id id)
 
321
{
 
322
        files_struct *fsp;
 
323
 
 
324
        if (file_id_equal(&fsp_fi_cache.id, &id)) {
 
325
                /* Positive or negative cache hit. */
 
326
                return fsp_fi_cache.fsp;
 
327
        }
 
328
 
 
329
        fsp_fi_cache.id = id;
 
330
 
 
331
        for (fsp=Files;fsp;fsp=fsp->next) {
 
332
                if (file_id_equal(&fsp->file_id, &id)) {
 
333
                        /* Setup positive cache. */
 
334
                        fsp_fi_cache.fsp = fsp;
 
335
                        return fsp;
 
336
                }
 
337
        }
 
338
 
 
339
        /* Setup negative cache. */
 
340
        fsp_fi_cache.fsp = NULL;
 
341
        return NULL;
 
342
}
 
343
 
 
344
/****************************************************************************
 
345
 Find the next fsp having the same device and inode.
 
346
****************************************************************************/
 
347
 
 
348
files_struct *file_find_di_next(files_struct *start_fsp)
 
349
{
 
350
        files_struct *fsp;
 
351
 
 
352
        for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
 
353
                if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
 
354
                        return fsp;
 
355
                }
 
356
        }
 
357
 
 
358
        return NULL;
 
359
}
 
360
 
 
361
/****************************************************************************
 
362
 Find a fsp that is open for printing.
 
363
****************************************************************************/
 
364
 
 
365
files_struct *file_find_print(void)
 
366
{
 
367
        files_struct *fsp;
 
368
 
 
369
        for (fsp=Files;fsp;fsp=fsp->next) {
 
370
                if (fsp->print_file) {
 
371
                        return fsp;
 
372
                }
 
373
        } 
 
374
 
 
375
        return NULL;
 
376
}
 
377
 
 
378
/****************************************************************************
 
379
 Find any fsp open with a pathname below that of an already open path.
 
380
****************************************************************************/
 
381
 
 
382
bool file_find_subpath(files_struct *dir_fsp)
 
383
{
 
384
        files_struct *fsp;
 
385
        size_t dlen;
 
386
        char *d_fullname = talloc_asprintf(talloc_tos(),
 
387
                                        "%s/%s",
 
388
                                        dir_fsp->conn->connectpath,
 
389
                                        dir_fsp->fsp_name);
 
390
        if (!d_fullname) {
 
391
                return false;
 
392
        }
 
393
 
 
394
        dlen = strlen(d_fullname);
 
395
 
 
396
        for (fsp=Files;fsp;fsp=fsp->next) {
 
397
                char *d1_fullname;
 
398
 
 
399
                if (fsp == dir_fsp) {
 
400
                        continue;
 
401
                }
 
402
 
 
403
                d1_fullname = talloc_asprintf(talloc_tos(),
 
404
                                        "%s/%s",
 
405
                                        fsp->conn->connectpath,
 
406
                                        fsp->fsp_name);
 
407
 
 
408
                /*
 
409
                 * If the open file has a path that is a longer
 
410
                 * component, then it's a subpath.
 
411
                 */
 
412
                if (strnequal(d_fullname, d1_fullname, dlen) &&
 
413
                                (d1_fullname[dlen] == '/')) {
 
414
                        TALLOC_FREE(d1_fullname);
 
415
                        TALLOC_FREE(d_fullname);
 
416
                        return true;
 
417
                }
 
418
                TALLOC_FREE(d1_fullname);
 
419
        }
 
420
 
 
421
        TALLOC_FREE(d_fullname);
 
422
        return false;
 
423
}
 
424
 
 
425
/****************************************************************************
 
426
 Sync open files on a connection.
 
427
****************************************************************************/
 
428
 
 
429
void file_sync_all(connection_struct *conn)
 
430
{
 
431
        files_struct *fsp, *next;
 
432
 
 
433
        for (fsp=Files;fsp;fsp=next) {
 
434
                next=fsp->next;
 
435
                if ((conn == fsp->conn) && (fsp->fh->fd != -1)) {
 
436
                        sync_file(conn, fsp, True /* write through */);
 
437
                }
 
438
        }
 
439
}
 
440
 
 
441
/****************************************************************************
 
442
 Free up a fsp.
 
443
****************************************************************************/
 
444
 
 
445
void file_free(struct smb_request *req, files_struct *fsp)
 
446
{
 
447
        DLIST_REMOVE(Files, fsp);
 
448
 
 
449
        string_free(&fsp->fsp_name);
 
450
 
 
451
        TALLOC_FREE(fsp->fake_file_handle);
 
452
 
 
453
        if (fsp->fh->ref_count == 1) {
 
454
                SAFE_FREE(fsp->fh);
 
455
        } else {
 
456
                fsp->fh->ref_count--;
 
457
        }
 
458
 
 
459
        if (fsp->notify) {
 
460
                notify_remove(fsp->conn->notify_ctx, fsp);
 
461
                TALLOC_FREE(fsp->notify);
 
462
        }
 
463
 
 
464
        /* Ensure this event will never fire. */
 
465
        TALLOC_FREE(fsp->oplock_timeout);
 
466
 
 
467
        /* Ensure this event will never fire. */
 
468
        TALLOC_FREE(fsp->update_write_time_event);
 
469
 
 
470
        bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
 
471
        files_used--;
 
472
 
 
473
        DEBUG(5,("freed files structure %d (%d used)\n",
 
474
                 fsp->fnum, files_used));
 
475
 
 
476
        fsp->conn->num_files_open--;
 
477
 
 
478
        if ((req != NULL) && (fsp == req->chain_fsp)) {
 
479
                req->chain_fsp = NULL;
 
480
        }
 
481
 
 
482
        /* Closing a file can invalidate the positive cache. */
 
483
        if (fsp == fsp_fi_cache.fsp) {
 
484
                ZERO_STRUCT(fsp_fi_cache);
 
485
        }
 
486
 
 
487
        /* Drop all remaining extensions. */
 
488
        while (fsp->vfs_extension) {
 
489
                vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp);
 
490
        }
 
491
 
 
492
        /* this is paranoia, just in case someone tries to reuse the
 
493
           information */
 
494
        ZERO_STRUCTP(fsp);
 
495
 
 
496
        SAFE_FREE(fsp);
 
497
}
 
498
 
 
499
/****************************************************************************
 
500
 Get an fsp from a 16 bit fnum.
 
501
****************************************************************************/
 
502
 
 
503
files_struct *file_fnum(uint16 fnum)
 
504
{
 
505
        files_struct *fsp;
 
506
        int count=0;
 
507
 
 
508
        for (fsp=Files;fsp;fsp=fsp->next, count++) {
 
509
                if (fsp->fnum == fnum) {
 
510
                        if (count > 10) {
 
511
                                DLIST_PROMOTE(Files, fsp);
 
512
                        }
 
513
                        return fsp;
 
514
                }
 
515
        }
 
516
        return NULL;
 
517
}
 
518
 
 
519
/****************************************************************************
 
520
 Get an fsp from a packet given the offset of a 16 bit fnum.
 
521
****************************************************************************/
 
522
 
 
523
files_struct *file_fsp(struct smb_request *req, uint16 fid)
 
524
{
 
525
        files_struct *fsp;
 
526
 
 
527
        if ((req != NULL) && (req->chain_fsp != NULL)) {
 
528
                return req->chain_fsp;
 
529
        }
 
530
 
 
531
        fsp = file_fnum(fid);
 
532
        if ((fsp != NULL) && (req != NULL)) {
 
533
                req->chain_fsp = fsp;
 
534
        }
 
535
        return fsp;
 
536
}
 
537
 
 
538
/****************************************************************************
 
539
 Duplicate the file handle part for a DOS or FCB open.
 
540
****************************************************************************/
 
541
 
 
542
void dup_file_fsp(struct smb_request *req, files_struct *from,
 
543
                      uint32 access_mask, uint32 share_access,
 
544
                      uint32 create_options, files_struct *to)
 
545
{
 
546
        SAFE_FREE(to->fh);
 
547
 
 
548
        to->fh = from->fh;
 
549
        to->fh->ref_count++;
 
550
 
 
551
        to->file_id = from->file_id;
 
552
        to->initial_allocation_size = from->initial_allocation_size;
 
553
        to->mode = from->mode;
 
554
        to->file_pid = from->file_pid;
 
555
        to->vuid = from->vuid;
 
556
        to->open_time = from->open_time;
 
557
        to->access_mask = access_mask;
 
558
        to->share_access = share_access;
 
559
        to->oplock_type = from->oplock_type;
 
560
        to->can_lock = from->can_lock;
 
561
        to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
 
562
        if (!CAN_WRITE(from->conn)) {
 
563
                to->can_write = False;
 
564
        } else {
 
565
                to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
 
566
        }
 
567
        to->print_file = from->print_file;
 
568
        to->modified = from->modified;
 
569
        to->is_directory = from->is_directory;
 
570
        to->aio_write_behind = from->aio_write_behind;
 
571
        string_set(&to->fsp_name,from->fsp_name);
 
572
}