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