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 extern int DEBUGLEVEL
;
26 static int real_max_open_files
;
28 #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))
30 #define FILE_HANDLE_OFFSET 0x1000
32 static struct bitmap
*file_bmap
;
34 static files_struct
*Files
;
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
;
42 * Indirection for file fd's. Needed as POSIX locking
43 * is based on file/process, not fd/process.
45 static file_fd_struct
*FileFd
;
47 static int files_used
, fd_ptr_used
;
49 /****************************************************************************
50 find first available file slot
51 ****************************************************************************/
52 files_struct
*file_new(void )
55 static int first_file
;
56 files_struct
*fsp
, *next
;
58 /* we want to give out file handles differently on each new
59 connection because of a common bug in MS clients where they try to
60 reuse a file descriptor from an earlier smb connection. This code
61 increases the chance that the errant client will get an error rather
62 than causing corruption */
63 if (first_file
== 0) {
64 first_file
= (getpid() ^ (int)time(NULL
)) % real_max_open_files
;
67 i
= bitmap_find(file_bmap
, first_file
);
70 * Before we give up, go through the open files
71 * and see if there are any files opened with a
72 * batch oplock. If so break the oplock and then
73 * re-use that entry (if it becomes closed).
74 * This may help as NT/95 clients tend to keep
75 * files batch oplocked for quite a long time
76 * after they have finished with them.
78 for (fsp
=Files
;fsp
;fsp
=next
) {
80 if (attempt_close_oplocked_file(fsp
)) {
85 DEBUG(0,("ERROR! Out of file structures\n"));
89 fsp
= (files_struct
*)malloc(sizeof(*fsp
));
90 if (!fsp
) return NULL
;
94 first_file
= (i
+1) % real_max_open_files
;
96 bitmap_set(file_bmap
, i
);
99 fsp
->fnum
= i
+ FILE_HANDLE_OFFSET
;
100 string_init(&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
));
114 /****************************************************************************
115 fd support routines - attempt to find an already open file by dev
116 and inode - increments the ref_count of the returned file_fd_struct *.
117 ****************************************************************************/
118 file_fd_struct
*fd_get_already_open(SMB_STRUCT_STAT
*sbuf
)
120 file_fd_struct
*fd_ptr
;
122 if(!sbuf
) return NULL
;
124 for (fd_ptr
=FileFd
;fd_ptr
;fd_ptr
=fd_ptr
->next
) {
125 if ((fd_ptr
->ref_count
> 0) &&
126 (sbuf
->st_dev
== fd_ptr
->dev
) &&
127 (sbuf
->st_ino
== fd_ptr
->inode
)) {
130 DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %.0f, ref_count = %d\n",
131 (unsigned int)fd_ptr
->dev
, (double)fd_ptr
->inode
,
143 /****************************************************************************
144 fd support routines - attempt to find a empty slot in the FileFd array.
145 Increments the ref_count of the returned entry.
146 ****************************************************************************/
147 file_fd_struct
*fd_get_new(void)
149 extern struct current_user current_user
;
150 file_fd_struct
*fd_ptr
;
152 fd_ptr
= (file_fd_struct
*)malloc(sizeof(*fd_ptr
));
154 DEBUG(0,("ERROR! malloc fail for file_fd struct.\n"));
158 ZERO_STRUCTP(fd_ptr
);
160 fd_ptr
->dev
= (SMB_DEV_T
)-1;
161 fd_ptr
->inode
= (SMB_INO_T
)-1;
163 fd_ptr
->fd_readonly
= -1;
164 fd_ptr
->fd_writeonly
= -1;
165 fd_ptr
->real_open_flags
= -1;
166 fd_add_to_uid_cache(fd_ptr
, (uid_t
)current_user
.uid
);
171 DLIST_ADD(FileFd
, fd_ptr
);
173 DEBUG(5,("allocated fd_ptr structure (%d used)\n", fd_ptr_used
));
179 /****************************************************************************
180 close all open files for a connection
181 ****************************************************************************/
182 void file_close_conn(connection_struct
*conn
)
184 files_struct
*fsp
, *next
;
186 for (fsp
=Files
;fsp
;fsp
=next
) {
188 if (fsp
->conn
== conn
&& fsp
->open
) {
189 if (fsp
->is_directory
)
190 close_directory(fsp
,False
);
192 close_file(fsp
,False
);
197 /****************************************************************************
198 initialise file structures
199 ****************************************************************************/
201 #define MAX_OPEN_FUDGEFACTOR 10
205 int request_max_open_files
= lp_max_open_files();
209 * Set the max_open files to be the requested
210 * max plus a fudgefactor to allow for the extra
211 * fd's we need such as log files etc...
213 real_lim
= set_maxfiles(request_max_open_files
+ MAX_OPEN_FUDGEFACTOR
);
215 real_max_open_files
= real_lim
- MAX_OPEN_FUDGEFACTOR
;
217 if(real_max_open_files
!= request_max_open_files
) {
218 DEBUG(1,("file_init: Information only: requested %d \
219 open files, %d are available.\n", request_max_open_files
, real_max_open_files
));
222 file_bmap
= bitmap_allocate(real_max_open_files
);
225 exit_server("out of memory in file_init");
229 * Ensure that pipe_handle_oppset is set correctly.
231 set_pipe_handle_offset(real_max_open_files
);
235 /****************************************************************************
236 close files open by a specified vuid
237 ****************************************************************************/
238 void file_close_user(int vuid
)
240 files_struct
*fsp
, *next
;
242 for (fsp
=Files
;fsp
;fsp
=next
) {
244 if ((fsp
->vuid
== vuid
) && fsp
->open
) {
245 if(!fsp
->is_directory
)
246 close_file(fsp
,False
);
248 close_directory(fsp
,False
);
254 /****************************************************************************
255 Find a fsp given a device, inode and timevalue
256 If this is from a kernel oplock break request then tval may be NULL.
257 ****************************************************************************/
259 files_struct
*file_find_dit(SMB_DEV_T dev
, SMB_INO_T inode
, struct timeval
*tval
)
264 for (fsp
=Files
;fsp
;fsp
=fsp
->next
,count
++) {
266 fsp
->fd_ptr
!= NULL
&&
267 fsp
->fd_ptr
->dev
== dev
&&
268 fsp
->fd_ptr
->inode
== inode
&&
269 (tval
? (fsp
->open_time
.tv_sec
== tval
->tv_sec
) : True
) &&
270 (tval
? (fsp
->open_time
.tv_usec
== tval
->tv_usec
) : True
)) {
272 DLIST_PROMOTE(Files
, fsp
);
281 /****************************************************************************
282 Find the first fsp given a device and inode.
283 ****************************************************************************/
285 files_struct
*file_find_di_first(SMB_DEV_T dev
, SMB_INO_T inode
)
289 for (fsp
=Files
;fsp
;fsp
=fsp
->next
) {
291 fsp
->fd_ptr
!= NULL
&&
292 fsp
->fd_ptr
->dev
== dev
&&
293 fsp
->fd_ptr
->inode
== inode
)
300 /****************************************************************************
301 Find the next fsp having the same device and inode.
302 ****************************************************************************/
304 files_struct
*file_find_di_next(files_struct
*start_fsp
)
308 for (fsp
= start_fsp
->next
;fsp
;fsp
=fsp
->next
) {
310 fsp
->fd_ptr
!= NULL
&&
311 fsp
->fd_ptr
->dev
== start_fsp
->fd_ptr
->dev
&&
312 fsp
->fd_ptr
->inode
== start_fsp
->fd_ptr
->inode
)
319 /****************************************************************************
320 find a fsp that is open for printing
321 ****************************************************************************/
322 files_struct
*file_find_print(void)
326 for (fsp
=Files
;fsp
;fsp
=fsp
->next
) {
327 if (fsp
->open
&& fsp
->print_file
) return fsp
;
334 /****************************************************************************
335 sync open files on a connection
336 ****************************************************************************/
337 void file_sync_all(connection_struct
*conn
)
339 files_struct
*fsp
, *next
;
341 for (fsp
=Files
;fsp
;fsp
=next
) {
343 if (fsp
->open
&& (conn
== fsp
->conn
) && (fsp
->fd_ptr
!= NULL
)) {
350 /****************************************************************************
352 ****************************************************************************/
353 void fd_ptr_free(file_fd_struct
*fd_ptr
)
355 DLIST_REMOVE(FileFd
, fd_ptr
);
359 DEBUG(5,("freed fd_ptr structure (%d used)\n", fd_ptr_used
));
362 ZERO_STRUCTP(fd_ptr
);
368 /****************************************************************************
370 ****************************************************************************/
371 void file_free(files_struct
*fsp
)
373 DLIST_REMOVE(Files
, fsp
);
375 string_free(&fsp
->fsp_name
);
377 if ((fsp
->fd_ptr
!= NULL
) && fsp
->fd_ptr
->ref_count
== 0) {
378 fd_ptr_free(fsp
->fd_ptr
);
381 bitmap_clear(file_bmap
, fsp
->fnum
- FILE_HANDLE_OFFSET
);
384 DEBUG(5,("freed files structure %d (%d used)\n",
385 fsp
->fnum
, files_used
));
387 /* this is paranoia, just in case someone tries to reuse the
391 if (fsp
== chain_fsp
) chain_fsp
= NULL
;
397 /****************************************************************************
398 get a fsp from a packet given the offset of a 16 bit fnum
399 ****************************************************************************/
400 files_struct
*file_fsp(char *buf
, int where
)
405 if (chain_fsp
) return chain_fsp
;
407 fnum
= SVAL(buf
, where
);
409 for (fsp
=Files
;fsp
;fsp
=fsp
->next
, count
++) {
410 if (fsp
->fnum
== fnum
) {
413 DLIST_PROMOTE(Files
, fsp
);
421 /****************************************************************************
422 Reset the chained fsp - done at the start of a packet reply
423 ****************************************************************************/
425 void file_chain_reset(void)
430 /****************************************************************************
431 Save the chained fsp - done when about to do an oplock break.
432 ****************************************************************************/
434 void file_chain_save(void)
436 oplock_save_chain_fsp
= chain_fsp
;
439 /****************************************************************************
440 Restore the chained fsp - done after an oplock break.
441 ****************************************************************************/
442 void file_chain_restore(void)
444 chain_fsp
= oplock_save_chain_fsp
;