@ -7,19 +7,26 @@
# include "string.h"
# include "macros.h"
# include "variables.h"
# include "debug.h"
/*************************************************/
/* FILE IO ROUTINES ******************************/
/*************************************************/
# define FIO_BUFFER_SIZE 512
# define MAX_HANDLES 64
typedef struct {
byte * buffer , * buffer_end ; ///< position pointer in local buffer and last valid byte of buffer
uint32 pos ; ///< current (system) position in file
FILE * cur_fh ; ///< current file handle
FILE * handles [ 64 ] ; ///< array of file handles we can have open
FILE * handles [ MAX_HANDLES ] ; ///< array of file handles we can have open
byte buffer_start [ FIO_BUFFER_SIZE ] ; ///< local buffer when read from file
# if defined(LIMITED_FDS)
uint open_handles ; ///< current amount of open handles
const char * filename [ MAX_HANDLES ] ; ///< array of filenames we (should) have open
uint usage_count [ MAX_HANDLES ] ; ///< count how many times this file has been opened
# endif /* LIMITED_FDS */
} Fio ;
static Fio _fio ;
@ -38,10 +45,27 @@ void FioSeekTo(uint32 pos, int mode)
fseek ( _fio . cur_fh , _fio . pos , SEEK_SET ) ;
}
# if defined(LIMITED_FDS)
static void FioRestoreFile ( int slot )
{
/* Do we still have the file open, or should we reopen it? */
if ( _fio . handles [ slot ] = = NULL ) {
DEBUG ( misc , 6 , " Restoring file '%s' in slot '%d' from disk " , _fio . filename [ slot ] , slot ) ;
FioOpenFile ( slot , _fio . filename [ slot ] ) ;
}
_fio . usage_count [ slot ] + + ;
}
# endif /* LIMITED_FDS */
// Seek to a file and a position
void FioSeekToFile ( uint32 pos )
{
FILE * f = _fio . handles [ pos > > 24 ] ;
FILE * f ;
# if defined(LIMITED_FDS)
/* Make sure we have this file open */
FioRestoreFile ( pos > > 24 ) ;
# endif /* LIMITED_FDS */
f = _fio . handles [ pos > > 24 ] ;
assert ( f ! = NULL ) ;
_fio . cur_fh = f ;
FioSeekTo ( GB ( pos , 0 , 24 ) , SEEK_SET ) ;
@ -92,6 +116,9 @@ static inline void FioCloseFile(int slot)
if ( _fio . handles [ slot ] ! = NULL ) {
fclose ( _fio . handles [ slot ] ) ;
_fio . handles [ slot ] = NULL ;
# if defined(LIMITED_FDS)
_fio . open_handles - - ;
# endif /* LIMITED_FDS */
}
}
@ -112,6 +139,30 @@ bool FioCheckFileExists(const char *filename)
return true ;
}
# if defined(LIMITED_FDS)
static void FioFreeHandle ( )
{
/* If we are about to open a file that will exceed the limit, close a file */
if ( _fio . open_handles + 1 = = LIMITED_FDS ) {
uint i , count ;
int slot ;
count = UINT_MAX ;
slot = - 1 ;
/* Find the file that is used the least */
for ( i = 0 ; i < lengthof ( _fio . handles ) ; i + + ) {
if ( _fio . handles [ i ] ! = NULL & & _fio . usage_count [ i ] < count ) {
count = _fio . usage_count [ i ] ;
slot = i ;
}
}
assert ( slot ! = - 1 ) ;
DEBUG ( misc , 6 , " Closing filehandler '%s' in slot '%d' because of fd-limit " , _fio . filename [ slot ] , slot ) ;
FioCloseFile ( slot ) ;
}
}
# endif /* LIMITED_FDS */
FILE * FioFOpenFile ( const char * filename )
{
FILE * f ;
@ -141,11 +192,20 @@ FILE *FioFOpenFile(const char *filename)
void FioOpenFile ( int slot , const char * filename )
{
FILE * f = FioFOpenFile ( filename ) ;
FILE * f ;
# if defined(LIMITED_FDS)
FioFreeHandle ( ) ;
# endif /* LIMITED_FDS */
f = FioFOpenFile ( filename ) ;
if ( f = = NULL ) error ( " Cannot open file '%s%s' " , _paths . data_dir , filename ) ;
FioCloseFile ( slot ) ; // if file was opened before, close it
_fio . handles [ slot ] = f ;
# if defined(LIMITED_FDS)
_fio . filename [ slot ] = filename ;
_fio . usage_count [ slot ] = 0 ;
_fio . open_handles + + ;
# endif /* LIMITED_FDS */
FioSeekToFile ( slot < < 24 ) ;
}