1998-08-15 11:27:34 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
Files [ ] structure handling
Copyright ( C ) Andrew Tridgell 1998
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
1998-09-30 05:49:24 +04:00
static int real_max_open_files ;
1998-08-15 11:27:34 +04:00
1998-09-30 05:49:24 +04:00
# define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))
1998-08-15 11:27:34 +04:00
1998-08-17 07:06:20 +04:00
# define FILE_HANDLE_OFFSET 0x1000
1998-08-16 08:08:47 +04:00
static struct bitmap * file_bmap ;
static files_struct * Files ;
1998-09-10 22:57:06 +04:00
1998-08-17 07:52:05 +04:00
/* a fsp to use when chaining */
static files_struct * chain_fsp = NULL ;
1998-08-18 02:59:53 +04:00
/* a fsp to use to save when breaking an oplock. */
static files_struct * oplock_save_chain_fsp = NULL ;
1998-08-17 07:52:05 +04:00
2000-04-10 17:05:23 +04:00
static int files_used ;
1998-08-15 11:27:34 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Return a unique number identifying this fsp over the life of this pid .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
static unsigned long get_gen_count ( void )
{
static unsigned long file_gen_counter ;
if ( ( + + file_gen_counter ) = = 0 )
return + + file_gen_counter ;
return file_gen_counter ;
}
/****************************************************************************
Find first available file slot .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-04-14 04:19:12 +04:00
files_struct * file_new ( connection_struct * conn )
1998-08-15 11:27:34 +04:00
{
int i ;
static int first_file ;
1998-08-17 10:13:32 +04:00
files_struct * fsp , * next ;
1998-08-15 11:27:34 +04:00
/* we want to give out file handles differently on each new
connection because of a common bug in MS clients where they try to
reuse a file descriptor from an earlier smb connection . This code
increases the chance that the errant client will get an error rather
than causing corruption */
if ( first_file = = 0 ) {
2000-05-02 06:23:41 +04:00
first_file = ( sys_getpid ( ) ^ ( int ) time ( NULL ) ) % real_max_open_files ;
1998-08-16 08:08:47 +04:00
}
1998-08-15 11:27:34 +04:00
1998-08-16 08:08:47 +04:00
i = bitmap_find ( file_bmap , first_file ) ;
if ( i = = - 1 ) {
/*
* Before we give up , go through the open files
* and see if there are any files opened with a
* batch oplock . If so break the oplock and then
* re - use that entry ( if it becomes closed ) .
* This may help as NT / 95 clients tend to keep
* files batch oplocked for quite a long time
* after they have finished with them .
*/
1998-08-17 10:13:32 +04:00
for ( fsp = Files ; fsp ; fsp = next ) {
next = fsp - > next ;
1998-08-16 08:08:47 +04:00
if ( attempt_close_oplocked_file ( fsp ) ) {
2001-04-14 04:19:12 +04:00
return file_new ( conn ) ;
1998-08-16 08:08:47 +04:00
}
1998-08-15 11:27:34 +04:00
}
1998-08-16 08:08:47 +04:00
DEBUG ( 0 , ( " ERROR! Out of file structures \n " ) ) ;
2000-04-22 04:33:16 +04:00
unix_ERR_class = ERRSRV ;
unix_ERR_code = ERRnofids ;
1998-08-16 08:08:47 +04:00
return NULL ;
}
1998-08-15 11:27:34 +04:00
1998-08-16 08:08:47 +04:00
fsp = ( files_struct * ) malloc ( sizeof ( * fsp ) ) ;
2000-04-22 04:33:16 +04:00
if ( ! fsp ) {
unix_ERR_class = ERRSRV ;
unix_ERR_code = ERRnofids ;
return NULL ;
}
1998-08-16 08:08:47 +04:00
1998-09-05 17:24:20 +04:00
ZERO_STRUCTP ( fsp ) ;
2000-04-10 17:12:04 +04:00
fsp - > fd = - 1 ;
2001-04-14 04:19:12 +04:00
fsp - > conn = conn ;
2001-10-21 01:59:34 +04:00
fsp - > file_id = get_gen_count ( ) ;
GetTimeOfDay ( & fsp - > open_time ) ;
1998-08-17 07:06:20 +04:00
1998-09-30 05:49:24 +04:00
first_file = ( i + 1 ) % real_max_open_files ;
1998-08-16 08:08:47 +04:00
bitmap_set ( file_bmap , i ) ;
files_used + + ;
1998-08-17 07:06:20 +04:00
fsp - > fnum = i + FILE_HANDLE_OFFSET ;
2000-01-16 14:18:04 +03:00
string_set ( & fsp - > fsp_name , " " ) ;
1998-08-16 08:08:47 +04:00
1998-08-17 10:47:53 +04:00
DLIST_ADD ( Files , fsp ) ;
1998-08-16 08:08:47 +04:00
1998-09-10 22:57:06 +04:00
DEBUG ( 5 , ( " allocated file structure %d, fnum = %d (%d used) \n " ,
i , fsp - > fnum , files_used ) ) ;
1998-08-17 07:52:05 +04:00
chain_fsp = fsp ;
1998-08-16 08:08:47 +04:00
return fsp ;
1998-08-15 11:27:34 +04:00
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Close all open files for a connection .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-15 11:27:34 +04:00
void file_close_conn ( connection_struct * conn )
{
1998-08-17 10:13:32 +04:00
files_struct * fsp , * next ;
1998-08-16 08:08:47 +04:00
1998-08-17 10:13:32 +04:00
for ( fsp = Files ; fsp ; fsp = next ) {
next = fsp - > next ;
2000-04-24 23:23:51 +04:00
if ( fsp - > conn = = conn ) {
1999-12-13 16:27:58 +03:00
close_file ( fsp , False ) ;
1998-08-16 08:08:47 +04:00
}
}
1998-08-15 11:27:34 +04:00
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Initialise file structures .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-30 05:49:24 +04:00
# define MAX_OPEN_FUDGEFACTOR 10
1998-08-15 11:27:34 +04:00
void file_init ( void )
{
2001-04-13 23:33:26 +04:00
int request_max_open_files = lp_max_open_files ( ) ;
1998-10-16 10:16:10 +04:00
int real_lim ;
1998-09-30 05:49:24 +04:00
1998-10-16 10:16:10 +04:00
/*
* Set the max_open files to be the requested
* max plus a fudgefactor to allow for the extra
* fd ' s we need such as log files etc . . .
*/
real_lim = set_maxfiles ( request_max_open_files + MAX_OPEN_FUDGEFACTOR ) ;
real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR ;
2001-04-13 23:33:26 +04:00
if ( real_max_open_files ! = request_max_open_files ) {
DEBUG ( 1 , ( " file_init: Information only: requested %d \
1998-10-16 10:16:10 +04:00
open files , % d are available . \ n " , request_max_open_files, real_max_open_files));
}
1998-09-30 05:49:24 +04:00
1998-10-05 05:57:03 +04:00
file_bmap = bitmap_allocate ( real_max_open_files ) ;
1998-09-30 05:49:24 +04:00
if ( ! file_bmap ) {
exit_server ( " out of memory in file_init " ) ;
}
1998-10-05 05:57:03 +04:00
1998-10-01 07:07:09 +04:00
/*
1999-12-13 16:27:58 +03:00
* Ensure that pipe_handle_oppset is set correctly .
1998-10-01 07:07:09 +04:00
*/
set_pipe_handle_offset ( real_max_open_files ) ;
1998-08-15 11:27:34 +04:00
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Close files open by a specified vuid .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-15 11:27:34 +04:00
void file_close_user ( int vuid )
{
1998-08-17 10:13:32 +04:00
files_struct * fsp , * next ;
1998-08-16 08:08:47 +04:00
1998-08-17 10:13:32 +04:00
for ( fsp = Files ; fsp ; fsp = next ) {
next = fsp - > next ;
2000-04-24 23:23:51 +04:00
if ( fsp - > vuid = = vuid ) {
1999-12-13 16:27:58 +03:00
close_file ( fsp , False ) ;
1998-08-15 11:27:34 +04:00
}
}
}
2001-10-21 01:59:34 +04:00
/****************************************************************************
Find a fsp given a file descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
files_struct * file_find_fd ( int fd )
{
int count = 0 ;
files_struct * fsp ;
for ( fsp = Files ; fsp ; fsp = fsp - > next , count + + ) {
if ( fsp - > fd = = fd ) {
if ( count > 10 ) {
DLIST_PROMOTE ( Files , fsp ) ;
}
return fsp ;
}
}
return NULL ;
}
1998-08-15 11:27:34 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Find a fsp given a device , inode and file_id .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-23 05:48:45 +04:00
2001-10-21 01:59:34 +04:00
files_struct * file_find_dif ( SMB_DEV_T dev , SMB_INO_T inode , unsigned long file_id )
1998-08-15 11:27:34 +04:00
{
1998-08-17 10:47:53 +04:00
int count = 0 ;
1998-08-16 08:08:47 +04:00
files_struct * fsp ;
1998-08-17 10:47:53 +04:00
for ( fsp = Files ; fsp ; fsp = fsp - > next , count + + ) {
2000-04-24 23:23:51 +04:00
if ( fsp - > fd ! = - 1 & &
2000-04-10 17:05:23 +04:00
fsp - > dev = = dev & &
fsp - > inode = = inode & &
2001-10-21 01:59:34 +04:00
fsp - > file_id = = file_id ) {
1998-08-17 10:47:53 +04:00
if ( count > 10 ) {
DLIST_PROMOTE ( Files , fsp ) ;
}
1998-08-15 11:27:34 +04:00
return fsp ;
}
1998-08-16 08:08:47 +04:00
}
1998-08-15 11:27:34 +04:00
return NULL ;
}
2000-04-24 23:23:51 +04:00
/****************************************************************************
Check if an fsp still exists .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
files_struct * file_find_fsp ( files_struct * orig_fsp )
{
files_struct * fsp ;
for ( fsp = Files ; fsp ; fsp = fsp - > next ) {
if ( fsp = = orig_fsp )
return fsp ;
}
return NULL ;
}
1998-10-23 07:34:50 +04:00
/****************************************************************************
Find the first fsp given a device and inode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
files_struct * file_find_di_first ( SMB_DEV_T dev , SMB_INO_T inode )
{
files_struct * fsp ;
for ( fsp = Files ; fsp ; fsp = fsp - > next ) {
2000-04-24 23:23:51 +04:00
if ( fsp - > fd ! = - 1 & &
2000-04-10 17:05:23 +04:00
fsp - > dev = = dev & &
fsp - > inode = = inode )
1998-10-23 07:34:50 +04:00
return fsp ;
}
return NULL ;
}
/****************************************************************************
Find the next fsp having the same device and inode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
files_struct * file_find_di_next ( files_struct * start_fsp )
{
files_struct * fsp ;
for ( fsp = start_fsp - > next ; fsp ; fsp = fsp - > next ) {
2000-04-24 23:23:51 +04:00
if ( fsp - > fd ! = - 1 & &
2000-04-10 17:05:23 +04:00
fsp - > dev = = start_fsp - > dev & &
fsp - > inode = = start_fsp - > inode )
1998-10-23 07:34:50 +04:00
return fsp ;
}
return NULL ;
}
1998-08-16 08:08:47 +04:00
1998-08-15 11:27:34 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Find a fsp that is open for printing .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-15 11:27:34 +04:00
files_struct * file_find_print ( void )
{
1998-08-16 08:08:47 +04:00
files_struct * fsp ;
1998-08-15 11:27:34 +04:00
1998-08-16 08:08:47 +04:00
for ( fsp = Files ; fsp ; fsp = fsp - > next ) {
2000-04-24 23:23:51 +04:00
if ( fsp - > print_file ) return fsp ;
1998-08-15 11:27:34 +04:00
}
1998-09-10 22:57:06 +04:00
1998-08-15 11:27:34 +04:00
return NULL ;
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Sync open files on a connection .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-15 11:27:34 +04:00
void file_sync_all ( connection_struct * conn )
{
1998-08-17 10:13:32 +04:00
files_struct * fsp , * next ;
1998-08-16 08:08:47 +04:00
1998-08-17 10:13:32 +04:00
for ( fsp = Files ; fsp ; fsp = next ) {
next = fsp - > next ;
2000-04-24 23:23:51 +04:00
if ( ( conn = = fsp - > conn ) & & ( fsp - > fd ! = - 1 ) ) {
2000-05-10 05:31:46 +04:00
sync_file ( conn , fsp ) ;
1998-08-15 11:27:34 +04:00
}
}
}
1998-08-16 08:08:47 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Free up a fsp .
1998-08-16 08:08:47 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-15 11:27:34 +04:00
void file_free ( files_struct * fsp )
{
1998-08-17 10:47:53 +04:00
DLIST_REMOVE ( Files , fsp ) ;
1998-08-16 08:08:47 +04:00
string_free ( & fsp - > fsp_name ) ;
1998-08-17 07:06:20 +04:00
bitmap_clear ( file_bmap , fsp - > fnum - FILE_HANDLE_OFFSET ) ;
1998-08-16 08:08:47 +04:00
files_used - - ;
DEBUG ( 5 , ( " freed files structure %d (%d used) \n " ,
fsp - > fnum , files_used ) ) ;
/* this is paranoia, just in case someone tries to reuse the
information */
1998-09-05 17:24:20 +04:00
ZERO_STRUCTP ( fsp ) ;
1998-08-16 08:08:47 +04:00
1998-08-17 07:52:05 +04:00
if ( fsp = = chain_fsp ) chain_fsp = NULL ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( fsp ) ;
1998-08-15 11:27:34 +04:00
}
1998-08-17 07:52:05 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Get a fsp from a packet given the offset of a 16 bit fnum .
1998-08-17 07:52:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-17 07:52:05 +04:00
files_struct * file_fsp ( char * buf , int where )
{
1998-08-17 10:47:53 +04:00
int fnum , count = 0 ;
1998-08-17 07:52:05 +04:00
files_struct * fsp ;
2001-10-21 01:59:34 +04:00
if ( chain_fsp )
return chain_fsp ;
1998-08-17 07:52:05 +04:00
fnum = SVAL ( buf , where ) ;
1998-08-17 10:47:53 +04:00
for ( fsp = Files ; fsp ; fsp = fsp - > next , count + + ) {
1998-08-17 07:52:05 +04:00
if ( fsp - > fnum = = fnum ) {
chain_fsp = fsp ;
1998-08-17 10:47:53 +04:00
if ( count > 10 ) {
DLIST_PROMOTE ( Files , fsp ) ;
}
1998-08-17 07:52:05 +04:00
return fsp ;
}
}
return NULL ;
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Reset the chained fsp - done at the start of a packet reply .
1998-08-17 07:52:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-20 23:28:37 +04:00
1998-08-17 07:52:05 +04:00
void file_chain_reset ( void )
{
chain_fsp = NULL ;
}
1998-08-18 02:59:53 +04:00
/****************************************************************************
Save the chained fsp - done when about to do an oplock break .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void file_chain_save ( void )
{
oplock_save_chain_fsp = chain_fsp ;
}
/****************************************************************************
Restore the chained fsp - done after an oplock break .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-18 02:59:53 +04:00
void file_chain_restore ( void )
{
chain_fsp = oplock_save_chain_fsp ;
}