//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
# ifndef FILESYSTEM_H
# define FILESYSTEM_H
# pragma once
# include <limits.h>
# include "tier0/threadtools.h"
# include "tier0/memalloc.h"
# include "tier1/interface.h"
# include "tier1/utlsymbol.h"
# include "tier1/utlstring.h"
# include "appframework/IAppSystem.h"
# include "tier1/checksum_crc.h"
# include "tier1/checksum_md5.h"
# include "tier1/refcount.h"
# include <time.h>
# ifdef _WIN32
# pragma once
# endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CUtlBuffer ;
class KeyValues ;
class IFileList ;
class IThreadPool ;
class CMemoryFileBacking ;
typedef void * FileHandle_t ;
typedef void * FileCacheHandle_t ;
typedef int FileFindHandle_t ;
typedef void ( * FileSystemLoggingFunc_t ) ( const char * fileName , const char * accessType ) ;
typedef int WaitForResourcesHandle_t ;
# ifdef _X360
typedef void * HANDLE ;
# endif
# define USE_CRC_FILE_TRACKING 0
// Turn on some extra pure server debug spew in certain builds.
// WARNING: This spew can be used by hackers to locate places to hack
// the code to bypas sv_pure! Be careful!
# if defined( _DEBUG ) || defined( STAGING_ONLY )
# define PURE_SERVER_DEBUG_SPEW
# endif
/// How strict will the pure server be for a particular set of files
enum EPureServerFileClass
{
ePureServerFileClass_Unknown = - 1 , // dummy debugging value
ePureServerFileClass_Any = 0 ,
ePureServerFileClass_AnyTrusted ,
ePureServerFileClass_CheckHash ,
} ;
class IPureServerWhitelist
{
public :
// Reference counting
virtual void AddRef ( ) = 0 ;
virtual void Release ( ) = 0 ;
// What should we do with a particular file?
virtual EPureServerFileClass GetFileClass ( const char * pszFilename ) = 0 ;
// Access list of trusted keys which we will allow to set trusted content
virtual int GetTrustedKeyCount ( ) const = 0 ;
virtual const byte * GetTrustedKey ( int iKeyIndex , int * nKeySize ) const = 0 ;
} ;
//-----------------------------------------------------------------------------
// Enums used by the interface
//-----------------------------------------------------------------------------
# define FILESYSTEM_MAX_SEARCH_PATHS 128
enum FileSystemSeek_t
{
FILESYSTEM_SEEK_HEAD = SEEK_SET ,
FILESYSTEM_SEEK_CURRENT = SEEK_CUR ,
FILESYSTEM_SEEK_TAIL = SEEK_END ,
} ;
enum
{
FILESYSTEM_INVALID_FIND_HANDLE = - 1
} ;
enum FileWarningLevel_t
{
// A problem!
FILESYSTEM_WARNING = - 1 ,
// Don't print anything
FILESYSTEM_WARNING_QUIET = 0 ,
// On shutdown, report names of files left unclosed
FILESYSTEM_WARNING_REPORTUNCLOSED ,
// Report number of times a file was opened, closed
FILESYSTEM_WARNING_REPORTUSAGE ,
// Report all open/close events to console ( !slow! )
FILESYSTEM_WARNING_REPORTALLACCESSES ,
// Report all open/close/read events to the console ( !slower! )
FILESYSTEM_WARNING_REPORTALLACCESSES_READ ,
// Report all open/close/read/write events to the console ( !slower! )
FILESYSTEM_WARNING_REPORTALLACCESSES_READWRITE ,
// Report all open/close/read/write events and all async I/O file events to the console ( !slower(est)! )
FILESYSTEM_WARNING_REPORTALLACCESSES_ASYNC ,
} ;
// search path filtering
enum PathTypeFilter_t
{
FILTER_NONE = 0 , // no filtering, all search path types match
FILTER_CULLPACK = 1 , // pack based search paths are culled (maps and zips)
FILTER_CULLNONPACK = 2 , // non-pack based search paths are culled
} ;
// search path querying (bit flags)
enum
{
PATH_IS_NORMAL = 0x00 , // normal path, not pack based
PATH_IS_PACKFILE = 0x01 , // path is a pack file
PATH_IS_MAPPACKFILE = 0x02 , // path is a map pack file
PATH_IS_REMOTE = 0x04 , // path is the remote filesystem
} ;
typedef uint32 PathTypeQuery_t ;
# define IS_PACKFILE( n ) ( n & ( PATH_IS_PACKFILE | PATH_IS_MAPPACKFILE ) )
# define IS_REMOTE( n ) ( n & PATH_IS_REMOTE )
enum DVDMode_t
{
DVDMODE_OFF = 0 , // not using dvd
DVDMODE_STRICT = 1 , // dvd device only
DVDMODE_DEV = 2 , // dev mode, mutiple devices ok
} ;
// In non-retail builds, enable the file blocking access tracking stuff...
# if defined( TRACK_BLOCKING_IO )
enum FileBlockingWarning_t
{
// Report how long synchronous i/o took to complete
FILESYSTEM_BLOCKING_SYNCHRONOUS = 0 ,
// Report how long async i/o took to complete if AsyncFileFinished caused it to load via "blocking" i/o
FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK ,
// Report how long async i/o took to complete
FILESYSTEM_BLOCKING_ASYNCHRONOUS ,
// Report how long the async "callback" took
FILESYSTEM_BLOCKING_CALLBACKTIMING ,
FILESYSTEM_BLOCKING_NUMBINS ,
} ;
# pragma pack(1)
class FileBlockingItem
{
public :
enum
{
FB_ACCESS_OPEN = 1 ,
FB_ACCESS_CLOSE = 2 ,
FB_ACCESS_READ = 3 ,
FB_ACCESS_WRITE = 4 ,
FB_ACCESS_APPEND = 5 ,
FB_ACCESS_SIZE = 6
} ;
FileBlockingItem ( ) :
m_ItemType ( ( FileBlockingWarning_t ) 0 ) ,
m_flElapsed ( 0.0f ) ,
m_nAccessType ( 0 )
{
SetFileName ( NULL ) ;
}
FileBlockingItem ( int type , char const * filename , float elapsed , int accessType ) :
m_ItemType ( ( FileBlockingWarning_t ) type ) ,
m_flElapsed ( elapsed ) ,
m_nAccessType ( accessType )
{
SetFileName ( filename ) ;
}
void SetFileName ( char const * filename )
{
if ( ! filename )
{
m_szFilename [ 0 ] = 0 ;
return ;
}
int len = Q_strlen ( filename ) ;
if ( len > = sizeof ( m_szFilename ) )
{
Q_strncpy ( m_szFilename , & filename [ len - sizeof ( m_szFilename ) + 1 ] , sizeof ( m_szFilename ) ) ;
}
else
{
Q_strncpy ( m_szFilename , filename , sizeof ( m_szFilename ) ) ;
}
}
char const * GetFileName ( ) const
{
return m_szFilename ;
}
FileBlockingWarning_t m_ItemType ;
float m_flElapsed ;
byte m_nAccessType ;
private :
char m_szFilename [ 32 ] ;
} ;
# pragma pack()
class IBlockingFileItemList
{
public :
// You can't call any of the below calls without locking first
virtual void LockMutex ( ) = 0 ;
virtual void UnlockMutex ( ) = 0 ;
virtual int First ( ) const = 0 ;
virtual int Next ( int i ) const = 0 ;
virtual int InvalidIndex ( ) const = 0 ;
virtual const FileBlockingItem & Get ( int index ) const = 0 ;
virtual void Reset ( ) = 0 ;
} ;
# endif // TRACK_BLOCKING_IO
enum FilesystemMountRetval_t
{
FILESYSTEM_MOUNT_OK = 0 ,
FILESYSTEM_MOUNT_FAILED ,
} ;
enum SearchPathAdd_t
{
PATH_ADD_TO_HEAD , // First path searched
PATH_ADD_TO_TAIL , // Last path searched
} ;
enum FilesystemOpenExFlags_t
{
FSOPEN_UNBUFFERED = ( 1 < < 0 ) ,
FSOPEN_FORCE_TRACK_CRC = ( 1 < < 1 ) , // This makes it calculate a CRC for the file (if the file came from disk) regardless
// of the IFileList passed to RegisterFileWhitelist.
FSOPEN_NEVERINPACK = ( 1 < < 2 ) , // 360 only, hint to FS that file is not allowed to be in pack file
} ;
# define FILESYSTEM_INVALID_HANDLE ( FileHandle_t )0
//-----------------------------------------------------------------------------
// Structures used by the interface
//-----------------------------------------------------------------------------
struct FileSystemStatistics
{
CInterlockedUInt nReads ,
nWrites ,
nBytesRead ,
nBytesWritten ,
nSeeks ;
} ;
//-----------------------------------------------------------------------------
// File system allocation functions. Client must free on failure
//-----------------------------------------------------------------------------
typedef void * ( * FSAllocFunc_t ) ( const char * pszFilename , unsigned nBytes ) ;
//-----------------------------------------------------------------------------
// Used to display dirty disk error functions
//-----------------------------------------------------------------------------
typedef void ( * FSDirtyDiskReportFunc_t ) ( ) ;
//-----------------------------------------------------------------------------
// Asynchronous support types
//-----------------------------------------------------------------------------
DECLARE_POINTER_HANDLE ( FSAsyncControl_t ) ;
DECLARE_POINTER_HANDLE ( FSAsyncFile_t ) ;
const FSAsyncFile_t FS_INVALID_ASYNC_FILE = ( FSAsyncFile_t ) ( 0x0000ffff ) ;
//---------------------------------------------------------
// Async file status
//---------------------------------------------------------
enum FSAsyncStatus_t
{
FSASYNC_ERR_NOT_MINE = - 8 , // Filename not part of the specified file system, try a different one. (Used internally to find the right filesystem)
FSASYNC_ERR_RETRY_LATER = - 7 , // Failure for a reason that might be temporary. You might retry, but not immediately. (E.g. Network problems)
FSASYNC_ERR_ALIGNMENT = - 6 , // read parameters invalid for unbuffered IO
FSASYNC_ERR_FAILURE = - 5 , // hard subsystem failure
FSASYNC_ERR_READING = - 4 , // read error on file
FSASYNC_ERR_NOMEMORY = - 3 , // out of memory for file read
FSASYNC_ERR_UNKNOWNID = - 2 , // caller's provided id is not recognized
FSASYNC_ERR_FILEOPEN = - 1 , // filename could not be opened (bad path, not exist, etc)
FSASYNC_OK = 0 , // operation is successful
FSASYNC_STATUS_PENDING , // file is properly queued, waiting for service
FSASYNC_STATUS_INPROGRESS , // file is being accessed
FSASYNC_STATUS_ABORTED , // file was aborted by caller
FSASYNC_STATUS_UNSERVICED , // file is not yet queued
} ;
//---------------------------------------------------------
// Async request flags
//---------------------------------------------------------
enum FSAsyncFlags_t
{
FSASYNC_FLAGS_ALLOCNOFREE = ( 1 < < 0 ) , // do the allocation for dataPtr, but don't free
FSASYNC_FLAGS_FREEDATAPTR = ( 1 < < 1 ) , // free the memory for the dataPtr post callback
FSASYNC_FLAGS_SYNC = ( 1 < < 2 ) , // Actually perform the operation synchronously. Used to simplify client code paths
FSASYNC_FLAGS_NULLTERMINATE = ( 1 < < 3 ) , // allocate an extra byte and null terminate the buffer read in
} ;
//---------------------------------------------------------
// Return value for CheckFileCRC.
//---------------------------------------------------------
enum EFileCRCStatus
{
k_eFileCRCStatus_CantOpenFile , // We don't have this file.
k_eFileCRCStatus_GotCRC ,
k_eFileCRCStatus_FileInVPK
} ;
// Used in CacheFileCRCs.
enum ECacheCRCType
{
k_eCacheCRCType_SingleFile ,
k_eCacheCRCType_Directory ,
k_eCacheCRCType_Directory_Recursive
} ;
//---------------------------------------------------------
// Optional completion callback for each async file serviced (or failed)
// call is not reentrant, async i/o guaranteed suspended until return
// Note: If you change the signature of the callback, you will have to account for it in FileSystemV12 (toml [4/18/2005] )
//---------------------------------------------------------
struct FileAsyncRequest_t ;
typedef void ( * FSAsyncCallbackFunc_t ) ( const FileAsyncRequest_t & request , int nBytesRead , FSAsyncStatus_t err ) ;
//---------------------------------------------------------
// Description of an async request
//---------------------------------------------------------
struct FileAsyncRequest_t
{
FileAsyncRequest_t ( ) { memset ( this , 0 , sizeof ( * this ) ) ; hSpecificAsyncFile = FS_INVALID_ASYNC_FILE ; }
const char * pszFilename ; // file system name
void * pData ; // optional, system will alloc/free if NULL
int nOffset ; // optional initial seek_set, 0=beginning
int nBytes ; // optional read clamp, -1=exist test, 0=full read
FSAsyncCallbackFunc_t pfnCallback ; // optional completion callback
void * pContext ; // caller's unique file identifier
int priority ; // inter list priority, 0=lowest
unsigned flags ; // behavior modifier
const char * pszPathID ; // path ID (NOTE: this field is here to remain binary compatible with release HL2 filesystem interface)
FSAsyncFile_t hSpecificAsyncFile ; // Optional hint obtained using AsyncBeginRead()
FSAllocFunc_t pfnAlloc ; // custom allocator. can be null. not compatible with FSASYNC_FLAGS_FREEDATAPTR
} ;
struct FileHash_t
{
enum EFileHashType_t
{
k_EFileHashTypeUnknown = 0 ,
k_EFileHashTypeEntireFile = 1 ,
k_EFileHashTypeIncompleteFile = 2 ,
} ;
FileHash_t ( )
{
m_eFileHashType = FileHash_t : : k_EFileHashTypeUnknown ;
m_cbFileLen = 0 ;
m_PackFileID = 0 ;
m_nPackFileNumber = 0 ;
}
int m_eFileHashType ;
CRC32_t m_crcIOSequence ;
MD5Value_t m_md5contents ;
int m_cbFileLen ;
int m_PackFileID ;
int m_nPackFileNumber ;
bool operator = = ( const FileHash_t & src ) const
{
return m_crcIOSequence = = src . m_crcIOSequence & &
m_md5contents = = src . m_md5contents & &
m_eFileHashType = = src . m_eFileHashType ;
}
bool operator ! = ( const FileHash_t & src ) const
{
return m_crcIOSequence ! = src . m_crcIOSequence | |
m_md5contents ! = src . m_md5contents | |
m_eFileHashType ! = src . m_eFileHashType ;
}
} ;
class CUnverifiedFileHash
{
public :
char m_PathID [ MAX_PATH ] ;
char m_Filename [ MAX_PATH ] ;
int m_nFileFraction ;
FileHash_t m_FileHash ;
} ;
class CUnverifiedCRCFile
{
public :
char m_PathID [ MAX_PATH ] ;
char m_Filename [ MAX_PATH ] ;
CRC32_t m_CRC ;
} ;
class CUnverifiedMD5File
{
public :
char m_PathID [ MAX_PATH ] ;
char m_Filename [ MAX_PATH ] ;
unsigned char bits [ MD5_DIGEST_LENGTH ] ;
} ;
// Spew flags for SetWhitelistSpewFlags (set with the fs_whitelist_spew_flags cvar).
// Update the comment for the fs_whitelist_spew_flags cvar if you change these.
# define WHITELIST_SPEW_WHILE_LOADING 0x0001 // list files as they are added to the CRC tracker
# define WHITELIST_SPEW_RELOAD_FILES 0x0002 // show files the filesystem is telling the engine to reload
# define WHITELIST_SPEW_DONT_RELOAD_FILES 0x0004 // show files the filesystem is NOT telling the engine to reload
//-----------------------------------------------------------------------------
// Interface to fetch a file asynchronously from any source. This is used
// as a hook
//-----------------------------------------------------------------------------
abstract_class IAsyncFileFetch {
public :
typedef void * Handle ;
/// Initiate a request. Returns error status, or on success
/// returns an opaque handle used to terminate the job
///
/// Should return FSASYNC_ERR_NOT_MINE if the filename isn't
/// handled by this interface
///
/// The callback is required, and is the only mechanism to communicate
/// status. (No polling.) The request is automatically destroyed anytime
/// after the callback is executed.
virtual FSAsyncStatus_t Start ( const FileAsyncRequest_t & request , Handle * pOutHandle , IThreadPool * pThreadPool ) = 0 ;
/// Attempt to complete any active work, returning status. The callback WILL
/// be executed (this is necessary in case we allocated the buffer).
/// Afterwards, the request is automatically destroyed.
virtual FSAsyncStatus_t FinishSynchronous ( Handle hControl ) = 0 ;
/// Terminate any active work and destroy all resources and bookkeeping info.
/// The callback will NOT be executed.
virtual FSAsyncStatus_t Abort ( Handle hControl ) = 0 ;
} ;
// This interface is for VPK files to communicate with FileTracker
abstract_class IThreadedFileMD5Processor
{
public :
virtual int SubmitThreadedMD5Request ( uint8 * pubBuffer , int cubBuffer , int PackFileID , int nPackFileNumber , int nPackFileFraction ) = 0 ;
virtual bool BlockUntilMD5RequestComplete ( int iRequest , MD5Value_t * pMd5ValueOut ) = 0 ;
virtual bool IsMD5RequestComplete ( int iRequest , MD5Value_t * pMd5ValueOut ) = 0 ;
} ;
//-----------------------------------------------------------------------------
// Base file system interface
//-----------------------------------------------------------------------------
// This is the minimal interface that can be implemented to provide access to
// a named set of files.
# define BASEFILESYSTEM_INTERFACE_VERSION "VBaseFileSystem011"
abstract_class IBaseFileSystem
{
public :
virtual int Read ( void * pOutput , int size , FileHandle_t file ) = 0 ;
virtual int Write ( void const * pInput , int size , FileHandle_t file ) = 0 ;
// if pathID is NULL, all paths will be searched for the file
virtual FileHandle_t Open ( const char * pFileName , const char * pOptions , const char * pathID = 0 ) = 0 ;
virtual void Close ( FileHandle_t file ) = 0 ;
virtual void Seek ( FileHandle_t file , int pos , FileSystemSeek_t seekType ) = 0 ;
virtual unsigned int Tell ( FileHandle_t file ) = 0 ;
virtual unsigned int Size ( FileHandle_t file ) = 0 ;
virtual unsigned int Size ( const char * pFileName , const char * pPathID = 0 ) = 0 ;
virtual void Flush ( FileHandle_t file ) = 0 ;
virtual bool Precache ( const char * pFileName , const char * pPathID = 0 ) = 0 ;
virtual bool FileExists ( const char * pFileName , const char * pPathID = 0 ) = 0 ;
virtual bool IsFileWritable ( char const * pFileName , const char * pPathID = 0 ) = 0 ;
virtual bool SetFileWritable ( char const * pFileName , bool writable , const char * pPathID = 0 ) = 0 ;
virtual time_t GetFileTime ( const char * pFileName , const char * pPathID = 0 ) = 0 ;
//--------------------------------------------------------
// Reads/writes files to utlbuffers. Use this for optimal read performance when doing open/read/close
//--------------------------------------------------------
virtual bool ReadFile ( const char * pFileName , const char * pPath , CUtlBuffer & buf , int nMaxBytes = 0 , int nStartingByte = 0 , FSAllocFunc_t pfnAlloc = NULL ) = 0 ;
virtual bool WriteFile ( const char * pFileName , const char * pPath , CUtlBuffer & buf ) = 0 ;
virtual bool UnzipFile ( const char * pFileName , const char * pPath , const char * pDestination ) = 0 ;
} ;
//-----------------------------------------------------------------------------
// Main file system interface
//-----------------------------------------------------------------------------
# define FILESYSTEM_INTERFACE_VERSION "VFileSystem022"
abstract_class IFileSystem : public IAppSystem , public IBaseFileSystem
{
public :
//--------------------------------------------------------
// Steam operations
//--------------------------------------------------------
virtual bool IsSteam ( ) const = 0 ;
// Supplying an extra app id will mount this app in addition
// to the one specified in the environment variable "steamappid"
//
// If nExtraAppId is < -1, then it will mount that app ID only.
// (Was needed by the dedicated server b/c the "SteamAppId" env var only gets passed to steam.dll
// at load time, so the dedicated couldn't pass it in that way).
virtual FilesystemMountRetval_t MountSteamContent ( int nExtraAppId = - 1 ) = 0 ;
//--------------------------------------------------------
// Search path manipulation
//--------------------------------------------------------
// Add paths in priority order (mod dir, game dir, ....)
// If one or more .pak files are in the specified directory, then they are
// added after the file system path
// If the path is the relative path to a .bsp file, then any previous .bsp file
// override is cleared and the current .bsp is searched for an embedded PAK file
// and this file becomes the highest priority search path ( i.e., it's looked at first
// even before the mod's file system path ).
virtual void AddSearchPath ( const char * pPath , const char * pathID , SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0 ;
virtual bool RemoveSearchPath ( const char * pPath , const char * pathID = 0 ) = 0 ;
// Remove all search paths (including write path?)
virtual void RemoveAllSearchPaths ( void ) = 0 ;
// Remove search paths associated with a given pathID
virtual void RemoveSearchPaths ( const char * szPathID ) = 0 ;
// This is for optimization. If you mark a path ID as "by request only", then files inside it
// will only be accessed if the path ID is specifically requested. Otherwise, it will be ignored.
// If there are currently no search paths with the specified path ID, then it will still
// remember it in case you add search paths with this path ID.
virtual void MarkPathIDByRequestOnly ( const char * pPathID , bool bRequestOnly ) = 0 ;
// converts a partial path into a full path
// Prefer using the RelativePathToFullPath_safe template wrapper to calling this directly
virtual const char * RelativePathToFullPath ( const char * pFileName , const char * pPathID , OUT_Z_CAP ( maxLenInChars ) char * pDest , int maxLenInChars , PathTypeFilter_t pathFilter = FILTER_NONE , PathTypeQuery_t * pPathType = NULL ) = 0 ;
template < size_t maxLenInChars > const char * RelativePathToFullPath_safe ( const char * pFileName , const char * pPathID , OUT_Z_ARRAY char ( & pDest ) [ maxLenInChars ] , PathTypeFilter_t pathFilter = FILTER_NONE , PathTypeQuery_t * pPathType = NULL )
{
return RelativePathToFullPath ( pFileName , pPathID , pDest , ( int ) maxLenInChars , pathFilter , pPathType ) ;
}
// Returns the search path, each path is separated by ;s. Returns the length of the string returned
// Prefer using the GetSearchPath_safe template wrapper to calling this directly
virtual int GetSearchPath ( const char * pathID , bool bGetPackFiles , OUT_Z_CAP ( maxLenInChars ) char * pDest , int maxLenInChars ) = 0 ;
template < size_t maxLenInChars > int GetSearchPath_safe ( const char * pathID , bool bGetPackFiles , OUT_Z_ARRAY char ( & pDest ) [ maxLenInChars ] )
{
return GetSearchPath ( pathID , bGetPackFiles , pDest , ( int ) maxLenInChars ) ;
}
// interface for custom pack files > 4Gb
virtual bool AddPackFile ( const char * fullpath , const char * pathID ) = 0 ;
//--------------------------------------------------------
// File manipulation operations
//--------------------------------------------------------
// Deletes a file (on the WritePath)
virtual void RemoveFile ( char const * pRelativePath , const char * pathID = 0 ) = 0 ;
// Renames a file (on the WritePath)
virtual bool RenameFile ( char const * pOldPath , char const * pNewPath , const char * pathID = 0 ) = 0 ;
// create a local directory structure
virtual void CreateDirHierarchy ( const char * path , const char * pathID = 0 ) = 0 ;
// File I/O and info
virtual bool IsDirectory ( const char * pFileName , const char * pathID = 0 ) = 0 ;
virtual void FileTimeToString ( char * pStrip , int maxCharsIncludingTerminator , time_t fileTime ) = 0 ;
//--------------------------------------------------------
// Open file operations
//--------------------------------------------------------
virtual void SetBufferSize ( FileHandle_t file , unsigned nBytes ) = 0 ;
virtual bool IsOk ( FileHandle_t file ) = 0 ;
virtual bool EndOfFile ( FileHandle_t file ) = 0 ;
virtual char * ReadLine ( char * pOutput , int maxChars , FileHandle_t file ) = 0 ;
virtual int FPrintf ( FileHandle_t file , PRINTF_FORMAT_STRING const char * pFormat , . . . ) = 0 ;
//--------------------------------------------------------
// Dynamic library operations
//--------------------------------------------------------
// load/unload modules
virtual CSysModule * LoadModule ( const char * pFileName , const char * pPathID = 0 , bool bValidatedDllOnly = true ) = 0 ;
virtual void UnloadModule ( CSysModule * pModule ) = 0 ;
//--------------------------------------------------------
// File searching operations
//--------------------------------------------------------
// FindFirst/FindNext. Also see FindFirstEx.
virtual const char * FindFirst ( const char * pWildCard , FileFindHandle_t * pHandle ) = 0 ;
virtual const char * FindNext ( FileFindHandle_t handle ) = 0 ;
virtual bool FindIsDirectory ( FileFindHandle_t handle ) = 0 ;
virtual void FindClose ( FileFindHandle_t handle ) = 0 ;
// Same as FindFirst, but you can filter by path ID, which can make it faster.
virtual const char * FindFirstEx (
const char * pWildCard ,
const char * pPathID ,
FileFindHandle_t * pHandle
) = 0 ;
//--------------------------------------------------------
// File name and directory operations
//--------------------------------------------------------
// FIXME: This method is obsolete! Use RelativePathToFullPath instead!
// converts a partial path into a full path
// Prefer using the GetLocalPath_safe template wrapper to calling this directly
virtual const char * GetLocalPath ( const char * pFileName , OUT_Z_CAP ( maxLenInChars ) char * pDest , int maxLenInChars ) = 0 ;
template < size_t maxLenInChars > const char * GetLocalPath_safe ( const char * pFileName , OUT_Z_ARRAY char ( & pDest ) [ maxLenInChars ] )
{
return GetLocalPath ( pFileName , pDest , ( int ) maxLenInChars ) ;
}
// Returns true on success ( based on current list of search paths, otherwise false if
// it can't be resolved )
// Prefer using the FullPathToRelativePath_safe template wrapper to calling this directly
virtual bool FullPathToRelativePath ( const char * pFullpath , OUT_Z_CAP ( maxLenInChars ) char * pDest , int maxLenInChars ) = 0 ;
template < size_t maxLenInChars > bool FullPathToRelativePath_safe ( const char * pFullpath , OUT_Z_ARRAY char ( & pDest ) [ maxLenInChars ] )
{
return FullPathToRelativePath ( pFullpath , pDest , ( int ) maxLenInChars ) ;
}
// Gets the current working directory
virtual bool GetCurrentDirectory ( char * pDirectory , int maxlen ) = 0 ;
//--------------------------------------------------------
// Filename dictionary operations
//--------------------------------------------------------
virtual FileNameHandle_t FindOrAddFileName ( char const * pFileName ) = 0 ;
virtual bool String ( const FileNameHandle_t & handle , char * buf , int buflen ) = 0 ;
//--------------------------------------------------------
// Asynchronous file operations
//--------------------------------------------------------
//------------------------------------
// Global operations
//------------------------------------
FSAsyncStatus_t AsyncRead ( const FileAsyncRequest_t & request , FSAsyncControl_t * phControl = NULL ) { return AsyncReadMultiple ( & request , 1 , phControl ) ; }
virtual FSAsyncStatus_t AsyncReadMultiple ( const FileAsyncRequest_t * pRequests , int nRequests , FSAsyncControl_t * phControls = NULL ) = 0 ;
virtual FSAsyncStatus_t AsyncAppend ( const char * pFileName , const void * pSrc , int nSrcBytes , bool bFreeMemory , FSAsyncControl_t * pControl = NULL ) = 0 ;
virtual FSAsyncStatus_t AsyncAppendFile ( const char * pAppendToFileName , const char * pAppendFromFileName , FSAsyncControl_t * pControl = NULL ) = 0 ;
virtual void AsyncFinishAll ( int iToPriority = 0 ) = 0 ;
virtual void AsyncFinishAllWrites ( ) = 0 ;
virtual FSAsyncStatus_t AsyncFlush ( ) = 0 ;
virtual bool AsyncSuspend ( ) = 0 ;
virtual bool AsyncResume ( ) = 0 ;
/// Add async fetcher interface. This gives apps a hook to intercept async requests and
/// pull the data from a source of their choosing. The immediate use case is to load
/// assets from the CDN via HTTP.
virtual void AsyncAddFetcher ( IAsyncFileFetch * pFetcher ) = 0 ;
virtual void AsyncRemoveFetcher ( IAsyncFileFetch * pFetcher ) = 0 ;
//------------------------------------
// Functions to hold a file open if planning on doing mutiple reads. Use is optional,
// and is taken only as a hint
//------------------------------------
virtual FSAsyncStatus_t AsyncBeginRead ( const char * pszFile , FSAsyncFile_t * phFile ) = 0 ;
virtual FSAsyncStatus_t AsyncEndRead ( FSAsyncFile_t hFile ) = 0 ;
//------------------------------------
// Request management
//------------------------------------
virtual FSAsyncStatus_t AsyncFinish ( FSAsyncControl_t hControl , bool wait = true ) = 0 ;
virtual FSAsyncStatus_t AsyncGetResult ( FSAsyncControl_t hControl , void * * ppData , int * pSize ) = 0 ;
virtual FSAsyncStatus_t AsyncAbort ( FSAsyncControl_t hControl ) = 0 ;
virtual FSAsyncStatus_t AsyncStatus ( FSAsyncControl_t hControl ) = 0 ;
// set a new priority for a file already in the queue
virtual FSAsyncStatus_t AsyncSetPriority ( FSAsyncControl_t hControl , int newPriority ) = 0 ;
virtual void AsyncAddRef ( FSAsyncControl_t hControl ) = 0 ;
virtual void AsyncRelease ( FSAsyncControl_t hControl ) = 0 ;
//--------------------------------------------------------
// Remote resource management
//--------------------------------------------------------
// starts waiting for resources to be available
// returns FILESYSTEM_INVALID_HANDLE if there is nothing to wait on
virtual WaitForResourcesHandle_t WaitForResources ( const char * resourcelist ) = 0 ;
// get progress on waiting for resources; progress is a float [0, 1], complete is true on the waiting being done
// returns false if no progress is available
// any calls after complete is true or on an invalid handle will return false, 0.0f, true
virtual bool GetWaitForResourcesProgress ( WaitForResourcesHandle_t handle , float * progress /* out */ , bool * complete /* out */ ) = 0 ;
// cancels a progress call
virtual void CancelWaitForResources ( WaitForResourcesHandle_t handle ) = 0 ;
// hints that a set of files will be loaded in near future
// HintResourceNeed() is not to be confused with resource precaching.
virtual int HintResourceNeed ( const char * hintlist , int forgetEverything ) = 0 ;
// returns true if a file is on disk
virtual bool IsFileImmediatelyAvailable ( const char * pFileName ) = 0 ;
// copies file out of pak/bsp/steam cache onto disk (to be accessible by third-party code)
virtual void GetLocalCopy ( const char * pFileName ) = 0 ;
//--------------------------------------------------------
// Debugging operations
//--------------------------------------------------------
// Dump to printf/OutputDebugString the list of files that have not been closed
virtual void PrintOpenedFiles ( void ) = 0 ;
virtual void PrintSearchPaths ( void ) = 0 ;
// output
virtual void SetWarningFunc ( void ( * pfnWarning ) ( PRINTF_FORMAT_STRING const char * fmt , . . . ) ) = 0 ;
virtual void SetWarningLevel ( FileWarningLevel_t level ) = 0 ;
virtual void AddLoggingFunc ( void ( * pfnLogFunc ) ( const char * fileName , const char * accessType ) ) = 0 ;
virtual void RemoveLoggingFunc ( FileSystemLoggingFunc_t logFunc ) = 0 ;
// Returns the file system statistics retreived by the implementation. Returns NULL if not supported.
virtual const FileSystemStatistics * GetFilesystemStatistics ( ) = 0 ;
//--------------------------------------------------------
// Start of new functions after Lost Coast release (7/05)
//--------------------------------------------------------
virtual FileHandle_t OpenEx ( const char * pFileName , const char * pOptions , unsigned flags = 0 , const char * pathID = 0 , char * * ppszResolvedFilename = NULL ) = 0 ;
// Extended version of read provides more context to allow for more optimal reading
virtual int ReadEx ( void * pOutput , int sizeDest , int size , FileHandle_t file ) = 0 ;
virtual int ReadFileEx ( const char * pFileName , const char * pPath , void * * ppBuf , bool bNullTerminate = false , bool bOptimalAlloc = false , int nMaxBytes = 0 , int nStartingByte = 0 , FSAllocFunc_t pfnAlloc = NULL ) = 0 ;
virtual FileNameHandle_t FindFileName ( char const * pFileName ) = 0 ;
# if defined( TRACK_BLOCKING_IO )
virtual void EnableBlockingFileAccessTracking ( bool state ) = 0 ;
virtual bool IsBlockingFileAccessEnabled ( ) const = 0 ;
virtual IBlockingFileItemList * RetrieveBlockingFileAccessInfo ( ) = 0 ;
# endif
virtual void SetupPreloadData ( ) = 0 ;
virtual void DiscardPreloadData ( ) = 0 ;
// Fixme, we could do these via a string embedded into the compiled data, etc...
enum KeyValuesPreloadType_t
{
TYPE_VMT ,
TYPE_SOUNDEMITTER ,
TYPE_SOUNDSCAPE ,
NUM_PRELOAD_TYPES
} ;
virtual void LoadCompiledKeyValues ( KeyValuesPreloadType_t type , char const * archiveFile ) = 0 ;
// If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup.
// Otherwise, it'll just fall through to the regular KeyValues loading routines
virtual KeyValues * LoadKeyValues ( KeyValuesPreloadType_t type , char const * filename , char const * pPathID = 0 ) = 0 ;
virtual bool LoadKeyValues ( KeyValues & head , KeyValuesPreloadType_t type , char const * filename , char const * pPathID = 0 ) = 0 ;
virtual bool ExtractRootKeyName ( KeyValuesPreloadType_t type , char * outbuf , size_t bufsize , char const * filename , char const * pPathID = 0 ) = 0 ;
virtual FSAsyncStatus_t AsyncWrite ( const char * pFileName , const void * pSrc , int nSrcBytes , bool bFreeMemory , bool bAppend = false , FSAsyncControl_t * pControl = NULL ) = 0 ;
virtual FSAsyncStatus_t AsyncWriteFile ( const char * pFileName , const CUtlBuffer * pSrc , int nSrcBytes , bool bFreeMemory , bool bAppend = false , FSAsyncControl_t * pControl = NULL ) = 0 ;
// Async read functions with memory blame
FSAsyncStatus_t AsyncReadCreditAlloc ( const FileAsyncRequest_t & request , const char * pszFile , int line , FSAsyncControl_t * phControl = NULL ) { return AsyncReadMultipleCreditAlloc ( & request , 1 , pszFile , line , phControl ) ; }
virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc ( const FileAsyncRequest_t * pRequests , int nRequests , const char * pszFile , int line , FSAsyncControl_t * phControls = NULL ) = 0 ;
virtual bool GetFileTypeForFullPath ( char const * pFullPath , OUT_Z_BYTECAP ( bufSizeInBytes ) wchar_t * buf , size_t bufSizeInBytes ) = 0 ;
//--------------------------------------------------------
//--------------------------------------------------------
virtual bool ReadToBuffer ( FileHandle_t hFile , CUtlBuffer & buf , int nMaxBytes = 0 , FSAllocFunc_t pfnAlloc = NULL ) = 0 ;
//--------------------------------------------------------
// Optimal IO operations
//--------------------------------------------------------
virtual bool GetOptimalIOConstraints ( FileHandle_t hFile , unsigned * pOffsetAlign , unsigned * pSizeAlign , unsigned * pBufferAlign ) = 0 ;
inline unsigned GetOptimalReadSize ( FileHandle_t hFile , unsigned nLogicalSize ) ;
virtual void * AllocOptimalReadBuffer ( FileHandle_t hFile , unsigned nSize = 0 , unsigned nOffset = 0 ) = 0 ;
virtual void FreeOptimalReadBuffer ( void * ) = 0 ;
//--------------------------------------------------------
//
//--------------------------------------------------------
virtual void BeginMapAccess ( ) = 0 ;
virtual void EndMapAccess ( ) = 0 ;
// Returns true on success, otherwise false if it can't be resolved
// Prefer using the FullPathToRelativePathEx_safe template wrapper to calling this directly
virtual bool FullPathToRelativePathEx ( const char * pFullpath , const char * pPathId , OUT_Z_CAP ( maxLenInChars ) char * pDest , int maxLenInChars ) = 0 ;
template < size_t maxLenInChars > bool FullPathToRelativePathEx_safe ( const char * pFullpath , OUT_Z_ARRAY char ( & pDest ) [ maxLenInChars ] )
{
return FullPathToRelativePathEx ( pFullpath , pDest , ( int ) maxLenInChars ) ;
}
virtual int GetPathIndex ( const FileNameHandle_t & handle ) = 0 ;
virtual time_t GetPathTime ( const char * pPath , const char * pPathID ) = 0 ;
virtual DVDMode_t GetDVDMode ( ) = 0 ;
//--------------------------------------------------------
// Whitelisting for pure servers.
//--------------------------------------------------------
// This should be called ONCE at startup. Multiplayer games (gameinfo.txt does not contain singleplayer_only)
// want to enable this so sv_pure works.
virtual void EnableWhitelistFileTracking ( bool bEnable , bool bCacheAllVPKHashes , bool bRecalculateAndCheckHashes ) = 0 ;
// This is called when the client connects to a server using a pure_server_whitelist.txt file.
virtual void RegisterFileWhitelist ( IPureServerWhitelist * pWhiteList , IFileList * * pFilesToReload ) = 0 ;
// Called when the client logs onto a server. Any files that came off disk should be marked as
// unverified because this server may have a different set of files it wants to guarantee.
virtual void MarkAllCRCsUnverified ( ) = 0 ;
// As the server loads whitelists when it transitions maps, it calls this to calculate CRCs for any files marked
// with check_crc. Then it calls CheckCachedFileCRC later when it gets client requests to verify CRCs.
virtual void CacheFileCRCs ( const char * pPathname , ECacheCRCType eType , IFileList * pFilter ) = 0 ;
virtual EFileCRCStatus CheckCachedFileHash ( const char * pPathID , const char * pRelativeFilename , int nFileFraction , FileHash_t * pFileHash ) = 0 ;
// Fills in the list of files that have been loaded off disk and have not been verified.
// Returns the number of files filled in (between 0 and nMaxFiles).
//
// This also removes any files it's returning from the unverified CRC list, so they won't be
// returned from here again.
// The client sends batches of these to the server to verify.
virtual int GetUnverifiedFileHashes ( CUnverifiedFileHash * pFiles , int nMaxFiles ) = 0 ;
// Control debug message output.
// Pass a combination of WHITELIST_SPEW_ flags.
virtual int GetWhitelistSpewFlags ( ) = 0 ;
virtual void SetWhitelistSpewFlags ( int flags ) = 0 ;
// Installs a callback used to display a dirty disk dialog
virtual void InstallDirtyDiskReportFunc ( FSDirtyDiskReportFunc_t func ) = 0 ;
//--------------------------------------------------------
// Low-level file caching. Cached files are loaded into memory and used
// to satisfy read requests (sync and async) until the cache is destroyed.
// NOTE: this could defeat file whitelisting, if a file were loaded in
// a non-whitelisted environment and then reused. Clients should not cache
// files across moves between pure/non-pure environments.
//--------------------------------------------------------
virtual FileCacheHandle_t CreateFileCache ( ) = 0 ;
virtual void AddFilesToFileCache ( FileCacheHandle_t cacheId , const char * * ppFileNames , int nFileNames , const char * pPathID ) = 0 ;
virtual bool IsFileCacheFileLoaded ( FileCacheHandle_t cacheId , const char * pFileName ) = 0 ;
virtual bool IsFileCacheLoaded ( FileCacheHandle_t cacheId ) = 0 ;
virtual void DestroyFileCache ( FileCacheHandle_t cacheId ) = 0 ;
// XXX For now, we assume that all path IDs are "GAME", never cache files
// outside of the game search path, and preferentially return those files
// whenever anyone searches for a match even if an on-disk file in another
// folder would have been found first in a traditional search. extending
// the memory cache to cover non-game files isn't necessary right now, but
// should just be a matter of defining a more complex key type. (henryg)
// Register a CMemoryFileBacking; must balance with UnregisterMemoryFile.
// Returns false and outputs an ref-bumped pointer to the existing entry
// if the same file has already been registered by someone else; this must
// be Unregistered to maintain the balance.
virtual bool RegisterMemoryFile ( CMemoryFileBacking * pFile , CMemoryFileBacking * * ppExistingFileWithRef ) = 0 ;
// Unregister a CMemoryFileBacking; must balance with RegisterMemoryFile.
virtual void UnregisterMemoryFile ( CMemoryFileBacking * pFile ) = 0 ;
virtual void CacheAllVPKFileHashes ( bool bCacheAllVPKHashes , bool bRecalculateAndCheckHashes ) = 0 ;
virtual bool CheckVPKFileHash ( int PackFileID , int nPackFileNumber , int nFileFraction , MD5Value_t & md5Value ) = 0 ;
// Called when we unload a file, to remove that file's info for pure server purposes.
virtual void NotifyFileUnloaded ( const char * pszFilename , const char * pPathId ) = 0 ;
// Returns true on successfully retrieve case-sensitive full path, otherwise false
// Prefer using the GetCaseCorrectFullPath template wrapper to calling this directly
virtual bool GetCaseCorrectFullPath_Ptr ( const char * pFullPath , OUT_Z_CAP ( maxLenInChars ) char * pDest , int maxLenInChars ) = 0 ;
template < size_t maxLenInChars > bool GetCaseCorrectFullPath ( const char * pFullPath , OUT_Z_ARRAY char ( & pDest ) [ maxLenInChars ] )
{
return GetCaseCorrectFullPath_Ptr ( pFullPath , pDest , ( int ) maxLenInChars ) ;
}
} ;
//-----------------------------------------------------------------------------
// Memory file backing, which you can use to fake out the filesystem, caching data
// in memory and have it associated with a file
//-----------------------------------------------------------------------------
class CMemoryFileBacking : public CRefCounted < CRefCountServiceMT >
{
public :
// malloc and free in headers with our janky memdbg system. What could go wrong. Except everything.
// (this free can't skip memdbg if paired malloc used memdbg)
# include <memdbgon.h>
CMemoryFileBacking ( IFileSystem * pFS ) : m_pFS ( pFS ) , m_nRegistered ( 0 ) , m_pFileName ( NULL ) , m_pData ( NULL ) , m_nLength ( 0 ) { }
~ CMemoryFileBacking ( ) { free ( ( char * ) m_pFileName ) ; if ( m_pData ) m_pFS - > FreeOptimalReadBuffer ( ( char * ) m_pData ) ; }
# include <memdbgoff.h>
IFileSystem * m_pFS ;
int m_nRegistered ;
const char * m_pFileName ;
const char * m_pData ;
int m_nLength ;
private :
CMemoryFileBacking ( const CMemoryFileBacking & ) ; // not defined
CMemoryFileBacking & operator = ( const CMemoryFileBacking & ) ; // not defined
} ;
//-----------------------------------------------------------------------------
# if defined( _X360 ) && !defined( _RETAIL )
extern char g_szXboxProfileLastFileOpened [ MAX_PATH ] ;
# define SetLastProfileFileRead( s ) Q_strncpy( g_szXboxProfileLastFileOpened, sizeof( g_szXboxProfileLastFileOpened), pFileName )
# define GetLastProfileFileRead() (&g_szXboxProfileLastFileOpened[0])
# else
# define SetLastProfileFileRead( s ) ((void)0)
# define GetLastProfileFileRead() NULL
# endif
# if defined( _X360 ) && defined( _BASETSD_H_ )
class CXboxDiskCacheSetter
{
public :
CXboxDiskCacheSetter ( SIZE_T newSize )
{
m_oldSize = XGetFileCacheSize ( ) ;
XSetFileCacheSize ( newSize ) ;
}
~ CXboxDiskCacheSetter ( )
{
XSetFileCacheSize ( m_oldSize ) ;
}
private :
SIZE_T m_oldSize ;
} ;
# define DISK_INTENSIVE() CXboxDiskCacheSetter cacheSetter( 1024*1024 )
# else
# define DISK_INTENSIVE() ((void)0)
# endif
//-----------------------------------------------------------------------------
inline unsigned IFileSystem : : GetOptimalReadSize ( FileHandle_t hFile , unsigned nLogicalSize )
{
unsigned align ;
if ( GetOptimalIOConstraints ( hFile , & align , NULL , NULL ) )
return AlignValue ( nLogicalSize , align ) ;
else
return nLogicalSize ;
}
//-----------------------------------------------------------------------------
// We include this here so it'll catch compile errors in VMPI early.
# include "filesystem_passthru.h"
//-----------------------------------------------------------------------------
// Async memory tracking
//-----------------------------------------------------------------------------
# if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
# define AsyncRead( a, b ) AsyncReadCreditAlloc( a, __FILE__, __LINE__, b )
# define AsyncReadMutiple( a, b, c ) AsyncReadMultipleCreditAlloc( a, b, __FILE__, __LINE__, c )
# endif
extern IFileSystem * g_pFullFileSystem ;
# endif // FILESYSTEM_H