Removed version number from file header.
[samba.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         string_set(&fsp->fsp_name,"");
116         
117         DLIST_ADD(Files, fsp);
118
119         DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
120                  i, fsp->fnum, files_used));
121
122         chain_fsp = fsp;
123         
124         return fsp;
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(fsp,False); 
139                 }
140         }
141 }
142
143 /****************************************************************************
144  Initialise file structures.
145 ****************************************************************************/
146
147 #define MAX_OPEN_FUDGEFACTOR 10
148
149 void file_init(void)
150 {
151         int request_max_open_files = lp_max_open_files();
152         int real_lim;
153
154         /*
155          * Set the max_open files to be the requested
156          * max plus a fudgefactor to allow for the extra
157          * fd's we need such as log files etc...
158          */
159         real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
160
161         real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
162
163         if(real_max_open_files != request_max_open_files) {
164                 DEBUG(1,("file_init: Information only: requested %d \
165 open files, %d are available.\n", request_max_open_files, real_max_open_files));
166         }
167
168         file_bmap = bitmap_allocate(real_max_open_files);
169         
170         if (!file_bmap) {
171                 exit_server("out of memory in file_init");
172         }
173         
174         /*
175          * Ensure that pipe_handle_oppset is set correctly.
176          */
177         set_pipe_handle_offset(real_max_open_files);
178 }
179
180 /****************************************************************************
181  Close files open by a specified vuid.
182 ****************************************************************************/
183
184 void file_close_user(int vuid)
185 {
186         files_struct *fsp, *next;
187
188         for (fsp=Files;fsp;fsp=next) {
189                 next=fsp->next;
190                 if (fsp->vuid == vuid) {
191                         close_file(fsp,False);
192                 }
193         }
194 }
195
196 /****************************************************************************
197  Find a fsp given a file descriptor.
198 ****************************************************************************/
199
200 files_struct *file_find_fd(int fd)
201 {
202         int count=0;
203         files_struct *fsp;
204
205         for (fsp=Files;fsp;fsp=fsp->next,count++) {
206                 if (fsp->fd == fd) {
207                         if (count > 10) {
208                                 DLIST_PROMOTE(Files, fsp);
209                         }
210                         return fsp;
211                 }
212         }
213
214         return NULL;
215 }
216
217 /****************************************************************************
218  Find a fsp given a device, inode and file_id.
219 ****************************************************************************/
220
221 files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
222 {
223         int count=0;
224         files_struct *fsp;
225
226         for (fsp=Files;fsp;fsp=fsp->next,count++) {
227                 if (fsp->fd != -1 &&
228                     fsp->dev == dev && 
229                     fsp->inode == inode &&
230                     fsp->file_id == file_id ) {
231                         if (count > 10) {
232                                 DLIST_PROMOTE(Files, fsp);
233                         }
234                         return fsp;
235                 }
236         }
237
238         return NULL;
239 }
240
241 /****************************************************************************
242  Check if an fsp still exists.
243 ****************************************************************************/
244
245 files_struct *file_find_fsp(files_struct *orig_fsp)
246 {
247         files_struct *fsp;
248
249     for (fsp=Files;fsp;fsp=fsp->next) {
250         if (fsp == orig_fsp)
251             return fsp;
252     }
253
254     return NULL;
255 }
256
257 /****************************************************************************
258  Find the first fsp given a device and inode.
259 ****************************************************************************/
260
261 files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
262 {
263     files_struct *fsp;
264
265     for (fsp=Files;fsp;fsp=fsp->next) {
266         if ( fsp->fd != -1 &&
267             fsp->dev == dev &&
268             fsp->inode == inode )
269             return fsp;
270     }
271
272     return NULL;
273 }
274
275 /****************************************************************************
276  Find the next fsp having the same device and inode.
277 ****************************************************************************/
278
279 files_struct *file_find_di_next(files_struct *start_fsp)
280 {
281     files_struct *fsp;
282
283     for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
284         if ( fsp->fd != -1 &&
285             fsp->dev == start_fsp->dev &&
286             fsp->inode == start_fsp->inode )
287             return fsp;
288     }
289
290     return NULL;
291 }
292
293 /****************************************************************************
294  Find a fsp that is open for printing.
295 ****************************************************************************/
296
297 files_struct *file_find_print(void)
298 {
299         files_struct *fsp;
300
301         for (fsp=Files;fsp;fsp=fsp->next) {
302                 if (fsp->print_file) return fsp;
303         } 
304
305         return NULL;
306 }
307
308 /****************************************************************************
309  Sync open files on a connection.
310 ****************************************************************************/
311
312 void file_sync_all(connection_struct *conn)
313 {
314         files_struct *fsp, *next;
315
316         for (fsp=Files;fsp;fsp=next) {
317                 next=fsp->next;
318                 if ((conn == fsp->conn) && (fsp->fd != -1)) {
319                         sync_file(conn,fsp);
320                 }
321         }
322 }
323
324 /****************************************************************************
325  Free up a fsp.
326 ****************************************************************************/
327
328 void file_free(files_struct *fsp)
329 {
330         DLIST_REMOVE(Files, fsp);
331
332         string_free(&fsp->fsp_name);
333
334         bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
335         files_used--;
336
337         DEBUG(5,("freed files structure %d (%d used)\n",
338                  fsp->fnum, files_used));
339
340         /* this is paranoia, just in case someone tries to reuse the 
341            information */
342         ZERO_STRUCTP(fsp);
343
344         if (fsp == chain_fsp) chain_fsp = NULL;
345
346         SAFE_FREE(fsp);
347 }
348
349 /****************************************************************************
350  Get a fsp from a packet given the offset of a 16 bit fnum.
351 ****************************************************************************/
352
353 files_struct *file_fsp(char *buf, int where)
354 {
355         int fnum, count=0;
356         files_struct *fsp;
357
358         if (chain_fsp)
359                 return chain_fsp;
360
361         fnum = SVAL(buf, where);
362
363         for (fsp=Files;fsp;fsp=fsp->next, count++) {
364                 if (fsp->fnum == fnum) {
365                         chain_fsp = fsp;
366                         if (count > 10) {
367                                 DLIST_PROMOTE(Files, fsp);
368                         }
369                         return fsp;
370                 }
371         }
372         return NULL;
373 }
374
375 /****************************************************************************
376  Reset the chained fsp - done at the start of a packet reply.
377 ****************************************************************************/
378
379 void file_chain_reset(void)
380 {
381         chain_fsp = NULL;
382 }
383
384 /****************************************************************************
385 Save the chained fsp - done when about to do an oplock break.
386 ****************************************************************************/
387
388 void file_chain_save(void)
389 {
390         oplock_save_chain_fsp = chain_fsp;
391 }
392
393 /****************************************************************************
394 Restore the chained fsp - done after an oplock break.
395 ****************************************************************************/
396
397 void file_chain_restore(void)
398 {
399         chain_fsp = oplock_save_chain_fsp;
400 }