2 Unix SMB/Netbios implementation.
4 Files[] structure handling
5 Copyright (C) Andrew Tridgell 1998
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.
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.
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.
24 static int real_max_open_files;
26 #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))
28 #define FILE_HANDLE_OFFSET 0x1000
30 static struct bitmap *file_bmap;
32 static files_struct *Files;
34 /* a fsp to use when chaining */
35 static files_struct *chain_fsp = NULL;
36 /* a fsp to use to save when breaking an oplock. */
37 static files_struct *oplock_save_chain_fsp = NULL;
39 static int files_used;
41 /****************************************************************************
42 find first available file slot
43 ****************************************************************************/
44 files_struct *file_new(connection_struct *conn)
47 static int first_file;
48 files_struct *fsp, *next;
50 /* we want to give out file handles differently on each new
51 connection because of a common bug in MS clients where they try to
52 reuse a file descriptor from an earlier smb connection. This code
53 increases the chance that the errant client will get an error rather
54 than causing corruption */
55 if (first_file == 0) {
56 first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
59 i = bitmap_find(file_bmap, first_file);
62 * Before we give up, go through the open files
63 * and see if there are any files opened with a
64 * batch oplock. If so break the oplock and then
65 * re-use that entry (if it becomes closed).
66 * This may help as NT/95 clients tend to keep
67 * files batch oplocked for quite a long time
68 * after they have finished with them.
70 for (fsp=Files;fsp;fsp=next) {
72 if (attempt_close_oplocked_file(fsp)) {
73 return file_new(conn);
77 DEBUG(0,("ERROR! Out of file structures\n"));
78 unix_ERR_class = ERRSRV;
79 unix_ERR_code = ERRnofids;
83 fsp = (files_struct *)malloc(sizeof(*fsp));
85 unix_ERR_class = ERRSRV;
86 unix_ERR_code = ERRnofids;
94 first_file = (i+1) % real_max_open_files;
96 bitmap_set(file_bmap, i);
99 fsp->fnum = i + FILE_HANDLE_OFFSET;
100 string_set(&fsp->fsp_name,"");
102 DLIST_ADD(Files, fsp);
104 DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
105 i, fsp->fnum, files_used));
113 /****************************************************************************
114 close all open files for a connection
115 ****************************************************************************/
116 void file_close_conn(connection_struct *conn)
118 files_struct *fsp, *next;
120 for (fsp=Files;fsp;fsp=next) {
122 if (fsp->conn == conn) {
123 close_file(fsp,False);
128 /****************************************************************************
129 initialise file structures
130 ****************************************************************************/
132 #define MAX_OPEN_FUDGEFACTOR 10
136 int request_max_open_files = lp_max_open_files();
140 * Set the max_open files to be the requested
141 * max plus a fudgefactor to allow for the extra
142 * fd's we need such as log files etc...
144 real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
146 real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
148 if(real_max_open_files != request_max_open_files) {
149 DEBUG(1,("file_init: Information only: requested %d \
150 open files, %d are available.\n", request_max_open_files, real_max_open_files));
153 file_bmap = bitmap_allocate(real_max_open_files);
156 exit_server("out of memory in file_init");
160 * Ensure that pipe_handle_oppset is set correctly.
162 set_pipe_handle_offset(real_max_open_files);
166 /****************************************************************************
167 close files open by a specified vuid
168 ****************************************************************************/
169 void file_close_user(int vuid)
171 files_struct *fsp, *next;
173 for (fsp=Files;fsp;fsp=next) {
175 if (fsp->vuid == vuid) {
176 close_file(fsp,False);
182 /****************************************************************************
183 Find a fsp given a device, inode and timevalue
184 If this is from a kernel oplock break request then tval may be NULL.
185 ****************************************************************************/
187 files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
192 for (fsp=Files;fsp;fsp=fsp->next,count++) {
195 fsp->inode == inode &&
196 (tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) &&
197 (tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True )) {
199 DLIST_PROMOTE(Files, fsp);
208 /****************************************************************************
209 Check if an fsp still exists.
210 ****************************************************************************/
212 files_struct *file_find_fsp(files_struct *orig_fsp)
216 for (fsp=Files;fsp;fsp=fsp->next) {
224 /****************************************************************************
225 Find the first fsp given a device and inode.
226 ****************************************************************************/
228 files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
232 for (fsp=Files;fsp;fsp=fsp->next) {
233 if ( fsp->fd != -1 &&
235 fsp->inode == inode )
242 /****************************************************************************
243 Find the next fsp having the same device and inode.
244 ****************************************************************************/
246 files_struct *file_find_di_next(files_struct *start_fsp)
250 for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
251 if ( fsp->fd != -1 &&
252 fsp->dev == start_fsp->dev &&
253 fsp->inode == start_fsp->inode )
260 /****************************************************************************
261 find a fsp that is open for printing
262 ****************************************************************************/
263 files_struct *file_find_print(void)
267 for (fsp=Files;fsp;fsp=fsp->next) {
268 if (fsp->print_file) return fsp;
275 /****************************************************************************
276 sync open files on a connection
277 ****************************************************************************/
278 void file_sync_all(connection_struct *conn)
280 files_struct *fsp, *next;
282 for (fsp=Files;fsp;fsp=next) {
284 if ((conn == fsp->conn) && (fsp->fd != -1)) {
291 /****************************************************************************
293 ****************************************************************************/
294 void file_free(files_struct *fsp)
296 DLIST_REMOVE(Files, fsp);
298 string_free(&fsp->fsp_name);
300 bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
303 DEBUG(5,("freed files structure %d (%d used)\n",
304 fsp->fnum, files_used));
306 /* this is paranoia, just in case someone tries to reuse the
310 if (fsp == chain_fsp) chain_fsp = NULL;
316 /****************************************************************************
317 get a fsp from a packet given the offset of a 16 bit fnum
318 ****************************************************************************/
319 files_struct *file_fsp(char *buf, int where)
324 if (chain_fsp) return chain_fsp;
326 fnum = SVAL(buf, where);
328 for (fsp=Files;fsp;fsp=fsp->next, count++) {
329 if (fsp->fnum == fnum) {
332 DLIST_PROMOTE(Files, fsp);
340 /****************************************************************************
341 Reset the chained fsp - done at the start of a packet reply
342 ****************************************************************************/
344 void file_chain_reset(void)
349 /****************************************************************************
350 Save the chained fsp - done when about to do an oplock break.
351 ****************************************************************************/
353 void file_chain_save(void)
355 oplock_save_chain_fsp = chain_fsp;
358 /****************************************************************************
359 Restore the chained fsp - done after an oplock break.
360 ****************************************************************************/
361 void file_chain_restore(void)
363 chain_fsp = oplock_save_chain_fsp;