s3: Change file_structs to be allocated with talloc instead of malloc
[ira/wip.git] / source3 / smbd / files.c
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         /*
69          * Make a child of the connection_struct as an fsp can't exist
70          * indepenedent of a connection.
71          */
72         fsp = talloc_zero(conn, struct files_struct);
73         if (!fsp) {
74                 return NT_STATUS_NO_MEMORY;
75         }
76
77         /*
78          * This can't be a child of fsp because the file_handle can be ref'd
79          * when doing a dos/fcb open, which will then share the file_handle
80          * across multiple fsps.
81          */
82         fsp->fh = talloc_zero(conn, struct fd_handle);
83         if (!fsp->fh) {
84                 TALLOC_FREE(fsp);
85                 return NT_STATUS_NO_MEMORY;
86         }
87
88         fsp->fh->ref_count = 1;
89         fsp->fh->fd = -1;
90
91         fsp->conn = conn;
92         fsp->fh->gen_id = get_gen_count();
93         GetTimeOfDay(&fsp->open_time);
94
95         first_file = (i+1) % real_max_open_files;
96
97         bitmap_set(file_bmap, i);
98         files_used++;
99
100         fsp->fnum = i + FILE_HANDLE_OFFSET;
101         SMB_ASSERT(fsp->fnum < 65536);
102
103         string_set(&fsp->fsp_name,"");
104         
105         DLIST_ADD(Files, fsp);
106
107         DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
108                  i, fsp->fnum, files_used));
109
110         if (req != NULL) {
111                 req->chain_fsp = fsp;
112         }
113
114         /* A new fsp invalidates the positive and
115           negative fsp_fi_cache as the new fsp is pushed
116           at the start of the list and we search from
117           a cache hit to the *end* of the list. */
118
119         ZERO_STRUCT(fsp_fi_cache);
120
121         conn->num_files_open++;
122
123         *result = fsp;
124         return NT_STATUS_OK;
125 }
126
127 /****************************************************************************
128  Close all open files for a connection.
129 ****************************************************************************/
130
131 void file_close_conn(connection_struct *conn)
132 {
133         files_struct *fsp, *next;
134         
135         for (fsp=Files;fsp;fsp=next) {
136                 next = fsp->next;
137                 if (fsp->conn == conn) {
138                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
139                 }
140         }
141 }
142
143 /****************************************************************************
144  Close all open files for a pid and a vuid.
145 ****************************************************************************/
146
147 void file_close_pid(uint16 smbpid, int vuid)
148 {
149         files_struct *fsp, *next;
150         
151         for (fsp=Files;fsp;fsp=next) {
152                 next = fsp->next;
153                 if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
154                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
155                 }
156         }
157 }
158
159 /****************************************************************************
160  Initialise file structures.
161 ****************************************************************************/
162
163 #define MAX_OPEN_FUDGEFACTOR 20
164
165 void file_init(void)
166 {
167         int request_max_open_files = lp_max_open_files();
168         int real_lim;
169
170         /*
171          * Set the max_open files to be the requested
172          * max plus a fudgefactor to allow for the extra
173          * fd's we need such as log files etc...
174          */
175         real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
176
177         real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
178
179         if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536)
180                 real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
181
182         if(real_max_open_files != request_max_open_files) {
183                 DEBUG(1,("file_init: Information only: requested %d \
184 open files, %d are available.\n", request_max_open_files, real_max_open_files));
185         }
186
187         SMB_ASSERT(real_max_open_files > 100);
188
189         file_bmap = bitmap_allocate(real_max_open_files);
190         
191         if (!file_bmap) {
192                 exit_server("out of memory in file_init");
193         }
194 }
195
196 /****************************************************************************
197  Close files open by a specified vuid.
198 ****************************************************************************/
199
200 void file_close_user(int vuid)
201 {
202         files_struct *fsp, *next;
203
204         for (fsp=Files;fsp;fsp=next) {
205                 next=fsp->next;
206                 if (fsp->vuid == vuid) {
207                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
208                 }
209         }
210 }
211
212 /*
213  * Walk the files table until "fn" returns non-NULL
214  */
215
216 struct files_struct *file_walk_table(
217         struct files_struct *(*fn)(struct files_struct *fsp,
218                                    void *private_data),
219         void *private_data)
220 {
221         struct files_struct *fsp, *next;
222
223         for (fsp = Files; fsp; fsp = next) {
224                 struct files_struct *ret;
225                 next = fsp->next;
226                 ret = fn(fsp, private_data);
227                 if (ret != NULL) {
228                         return ret;
229                 }
230         }
231         return NULL;
232 }
233
234 /****************************************************************************
235  Debug to enumerate all open files in the smbd.
236 ****************************************************************************/
237
238 void file_dump_open_table(void)
239 {
240         int count=0;
241         files_struct *fsp;
242
243         for (fsp=Files;fsp;fsp=fsp->next,count++) {
244                 DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n",
245                         count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id,
246                           file_id_string_tos(&fsp->file_id)));
247         }
248 }
249
250 /****************************************************************************
251  Find a fsp given a file descriptor.
252 ****************************************************************************/
253
254 files_struct *file_find_fd(int fd)
255 {
256         int count=0;
257         files_struct *fsp;
258
259         for (fsp=Files;fsp;fsp=fsp->next,count++) {
260                 if (fsp->fh->fd == fd) {
261                         if (count > 10) {
262                                 DLIST_PROMOTE(Files, fsp);
263                         }
264                         return fsp;
265                 }
266         }
267
268         return NULL;
269 }
270
271 /****************************************************************************
272  Find a fsp given a device, inode and file_id.
273 ****************************************************************************/
274
275 files_struct *file_find_dif(struct file_id id, unsigned long gen_id)
276 {
277         int count=0;
278         files_struct *fsp;
279
280         for (fsp=Files;fsp;fsp=fsp->next,count++) {
281                 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
282                 if (file_id_equal(&fsp->file_id, &id) &&
283                     fsp->fh->gen_id == gen_id ) {
284                         if (count > 10) {
285                                 DLIST_PROMOTE(Files, fsp);
286                         }
287                         /* Paranoia check. */
288                         if ((fsp->fh->fd == -1) &&
289                             (fsp->oplock_type != NO_OPLOCK) &&
290                             (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
291                                 DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \
292 oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, 
293                                          file_id_string_tos(&fsp->file_id),
294                                          (unsigned int)fsp->fh->gen_id,
295                                          (unsigned int)fsp->oplock_type ));
296                                 smb_panic("file_find_dif");
297                         }
298                         return fsp;
299                 }
300         }
301
302         return NULL;
303 }
304
305 /****************************************************************************
306  Check if an fsp still exists.
307 ****************************************************************************/
308
309 files_struct *file_find_fsp(files_struct *orig_fsp)
310 {
311         files_struct *fsp;
312
313         for (fsp=Files;fsp;fsp=fsp->next) {
314                 if (fsp == orig_fsp)
315                         return fsp;
316         }
317
318         return NULL;
319 }
320
321 /****************************************************************************
322  Find the first fsp given a device and inode.
323  We use a singleton cache here to speed up searching from getfilepathinfo
324  calls.
325 ****************************************************************************/
326
327 files_struct *file_find_di_first(struct file_id id)
328 {
329         files_struct *fsp;
330
331         if (file_id_equal(&fsp_fi_cache.id, &id)) {
332                 /* Positive or negative cache hit. */
333                 return fsp_fi_cache.fsp;
334         }
335
336         fsp_fi_cache.id = id;
337
338         for (fsp=Files;fsp;fsp=fsp->next) {
339                 if (file_id_equal(&fsp->file_id, &id)) {
340                         /* Setup positive cache. */
341                         fsp_fi_cache.fsp = fsp;
342                         return fsp;
343                 }
344         }
345
346         /* Setup negative cache. */
347         fsp_fi_cache.fsp = NULL;
348         return NULL;
349 }
350
351 /****************************************************************************
352  Find the next fsp having the same device and inode.
353 ****************************************************************************/
354
355 files_struct *file_find_di_next(files_struct *start_fsp)
356 {
357         files_struct *fsp;
358
359         for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
360                 if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
361                         return fsp;
362                 }
363         }
364
365         return NULL;
366 }
367
368 /****************************************************************************
369  Find a fsp that is open for printing.
370 ****************************************************************************/
371
372 files_struct *file_find_print(void)
373 {
374         files_struct *fsp;
375
376         for (fsp=Files;fsp;fsp=fsp->next) {
377                 if (fsp->print_file) {
378                         return fsp;
379                 }
380         } 
381
382         return NULL;
383 }
384
385 /****************************************************************************
386  Find any fsp open with a pathname below that of an already open path.
387 ****************************************************************************/
388
389 bool file_find_subpath(files_struct *dir_fsp)
390 {
391         files_struct *fsp;
392         size_t dlen;
393         char *d_fullname = talloc_asprintf(talloc_tos(),
394                                         "%s/%s",
395                                         dir_fsp->conn->connectpath,
396                                         dir_fsp->fsp_name);
397
398         if (!d_fullname) {
399                 return false;
400         }
401
402         dlen = strlen(d_fullname);
403
404         for (fsp=Files;fsp;fsp=fsp->next) {
405                 char *d1_fullname;
406
407                 if (fsp == dir_fsp) {
408                         continue;
409                 }
410
411                 d1_fullname = talloc_asprintf(talloc_tos(),
412                                         "%s/%s",
413                                         fsp->conn->connectpath,
414                                         fsp->fsp_name);
415
416                 if (strnequal(d_fullname, d1_fullname, dlen)) {
417                         TALLOC_FREE(d_fullname);
418                         TALLOC_FREE(d1_fullname);
419                         return true;
420                 }
421                 TALLOC_FREE(d1_fullname);
422         } 
423
424         TALLOC_FREE(d_fullname);
425         return false;
426 }
427
428 /****************************************************************************
429  Sync open files on a connection.
430 ****************************************************************************/
431
432 void file_sync_all(connection_struct *conn)
433 {
434         files_struct *fsp, *next;
435
436         for (fsp=Files;fsp;fsp=next) {
437                 next=fsp->next;
438                 if ((conn == fsp->conn) && (fsp->fh->fd != -1)) {
439                         sync_file(conn, fsp, True /* write through */);
440                 }
441         }
442 }
443
444 /****************************************************************************
445  Free up a fsp.
446 ****************************************************************************/
447
448 void file_free(struct smb_request *req, files_struct *fsp)
449 {
450         DLIST_REMOVE(Files, fsp);
451
452         string_free(&fsp->fsp_name);
453
454         TALLOC_FREE(fsp->fake_file_handle);
455
456         if (fsp->fh->ref_count == 1) {
457                 TALLOC_FREE(fsp->fh);
458         } else {
459                 fsp->fh->ref_count--;
460         }
461
462         if (fsp->notify) {
463                 if (fsp->is_directory) {
464                         notify_remove_onelevel(fsp->conn->notify_ctx,
465                                                &fsp->file_id, fsp);
466                 }
467                 notify_remove(fsp->conn->notify_ctx, fsp);
468                 TALLOC_FREE(fsp->notify);
469         }
470
471         /* Ensure this event will never fire. */
472         TALLOC_FREE(fsp->oplock_timeout);
473
474         /* Ensure this event will never fire. */
475         TALLOC_FREE(fsp->update_write_time_event);
476
477         bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
478         files_used--;
479
480         DEBUG(5,("freed files structure %d (%d used)\n",
481                  fsp->fnum, files_used));
482
483         fsp->conn->num_files_open--;
484
485         if ((req != NULL) && (fsp == req->chain_fsp)) {
486                 req->chain_fsp = NULL;
487         }
488
489         /* Closing a file can invalidate the positive cache. */
490         if (fsp == fsp_fi_cache.fsp) {
491                 ZERO_STRUCT(fsp_fi_cache);
492         }
493
494         /* Drop all remaining extensions. */
495         while (fsp->vfs_extension) {
496                 vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp);
497         }
498
499         /* this is paranoia, just in case someone tries to reuse the
500            information */
501         ZERO_STRUCTP(fsp);
502
503         TALLOC_FREE(fsp);
504 }
505
506 /****************************************************************************
507  Get an fsp from a 16 bit fnum.
508 ****************************************************************************/
509
510 files_struct *file_fnum(uint16 fnum)
511 {
512         files_struct *fsp;
513         int count=0;
514
515         for (fsp=Files;fsp;fsp=fsp->next, count++) {
516                 if (fsp->fnum == fnum) {
517                         if (count > 10) {
518                                 DLIST_PROMOTE(Files, fsp);
519                         }
520                         return fsp;
521                 }
522         }
523         return NULL;
524 }
525
526 /****************************************************************************
527  Get an fsp from a packet given the offset of a 16 bit fnum.
528 ****************************************************************************/
529
530 files_struct *file_fsp(struct smb_request *req, uint16 fid)
531 {
532         files_struct *fsp;
533
534         if ((req != NULL) && (req->chain_fsp != NULL)) {
535                 return req->chain_fsp;
536         }
537
538         fsp = file_fnum(fid);
539         if ((fsp != NULL) && (req != NULL)) {
540                 req->chain_fsp = fsp;
541         }
542         return fsp;
543 }
544
545 /****************************************************************************
546  Duplicate the file handle part for a DOS or FCB open.
547 ****************************************************************************/
548
549 void dup_file_fsp(struct smb_request *req, files_struct *from,
550                       uint32 access_mask, uint32 share_access,
551                       uint32 create_options, files_struct *to)
552 {
553         TALLOC_FREE(to->fh);
554
555         to->fh = from->fh;
556         to->fh->ref_count++;
557
558         to->file_id = from->file_id;
559         to->initial_allocation_size = from->initial_allocation_size;
560         to->mode = from->mode;
561         to->file_pid = from->file_pid;
562         to->vuid = from->vuid;
563         to->open_time = from->open_time;
564         to->access_mask = access_mask;
565         to->share_access = share_access;
566         to->oplock_type = from->oplock_type;
567         to->can_lock = from->can_lock;
568         to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
569         if (!CAN_WRITE(from->conn)) {
570                 to->can_write = False;
571         } else {
572                 to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
573         }
574         to->print_file = from->print_file;
575         to->modified = from->modified;
576         to->is_directory = from->is_directory;
577         to->aio_write_behind = from->aio_write_behind;
578         string_set(&to->fsp_name,from->fsp_name);
579 }