5b930f994009759489cc8e76f1cd657617871b78
[tprouty/samba.git] / source / smbd / files.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Files[] structure handling
5    Copyright (C) Andrew Tridgell 1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 static int real_max_open_files;
27
28 #define VALID_FNUM(fnum)   (((fnum) >= 0) && ((fnum) < real_max_open_files))
29
30 #define FILE_HANDLE_OFFSET 0x1000
31
32 static struct bitmap *file_bmap;
33
34 static files_struct *Files;
35  
36 /* a fsp to use when chaining */
37 static files_struct *chain_fsp = NULL;
38 /* a fsp to use to save when breaking an oplock. */
39 static files_struct *oplock_save_chain_fsp = NULL;
40
41 static int files_used;
42
43 /****************************************************************************
44   find first available file slot
45 ****************************************************************************/
46 files_struct *file_new(void )
47 {
48         int i;
49         static int first_file;
50         files_struct *fsp, *next;
51
52         /* we want to give out file handles differently on each new
53            connection because of a common bug in MS clients where they try to
54            reuse a file descriptor from an earlier smb connection. This code
55            increases the chance that the errant client will get an error rather
56            than causing corruption */
57         if (first_file == 0) {
58                 first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
59         }
60
61         i = bitmap_find(file_bmap, first_file);
62         if (i == -1) {
63                 /* 
64                  * Before we give up, go through the open files 
65                  * and see if there are any files opened with a
66                  * batch oplock. If so break the oplock and then
67                  * re-use that entry (if it becomes closed).
68                  * This may help as NT/95 clients tend to keep
69                  * files batch oplocked for quite a long time
70                  * after they have finished with them.
71                  */
72                 for (fsp=Files;fsp;fsp=next) {
73                         next=fsp->next;
74                         if (attempt_close_oplocked_file(fsp)) {
75                                 return file_new();
76                         }
77                 }
78
79                 DEBUG(0,("ERROR! Out of file structures\n"));
80                 unix_ERR_class = ERRSRV;
81                 unix_ERR_code = ERRnofids;
82                 return NULL;
83         }
84
85         fsp = (files_struct *)malloc(sizeof(*fsp));
86         if (!fsp) {
87                 unix_ERR_class = ERRSRV;
88                 unix_ERR_code = ERRnofids;
89                 return NULL;
90         }
91
92         ZERO_STRUCTP(fsp);
93         fsp->fd = -1;
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         string_set(&fsp->fsp_name,"");
102         
103         DLIST_ADD(Files, fsp);
104
105         DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
106                  i, fsp->fnum, files_used));
107
108         chain_fsp = fsp;
109         
110         return fsp;
111 }
112
113
114 /****************************************************************************
115 close all open files for a connection
116 ****************************************************************************/
117 void file_close_conn(connection_struct *conn)
118 {
119         files_struct *fsp, *next;
120         
121         for (fsp=Files;fsp;fsp=next) {
122                 next = fsp->next;
123                 if (fsp->conn == conn) {
124                         close_file(fsp,False); 
125                 }
126         }
127 }
128
129 /****************************************************************************
130 initialise file structures
131 ****************************************************************************/
132
133 #define MAX_OPEN_FUDGEFACTOR 10
134
135 void file_init(void)
136 {
137         int request_max_open_files = lp_max_open_files();
138         int real_lim;
139
140         /*
141          * Set the max_open files to be the requested
142          * max plus a fudgefactor to allow for the extra
143          * fd's we need such as log files etc...
144          */
145         real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
146
147         real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
148
149         if(real_max_open_files != request_max_open_files) {
150                 DEBUG(1,("file_init: Information only: requested %d \
151 open files, %d are available.\n", request_max_open_files, real_max_open_files));
152         }
153
154         file_bmap = bitmap_allocate(real_max_open_files);
155         
156         if (!file_bmap) {
157                 exit_server("out of memory in file_init");
158         }
159         
160         /*
161          * Ensure that pipe_handle_oppset is set correctly.
162          */
163         set_pipe_handle_offset(real_max_open_files);
164 }
165
166
167 /****************************************************************************
168 close files open by a specified vuid
169 ****************************************************************************/
170 void file_close_user(int vuid)
171 {
172         files_struct *fsp, *next;
173
174         for (fsp=Files;fsp;fsp=next) {
175                 next=fsp->next;
176                 if (fsp->vuid == vuid) {
177                         close_file(fsp,False);
178                 }
179         }
180 }
181
182
183 /****************************************************************************
184  Find a fsp given a device, inode and timevalue
185  If this is from a kernel oplock break request then tval may be NULL.
186 ****************************************************************************/
187
188 files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
189 {
190         int count=0;
191         files_struct *fsp;
192
193         for (fsp=Files;fsp;fsp=fsp->next,count++) {
194                 if (fsp->fd != -1 &&
195                     fsp->dev == dev && 
196                     fsp->inode == inode &&
197                     (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) &&
198                     (tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True )) {
199                         if (count > 10) {
200                                 DLIST_PROMOTE(Files, fsp);
201                         }
202                         return fsp;
203                 }
204         }
205
206         return NULL;
207 }
208
209 /****************************************************************************
210  Check if an fsp still exists.
211 ****************************************************************************/
212
213 files_struct *file_find_fsp(files_struct *orig_fsp)
214 {
215         files_struct *fsp;
216
217     for (fsp=Files;fsp;fsp=fsp->next) {
218         if (fsp == orig_fsp)
219             return fsp;
220     }
221
222     return NULL;
223 }
224
225 /****************************************************************************
226  Find the first fsp given a device and inode.
227 ****************************************************************************/
228
229 files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
230 {
231     files_struct *fsp;
232
233     for (fsp=Files;fsp;fsp=fsp->next) {
234         if ( fsp->fd != -1 &&
235             fsp->dev == dev &&
236             fsp->inode == inode )
237             return fsp;
238     }
239
240     return NULL;
241 }
242
243 /****************************************************************************
244  Find the next fsp having the same device and inode.
245 ****************************************************************************/
246
247 files_struct *file_find_di_next(files_struct *start_fsp)
248 {
249     files_struct *fsp;
250
251     for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
252         if ( fsp->fd != -1 &&
253             fsp->dev == start_fsp->dev &&
254             fsp->inode == start_fsp->inode )
255             return fsp;
256     }
257
258     return NULL;
259 }
260
261 /****************************************************************************
262 find a fsp that is open for printing
263 ****************************************************************************/
264 files_struct *file_find_print(void)
265 {
266         files_struct *fsp;
267
268         for (fsp=Files;fsp;fsp=fsp->next) {
269                 if (fsp->print_file) return fsp;
270         } 
271
272         return NULL;
273 }
274
275
276 /****************************************************************************
277 sync open files on a connection
278 ****************************************************************************/
279 void file_sync_all(connection_struct *conn)
280 {
281         files_struct *fsp, *next;
282
283         for (fsp=Files;fsp;fsp=next) {
284                 next=fsp->next;
285                 if ((conn == fsp->conn) && (fsp->fd != -1)) {
286                         conn->vfs_ops.fsync(fsp->fd);
287                 }
288         }
289 }
290
291
292 /****************************************************************************
293 free up a fsp
294 ****************************************************************************/
295 void file_free(files_struct *fsp)
296 {
297         DLIST_REMOVE(Files, fsp);
298
299         string_free(&fsp->fsp_name);
300
301         bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
302         files_used--;
303
304         DEBUG(5,("freed files structure %d (%d used)\n",
305                  fsp->fnum, files_used));
306
307         /* this is paranoia, just in case someone tries to reuse the 
308            information */
309         ZERO_STRUCTP(fsp);
310
311         if (fsp == chain_fsp) chain_fsp = NULL;
312
313         free(fsp);
314 }
315
316
317 /****************************************************************************
318 get a fsp from a packet given the offset of a 16 bit fnum
319 ****************************************************************************/
320 files_struct *file_fsp(char *buf, int where)
321 {
322         int fnum, count=0;
323         files_struct *fsp;
324
325         if (chain_fsp) return chain_fsp;
326
327         fnum = SVAL(buf, where);
328
329         for (fsp=Files;fsp;fsp=fsp->next, count++) {
330                 if (fsp->fnum == fnum) {
331                         chain_fsp = fsp;
332                         if (count > 10) {
333                                 DLIST_PROMOTE(Files, fsp);
334                         }
335                         return fsp;
336                 }
337         }
338         return NULL;
339 }
340
341 /****************************************************************************
342  Reset the chained fsp - done at the start of a packet reply
343 ****************************************************************************/
344
345 void file_chain_reset(void)
346 {
347         chain_fsp = NULL;
348 }
349
350 /****************************************************************************
351 Save the chained fsp - done when about to do an oplock break.
352 ****************************************************************************/
353
354 void file_chain_save(void)
355 {
356         oplock_save_chain_fsp = chain_fsp;
357 }
358
359 /****************************************************************************
360 Restore the chained fsp - done after an oplock break.
361 ****************************************************************************/
362 void file_chain_restore(void)
363 {
364         chain_fsp = oplock_save_chain_fsp;
365 }