import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / 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 /****************************************************************************
41  Return a unique number identifying this fsp over the life of this pid.
42 ****************************************************************************/
43
44 static unsigned long get_gen_count(void)
45 {
46         static unsigned long file_gen_counter;
47
48         if ((++file_gen_counter) == 0)
49                 return ++file_gen_counter;
50         return file_gen_counter;
51 }
52
53 /****************************************************************************
54  Find first available file slot.
55 ****************************************************************************/
56
57 files_struct *file_new(connection_struct *conn)
58 {
59         int i;
60         static int first_file;
61         files_struct *fsp, *next;
62
63         /* we want to give out file handles differently on each new
64            connection because of a common bug in MS clients where they try to
65            reuse a file descriptor from an earlier smb connection. This code
66            increases the chance that the errant client will get an error rather
67            than causing corruption */
68         if (first_file == 0) {
69                 first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
70         }
71
72         i = bitmap_find(file_bmap, first_file);
73         if (i == -1) {
74                 /* 
75                  * Before we give up, go through the open files 
76                  * and see if there are any files opened with a
77                  * batch oplock. If so break the oplock and then
78                  * re-use that entry (if it becomes closed).
79                  * This may help as NT/95 clients tend to keep
80                  * files batch oplocked for quite a long time
81                  * after they have finished with them.
82                  */
83                 for (fsp=Files;fsp;fsp=next) {
84                         next=fsp->next;
85                         if (attempt_close_oplocked_file(fsp)) {
86                                 return file_new(conn);
87                         }
88                 }
89
90                 DEBUG(0,("ERROR! Out of file structures\n"));
91                 unix_ERR_class = ERRSRV;
92                 unix_ERR_code = ERRnofids;
93                 return NULL;
94         }
95
96         fsp = (files_struct *)malloc(sizeof(*fsp));
97         if (!fsp) {
98                 unix_ERR_class = ERRSRV;
99                 unix_ERR_code = ERRnofids;
100                 return NULL;
101         }
102
103         ZERO_STRUCTP(fsp);
104         fsp->fd = -1;
105         fsp->conn = conn;
106         fsp->file_id = get_gen_count();
107         GetTimeOfDay(&fsp->open_time);
108
109         first_file = (i+1) % real_max_open_files;
110
111         bitmap_set(file_bmap, i);
112         files_used++;
113
114         fsp->fnum = i + FILE_HANDLE_OFFSET;
115         SMB_ASSERT(fsp->fnum < 65536);
116
117         string_set(&fsp->fsp_name,"");
118         
119         DLIST_ADD(Files, fsp);
120
121         DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
122                  i, fsp->fnum, files_used));
123
124         chain_fsp = fsp;
125         
126         return fsp;
127 }
128
129 /****************************************************************************
130  Close all open files for a connection.
131 ****************************************************************************/
132
133 void file_close_conn(connection_struct *conn)
134 {
135         files_struct *fsp, *next;
136         
137         for (fsp=Files;fsp;fsp=next) {
138                 next = fsp->next;
139                 if (fsp->conn == conn) {
140                         close_file(fsp,False); 
141                 }
142         }
143 }
144
145 /****************************************************************************
146  Close all open files for a pid.
147 ****************************************************************************/
148
149 void file_close_pid(uint16 smbpid)
150 {
151         files_struct *fsp, *next;
152         
153         for (fsp=Files;fsp;fsp=next) {
154                 next = fsp->next;
155                 if (fsp->file_pid == smbpid) {
156                         close_file(fsp,False); 
157                 }
158         }
159 }
160
161 /****************************************************************************
162  Initialise file structures.
163 ****************************************************************************/
164
165 #define MAX_OPEN_FUDGEFACTOR 20
166
167 void file_init(void)
168 {
169         int request_max_open_files = lp_max_open_files();
170         int real_lim;
171
172         /*
173          * Set the max_open files to be the requested
174          * max plus a fudgefactor to allow for the extra
175          * fd's we need such as log files etc...
176          */
177         real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
178
179         real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
180
181         if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536)
182                 real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
183
184         if(real_max_open_files != request_max_open_files) {
185                 DEBUG(1,("file_init: Information only: requested %d \
186 open files, %d are available.\n", request_max_open_files, real_max_open_files));
187         }
188
189         SMB_ASSERT(real_max_open_files > 100);
190
191         file_bmap = bitmap_allocate(real_max_open_files);
192         
193         if (!file_bmap) {
194                 exit_server("out of memory in file_init");
195         }
196         
197         /*
198          * Ensure that pipe_handle_oppset is set correctly.
199          */
200         set_pipe_handle_offset(real_max_open_files);
201 }
202
203 /****************************************************************************
204  Close files open by a specified vuid.
205 ****************************************************************************/
206
207 void file_close_user(int vuid)
208 {
209         files_struct *fsp, *next;
210
211         for (fsp=Files;fsp;fsp=next) {
212                 next=fsp->next;
213                 if (fsp->vuid == vuid) {
214                         close_file(fsp,False);
215                 }
216         }
217 }
218
219 void file_dump_open_table(void)
220 {
221         int count=0;
222         files_struct *fsp;
223
224         for (fsp=Files;fsp;fsp=fsp->next,count++) {
225                 DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n",
226                         count, fsp->fnum, fsp->fsp_name, fsp->fd, (unsigned long)fsp->file_id,
227                         (unsigned int)fsp->dev, (double)fsp->inode ));
228         }
229 }
230
231 /****************************************************************************
232  Find a fsp given a file descriptor.
233 ****************************************************************************/
234
235 files_struct *file_find_fd(int fd)
236 {
237         int count=0;
238         files_struct *fsp;
239
240         for (fsp=Files;fsp;fsp=fsp->next,count++) {
241                 if (fsp->fd == fd) {
242                         if (count > 10) {
243                                 DLIST_PROMOTE(Files, fsp);
244                         }
245                         return fsp;
246                 }
247         }
248
249         return NULL;
250 }
251
252 /****************************************************************************
253  Find a fsp given a device, inode and file_id.
254 ****************************************************************************/
255
256 files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
257 {
258         int count=0;
259         files_struct *fsp;
260
261         for (fsp=Files;fsp;fsp=fsp->next,count++) {
262                 /* We can have a fsp->fd == -1 here as it could be a stat open. */
263                 if (fsp->dev == dev && 
264                     fsp->inode == inode &&
265                     fsp->file_id == file_id ) {
266                         if (count > 10) {
267                                 DLIST_PROMOTE(Files, fsp);
268                         }
269                         /* Paranoia check. */
270                         if (fsp->fd == -1 && fsp->oplock_type != NO_OPLOCK) {
271                                 DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \
272 oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev,
273                                                 (double)fsp->inode, (unsigned int)fsp->file_id,
274                                                 (unsigned int)fsp->oplock_type ));
275                                 smb_panic("file_find_dif\n");
276                         }
277                         return fsp;
278                 }
279         }
280
281         return NULL;
282 }
283
284 /****************************************************************************
285  Check if an fsp still exists.
286 ****************************************************************************/
287
288 files_struct *file_find_fsp(files_struct *orig_fsp)
289 {
290         files_struct *fsp;
291
292     for (fsp=Files;fsp;fsp=fsp->next) {
293         if (fsp == orig_fsp)
294             return fsp;
295     }
296
297     return NULL;
298 }
299
300 /****************************************************************************
301  Find the first fsp given a device and inode.
302 ****************************************************************************/
303
304 files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
305 {
306     files_struct *fsp;
307
308     for (fsp=Files;fsp;fsp=fsp->next) {
309         if ( fsp->fd != -1 &&
310             fsp->dev == dev &&
311             fsp->inode == inode )
312             return fsp;
313     }
314
315     return NULL;
316 }
317
318 /****************************************************************************
319  Find the next fsp having the same device and inode.
320 ****************************************************************************/
321
322 files_struct *file_find_di_next(files_struct *start_fsp)
323 {
324     files_struct *fsp;
325
326     for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
327         if ( fsp->fd != -1 &&
328             fsp->dev == start_fsp->dev &&
329             fsp->inode == start_fsp->inode )
330             return fsp;
331     }
332
333     return NULL;
334 }
335
336 /****************************************************************************
337  Find a fsp that is open for printing.
338 ****************************************************************************/
339
340 files_struct *file_find_print(void)
341 {
342         files_struct *fsp;
343
344         for (fsp=Files;fsp;fsp=fsp->next) {
345                 if (fsp->print_file) return fsp;
346         } 
347
348         return NULL;
349 }
350
351 /****************************************************************************
352  Sync open files on a connection.
353 ****************************************************************************/
354
355 void file_sync_all(connection_struct *conn)
356 {
357         files_struct *fsp, *next;
358
359         for (fsp=Files;fsp;fsp=next) {
360                 next=fsp->next;
361                 if ((conn == fsp->conn) && (fsp->fd != -1)) {
362                         sync_file(conn,fsp);
363                 }
364         }
365 }
366
367 /****************************************************************************
368  Free up a fsp.
369 ****************************************************************************/
370
371 void file_free(files_struct *fsp)
372 {
373         DLIST_REMOVE(Files, fsp);
374
375         string_free(&fsp->fsp_name);
376
377         if (fsp->fake_file_handle) {
378                 destroy_fake_file_handle(&fsp->fake_file_handle);
379         }
380
381         bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
382         files_used--;
383
384         DEBUG(5,("freed files structure %d (%d used)\n",
385                  fsp->fnum, files_used));
386
387         /* this is paranoia, just in case someone tries to reuse the 
388            information */
389         ZERO_STRUCTP(fsp);
390
391         if (fsp == chain_fsp) chain_fsp = NULL;
392
393         SAFE_FREE(fsp);
394 }
395
396 /****************************************************************************
397  Get a fsp from a packet given the offset of a 16 bit fnum.
398 ****************************************************************************/
399
400 files_struct *file_fsp(char *buf, int where)
401 {
402         int fnum, count=0;
403         files_struct *fsp;
404
405         if (chain_fsp)
406                 return chain_fsp;
407
408         if (!buf)
409                 return NULL;
410         fnum = SVAL(buf, where);
411
412         for (fsp=Files;fsp;fsp=fsp->next, count++) {
413                 if (fsp->fnum == fnum) {
414                         chain_fsp = fsp;
415                         if (count > 10) {
416                                 DLIST_PROMOTE(Files, fsp);
417                         }
418                         return fsp;
419                 }
420         }
421         return NULL;
422 }
423
424 /****************************************************************************
425  Reset the chained fsp - done at the start of a packet reply.
426 ****************************************************************************/
427
428 void file_chain_reset(void)
429 {
430         chain_fsp = NULL;
431 }
432
433 /****************************************************************************
434 Save the chained fsp - done when about to do an oplock break.
435 ****************************************************************************/
436
437 void file_chain_save(void)
438 {
439         oplock_save_chain_fsp = chain_fsp;
440 }
441
442 /****************************************************************************
443 Restore the chained fsp - done after an oplock break.
444 ****************************************************************************/
445
446 void file_chain_restore(void)
447 {
448         chain_fsp = oplock_save_chain_fsp;
449 }