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