Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1016 lines
41 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #ifndef FILESYSTEM_H
  8. #define FILESYSTEM_H
  9. #pragma once
  10. #include <limits.h>
  11. #include "tier0/threadtools.h"
  12. #include "tier0/memalloc.h"
  13. #include "tier1/interface.h"
  14. #include "tier1/utlsymbol.h"
  15. #include "tier1/utlstring.h"
  16. #include "appframework/IAppSystem.h"
  17. #include "tier1/checksum_crc.h"
  18. #include "tier1/checksum_md5.h"
  19. #include "tier1/refcount.h"
  20. #ifdef _WIN32
  21. #pragma once
  22. #endif
  23. //-----------------------------------------------------------------------------
  24. // Forward declarations
  25. //-----------------------------------------------------------------------------
  26. class CUtlBuffer;
  27. class KeyValues;
  28. class IFileList;
  29. class IThreadPool;
  30. class CMemoryFileBacking;
  31. typedef void * FileHandle_t;
  32. typedef void * FileCacheHandle_t;
  33. typedef int FileFindHandle_t;
  34. typedef void (*FileSystemLoggingFunc_t)( const char *fileName, const char *accessType );
  35. typedef int WaitForResourcesHandle_t;
  36. #ifdef _X360
  37. typedef void* HANDLE;
  38. #endif
  39. #define USE_CRC_FILE_TRACKING 0
  40. // Turn on some extra pure server debug spew in certain builds.
  41. // WARNING: This spew can be used by hackers to locate places to hack
  42. // the code to bypas sv_pure! Be careful!
  43. #if defined( _DEBUG ) || defined( STAGING_ONLY )
  44. #define PURE_SERVER_DEBUG_SPEW
  45. #endif
  46. /// How strict will the pure server be for a particular set of files
  47. enum EPureServerFileClass
  48. {
  49. ePureServerFileClass_Unknown = -1, // dummy debugging value
  50. ePureServerFileClass_Any = 0,
  51. ePureServerFileClass_AnyTrusted,
  52. ePureServerFileClass_CheckHash,
  53. };
  54. class IPureServerWhitelist
  55. {
  56. public:
  57. // Reference counting
  58. virtual void AddRef() = 0;
  59. virtual void Release() = 0;
  60. // What should we do with a particular file?
  61. virtual EPureServerFileClass GetFileClass( const char *pszFilename ) = 0;
  62. // Access list of trusted keys which we will allow to set trusted content
  63. virtual int GetTrustedKeyCount() const = 0;
  64. virtual const byte *GetTrustedKey( int iKeyIndex, int *nKeySize ) const = 0;
  65. };
  66. //-----------------------------------------------------------------------------
  67. // Enums used by the interface
  68. //-----------------------------------------------------------------------------
  69. #define FILESYSTEM_MAX_SEARCH_PATHS 128
  70. enum FileSystemSeek_t
  71. {
  72. FILESYSTEM_SEEK_HEAD = SEEK_SET,
  73. FILESYSTEM_SEEK_CURRENT = SEEK_CUR,
  74. FILESYSTEM_SEEK_TAIL = SEEK_END,
  75. };
  76. enum
  77. {
  78. FILESYSTEM_INVALID_FIND_HANDLE = -1
  79. };
  80. enum FileWarningLevel_t
  81. {
  82. // A problem!
  83. FILESYSTEM_WARNING = -1,
  84. // Don't print anything
  85. FILESYSTEM_WARNING_QUIET = 0,
  86. // On shutdown, report names of files left unclosed
  87. FILESYSTEM_WARNING_REPORTUNCLOSED,
  88. // Report number of times a file was opened, closed
  89. FILESYSTEM_WARNING_REPORTUSAGE,
  90. // Report all open/close events to console ( !slow! )
  91. FILESYSTEM_WARNING_REPORTALLACCESSES,
  92. // Report all open/close/read events to the console ( !slower! )
  93. FILESYSTEM_WARNING_REPORTALLACCESSES_READ,
  94. // Report all open/close/read/write events to the console ( !slower! )
  95. FILESYSTEM_WARNING_REPORTALLACCESSES_READWRITE,
  96. // Report all open/close/read/write events and all async I/O file events to the console ( !slower(est)! )
  97. FILESYSTEM_WARNING_REPORTALLACCESSES_ASYNC,
  98. };
  99. // search path filtering
  100. enum PathTypeFilter_t
  101. {
  102. FILTER_NONE = 0, // no filtering, all search path types match
  103. FILTER_CULLPACK = 1, // pack based search paths are culled (maps and zips)
  104. FILTER_CULLNONPACK = 2, // non-pack based search paths are culled
  105. };
  106. // search path querying (bit flags)
  107. enum
  108. {
  109. PATH_IS_NORMAL = 0x00, // normal path, not pack based
  110. PATH_IS_PACKFILE = 0x01, // path is a pack file
  111. PATH_IS_MAPPACKFILE = 0x02, // path is a map pack file
  112. PATH_IS_REMOTE = 0x04, // path is the remote filesystem
  113. };
  114. typedef uint32 PathTypeQuery_t;
  115. #define IS_PACKFILE( n ) ( n & ( PATH_IS_PACKFILE | PATH_IS_MAPPACKFILE ) )
  116. #define IS_REMOTE( n ) ( n & PATH_IS_REMOTE )
  117. enum DVDMode_t
  118. {
  119. DVDMODE_OFF = 0, // not using dvd
  120. DVDMODE_STRICT = 1, // dvd device only
  121. DVDMODE_DEV = 2, // dev mode, mutiple devices ok
  122. };
  123. // In non-retail builds, enable the file blocking access tracking stuff...
  124. #if defined( TRACK_BLOCKING_IO )
  125. enum FileBlockingWarning_t
  126. {
  127. // Report how long synchronous i/o took to complete
  128. FILESYSTEM_BLOCKING_SYNCHRONOUS = 0,
  129. // Report how long async i/o took to complete if AsyncFileFinished caused it to load via "blocking" i/o
  130. FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK,
  131. // Report how long async i/o took to complete
  132. FILESYSTEM_BLOCKING_ASYNCHRONOUS,
  133. // Report how long the async "callback" took
  134. FILESYSTEM_BLOCKING_CALLBACKTIMING,
  135. FILESYSTEM_BLOCKING_NUMBINS,
  136. };
  137. #pragma pack(1)
  138. class FileBlockingItem
  139. {
  140. public:
  141. enum
  142. {
  143. FB_ACCESS_OPEN = 1,
  144. FB_ACCESS_CLOSE = 2,
  145. FB_ACCESS_READ = 3,
  146. FB_ACCESS_WRITE = 4,
  147. FB_ACCESS_APPEND = 5,
  148. FB_ACCESS_SIZE = 6
  149. };
  150. FileBlockingItem() :
  151. m_ItemType( (FileBlockingWarning_t)0 ),
  152. m_flElapsed( 0.0f ),
  153. m_nAccessType( 0 )
  154. {
  155. SetFileName( NULL );
  156. }
  157. FileBlockingItem( int type, char const *filename, float elapsed, int accessType ) :
  158. m_ItemType( (FileBlockingWarning_t)type ),
  159. m_flElapsed( elapsed ),
  160. m_nAccessType( accessType )
  161. {
  162. SetFileName( filename );
  163. }
  164. void SetFileName( char const *filename )
  165. {
  166. if ( !filename )
  167. {
  168. m_szFilename[ 0 ] = 0;
  169. return;
  170. }
  171. int len = Q_strlen( filename );
  172. if ( len >= sizeof( m_szFilename ) )
  173. {
  174. Q_strncpy( m_szFilename, &filename[ len - sizeof( m_szFilename ) + 1 ], sizeof( m_szFilename ) );
  175. }
  176. else
  177. {
  178. Q_strncpy( m_szFilename, filename, sizeof( m_szFilename ) );
  179. }
  180. }
  181. char const *GetFileName() const
  182. {
  183. return m_szFilename;
  184. }
  185. FileBlockingWarning_t m_ItemType;
  186. float m_flElapsed;
  187. byte m_nAccessType;
  188. private:
  189. char m_szFilename[ 32 ];
  190. };
  191. #pragma pack()
  192. class IBlockingFileItemList
  193. {
  194. public:
  195. // You can't call any of the below calls without locking first
  196. virtual void LockMutex() = 0;
  197. virtual void UnlockMutex() = 0;
  198. virtual int First() const = 0;
  199. virtual int Next( int i ) const = 0;
  200. virtual int InvalidIndex() const = 0;
  201. virtual const FileBlockingItem& Get( int index ) const = 0;
  202. virtual void Reset() = 0;
  203. };
  204. #endif // TRACK_BLOCKING_IO
  205. enum FilesystemMountRetval_t
  206. {
  207. FILESYSTEM_MOUNT_OK = 0,
  208. FILESYSTEM_MOUNT_FAILED,
  209. };
  210. enum SearchPathAdd_t
  211. {
  212. PATH_ADD_TO_HEAD, // First path searched
  213. PATH_ADD_TO_TAIL, // Last path searched
  214. };
  215. enum FilesystemOpenExFlags_t
  216. {
  217. FSOPEN_UNBUFFERED = (1 << 0),
  218. FSOPEN_FORCE_TRACK_CRC = (1 << 1), // This makes it calculate a CRC for the file (if the file came from disk) regardless
  219. // of the IFileList passed to RegisterFileWhitelist.
  220. FSOPEN_NEVERINPACK = (1 << 2), // 360 only, hint to FS that file is not allowed to be in pack file
  221. };
  222. #define FILESYSTEM_INVALID_HANDLE ( FileHandle_t )0
  223. //-----------------------------------------------------------------------------
  224. // Structures used by the interface
  225. //-----------------------------------------------------------------------------
  226. struct FileSystemStatistics
  227. {
  228. CInterlockedUInt nReads,
  229. nWrites,
  230. nBytesRead,
  231. nBytesWritten,
  232. nSeeks;
  233. };
  234. //-----------------------------------------------------------------------------
  235. // File system allocation functions. Client must free on failure
  236. //-----------------------------------------------------------------------------
  237. typedef void *(*FSAllocFunc_t)( const char *pszFilename, unsigned nBytes );
  238. //-----------------------------------------------------------------------------
  239. // Used to display dirty disk error functions
  240. //-----------------------------------------------------------------------------
  241. typedef void (*FSDirtyDiskReportFunc_t)();
  242. //-----------------------------------------------------------------------------
  243. // Asynchronous support types
  244. //-----------------------------------------------------------------------------
  245. DECLARE_POINTER_HANDLE(FSAsyncControl_t);
  246. DECLARE_POINTER_HANDLE(FSAsyncFile_t);
  247. const FSAsyncFile_t FS_INVALID_ASYNC_FILE = (FSAsyncFile_t)(0x0000ffff);
  248. //---------------------------------------------------------
  249. // Async file status
  250. //---------------------------------------------------------
  251. enum FSAsyncStatus_t
  252. {
  253. FSASYNC_ERR_NOT_MINE = -8, // Filename not part of the specified file system, try a different one. (Used internally to find the right filesystem)
  254. FSASYNC_ERR_RETRY_LATER = -7, // Failure for a reason that might be temporary. You might retry, but not immediately. (E.g. Network problems)
  255. FSASYNC_ERR_ALIGNMENT = -6, // read parameters invalid for unbuffered IO
  256. FSASYNC_ERR_FAILURE = -5, // hard subsystem failure
  257. FSASYNC_ERR_READING = -4, // read error on file
  258. FSASYNC_ERR_NOMEMORY = -3, // out of memory for file read
  259. FSASYNC_ERR_UNKNOWNID = -2, // caller's provided id is not recognized
  260. FSASYNC_ERR_FILEOPEN = -1, // filename could not be opened (bad path, not exist, etc)
  261. FSASYNC_OK = 0, // operation is successful
  262. FSASYNC_STATUS_PENDING, // file is properly queued, waiting for service
  263. FSASYNC_STATUS_INPROGRESS, // file is being accessed
  264. FSASYNC_STATUS_ABORTED, // file was aborted by caller
  265. FSASYNC_STATUS_UNSERVICED, // file is not yet queued
  266. };
  267. //---------------------------------------------------------
  268. // Async request flags
  269. //---------------------------------------------------------
  270. enum FSAsyncFlags_t
  271. {
  272. FSASYNC_FLAGS_ALLOCNOFREE = ( 1 << 0 ), // do the allocation for dataPtr, but don't free
  273. FSASYNC_FLAGS_FREEDATAPTR = ( 1 << 1 ), // free the memory for the dataPtr post callback
  274. FSASYNC_FLAGS_SYNC = ( 1 << 2 ), // Actually perform the operation synchronously. Used to simplify client code paths
  275. FSASYNC_FLAGS_NULLTERMINATE = ( 1 << 3 ), // allocate an extra byte and null terminate the buffer read in
  276. };
  277. //---------------------------------------------------------
  278. // Return value for CheckFileCRC.
  279. //---------------------------------------------------------
  280. enum EFileCRCStatus
  281. {
  282. k_eFileCRCStatus_CantOpenFile, // We don't have this file.
  283. k_eFileCRCStatus_GotCRC,
  284. k_eFileCRCStatus_FileInVPK
  285. };
  286. // Used in CacheFileCRCs.
  287. enum ECacheCRCType
  288. {
  289. k_eCacheCRCType_SingleFile,
  290. k_eCacheCRCType_Directory,
  291. k_eCacheCRCType_Directory_Recursive
  292. };
  293. //---------------------------------------------------------
  294. // Optional completion callback for each async file serviced (or failed)
  295. // call is not reentrant, async i/o guaranteed suspended until return
  296. // Note: If you change the signature of the callback, you will have to account for it in FileSystemV12 (toml [4/18/2005] )
  297. //---------------------------------------------------------
  298. struct FileAsyncRequest_t;
  299. typedef void (*FSAsyncCallbackFunc_t)(const FileAsyncRequest_t &request, int nBytesRead, FSAsyncStatus_t err);
  300. //---------------------------------------------------------
  301. // Description of an async request
  302. //---------------------------------------------------------
  303. struct FileAsyncRequest_t
  304. {
  305. FileAsyncRequest_t() { memset( this, 0, sizeof(*this) ); hSpecificAsyncFile = FS_INVALID_ASYNC_FILE; }
  306. const char * pszFilename; // file system name
  307. void * pData; // optional, system will alloc/free if NULL
  308. int nOffset; // optional initial seek_set, 0=beginning
  309. int nBytes; // optional read clamp, -1=exist test, 0=full read
  310. FSAsyncCallbackFunc_t pfnCallback; // optional completion callback
  311. void * pContext; // caller's unique file identifier
  312. int priority; // inter list priority, 0=lowest
  313. unsigned flags; // behavior modifier
  314. const char * pszPathID; // path ID (NOTE: this field is here to remain binary compatible with release HL2 filesystem interface)
  315. FSAsyncFile_t hSpecificAsyncFile; // Optional hint obtained using AsyncBeginRead()
  316. FSAllocFunc_t pfnAlloc; // custom allocator. can be null. not compatible with FSASYNC_FLAGS_FREEDATAPTR
  317. };
  318. struct FileHash_t
  319. {
  320. enum EFileHashType_t
  321. {
  322. k_EFileHashTypeUnknown = 0,
  323. k_EFileHashTypeEntireFile = 1,
  324. k_EFileHashTypeIncompleteFile = 2,
  325. };
  326. FileHash_t()
  327. {
  328. m_eFileHashType = FileHash_t::k_EFileHashTypeUnknown;
  329. m_cbFileLen = 0;
  330. m_PackFileID = 0;
  331. m_nPackFileNumber = 0;
  332. }
  333. int m_eFileHashType;
  334. CRC32_t m_crcIOSequence;
  335. MD5Value_t m_md5contents;
  336. int m_cbFileLen;
  337. int m_PackFileID;
  338. int m_nPackFileNumber;
  339. bool operator==( const FileHash_t &src ) const
  340. {
  341. return m_crcIOSequence == src.m_crcIOSequence &&
  342. m_md5contents == src.m_md5contents &&
  343. m_eFileHashType == src.m_eFileHashType;
  344. }
  345. bool operator!=( const FileHash_t &src ) const
  346. {
  347. return m_crcIOSequence != src.m_crcIOSequence ||
  348. m_md5contents != src.m_md5contents ||
  349. m_eFileHashType != src.m_eFileHashType;
  350. }
  351. };
  352. class CUnverifiedFileHash
  353. {
  354. public:
  355. char m_PathID[MAX_PATH];
  356. char m_Filename[MAX_PATH];
  357. int m_nFileFraction;
  358. FileHash_t m_FileHash;
  359. };
  360. class CUnverifiedCRCFile
  361. {
  362. public:
  363. char m_PathID[MAX_PATH];
  364. char m_Filename[MAX_PATH];
  365. CRC32_t m_CRC;
  366. };
  367. class CUnverifiedMD5File
  368. {
  369. public:
  370. char m_PathID[MAX_PATH];
  371. char m_Filename[MAX_PATH];
  372. unsigned char bits[MD5_DIGEST_LENGTH];
  373. };
  374. // Spew flags for SetWhitelistSpewFlags (set with the fs_whitelist_spew_flags cvar).
  375. // Update the comment for the fs_whitelist_spew_flags cvar if you change these.
  376. #define WHITELIST_SPEW_WHILE_LOADING 0x0001 // list files as they are added to the CRC tracker
  377. #define WHITELIST_SPEW_RELOAD_FILES 0x0002 // show files the filesystem is telling the engine to reload
  378. #define WHITELIST_SPEW_DONT_RELOAD_FILES 0x0004 // show files the filesystem is NOT telling the engine to reload
  379. //-----------------------------------------------------------------------------
  380. // Interface to fetch a file asynchronously from any source. This is used
  381. // as a hook
  382. //-----------------------------------------------------------------------------
  383. abstract_class IAsyncFileFetch {
  384. public:
  385. typedef void *Handle;
  386. /// Initiate a request. Returns error status, or on success
  387. /// returns an opaque handle used to terminate the job
  388. ///
  389. /// Should return FSASYNC_ERR_NOT_MINE if the filename isn't
  390. /// handled by this interface
  391. ///
  392. /// The callback is required, and is the only mechanism to communicate
  393. /// status. (No polling.) The request is automatically destroyed anytime
  394. /// after the callback is executed.
  395. virtual FSAsyncStatus_t Start( const FileAsyncRequest_t &request, Handle *pOutHandle, IThreadPool *pThreadPool ) = 0;
  396. /// Attempt to complete any active work, returning status. The callback WILL
  397. /// be executed (this is necessary in case we allocated the buffer).
  398. /// Afterwards, the request is automatically destroyed.
  399. virtual FSAsyncStatus_t FinishSynchronous( Handle hControl ) = 0;
  400. /// Terminate any active work and destroy all resources and bookkeeping info.
  401. /// The callback will NOT be executed.
  402. virtual FSAsyncStatus_t Abort( Handle hControl ) = 0;
  403. };
  404. // This interface is for VPK files to communicate with FileTracker
  405. abstract_class IThreadedFileMD5Processor
  406. {
  407. public:
  408. virtual int SubmitThreadedMD5Request( uint8 *pubBuffer, int cubBuffer, int PackFileID, int nPackFileNumber, int nPackFileFraction ) = 0;
  409. virtual bool BlockUntilMD5RequestComplete( int iRequest, MD5Value_t *pMd5ValueOut ) = 0;
  410. virtual bool IsMD5RequestComplete( int iRequest, MD5Value_t *pMd5ValueOut ) = 0;
  411. };
  412. //-----------------------------------------------------------------------------
  413. // Base file system interface
  414. //-----------------------------------------------------------------------------
  415. // This is the minimal interface that can be implemented to provide access to
  416. // a named set of files.
  417. #define BASEFILESYSTEM_INTERFACE_VERSION "VBaseFileSystem011"
  418. abstract_class IBaseFileSystem
  419. {
  420. public:
  421. virtual int Read( void* pOutput, int size, FileHandle_t file ) = 0;
  422. virtual int Write( void const* pInput, int size, FileHandle_t file ) = 0;
  423. // if pathID is NULL, all paths will be searched for the file
  424. virtual FileHandle_t Open( const char *pFileName, const char *pOptions, const char *pathID = 0 ) = 0;
  425. virtual void Close( FileHandle_t file ) = 0;
  426. virtual void Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType ) = 0;
  427. virtual unsigned int Tell( FileHandle_t file ) = 0;
  428. virtual unsigned int Size( FileHandle_t file ) = 0;
  429. virtual unsigned int Size( const char *pFileName, const char *pPathID = 0 ) = 0;
  430. virtual void Flush( FileHandle_t file ) = 0;
  431. virtual bool Precache( const char *pFileName, const char *pPathID = 0 ) = 0;
  432. virtual bool FileExists( const char *pFileName, const char *pPathID = 0 ) = 0;
  433. virtual bool IsFileWritable( char const *pFileName, const char *pPathID = 0 ) = 0;
  434. virtual bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID = 0 ) = 0;
  435. virtual long GetFileTime( const char *pFileName, const char *pPathID = 0 ) = 0;
  436. //--------------------------------------------------------
  437. // Reads/writes files to utlbuffers. Use this for optimal read performance when doing open/read/close
  438. //--------------------------------------------------------
  439. virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0;
  440. virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) = 0;
  441. virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) = 0;
  442. };
  443. //-----------------------------------------------------------------------------
  444. // Main file system interface
  445. //-----------------------------------------------------------------------------
  446. #define FILESYSTEM_INTERFACE_VERSION "VFileSystem022"
  447. abstract_class IFileSystem : public IAppSystem, public IBaseFileSystem
  448. {
  449. public:
  450. //--------------------------------------------------------
  451. // Steam operations
  452. //--------------------------------------------------------
  453. virtual bool IsSteam() const = 0;
  454. // Supplying an extra app id will mount this app in addition
  455. // to the one specified in the environment variable "steamappid"
  456. //
  457. // If nExtraAppId is < -1, then it will mount that app ID only.
  458. // (Was needed by the dedicated server b/c the "SteamAppId" env var only gets passed to steam.dll
  459. // at load time, so the dedicated couldn't pass it in that way).
  460. virtual FilesystemMountRetval_t MountSteamContent( int nExtraAppId = -1 ) = 0;
  461. //--------------------------------------------------------
  462. // Search path manipulation
  463. //--------------------------------------------------------
  464. // Add paths in priority order (mod dir, game dir, ....)
  465. // If one or more .pak files are in the specified directory, then they are
  466. // added after the file system path
  467. // If the path is the relative path to a .bsp file, then any previous .bsp file
  468. // override is cleared and the current .bsp is searched for an embedded PAK file
  469. // and this file becomes the highest priority search path ( i.e., it's looked at first
  470. // even before the mod's file system path ).
  471. virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0;
  472. virtual bool RemoveSearchPath( const char *pPath, const char *pathID = 0 ) = 0;
  473. // Remove all search paths (including write path?)
  474. virtual void RemoveAllSearchPaths( void ) = 0;
  475. // Remove search paths associated with a given pathID
  476. virtual void RemoveSearchPaths( const char *szPathID ) = 0;
  477. // This is for optimization. If you mark a path ID as "by request only", then files inside it
  478. // will only be accessed if the path ID is specifically requested. Otherwise, it will be ignored.
  479. // If there are currently no search paths with the specified path ID, then it will still
  480. // remember it in case you add search paths with this path ID.
  481. virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) = 0;
  482. // converts a partial path into a full path
  483. // Prefer using the RelativePathToFullPath_safe template wrapper to calling this directly
  484. 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;
  485. 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 )
  486. {
  487. return RelativePathToFullPath( pFileName, pPathID, pDest, (int)maxLenInChars, pathFilter, pPathType );
  488. }
  489. // Returns the search path, each path is separated by ;s. Returns the length of the string returned
  490. // Prefer using the GetSearchPath_safe template wrapper to calling this directly
  491. virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars ) = 0;
  492. template <size_t maxLenInChars> int GetSearchPath_safe( const char *pathID, bool bGetPackFiles, OUT_Z_ARRAY char (&pDest)[maxLenInChars] )
  493. {
  494. return GetSearchPath( pathID, bGetPackFiles, pDest, (int)maxLenInChars );
  495. }
  496. // interface for custom pack files > 4Gb
  497. virtual bool AddPackFile( const char *fullpath, const char *pathID ) = 0;
  498. //--------------------------------------------------------
  499. // File manipulation operations
  500. //--------------------------------------------------------
  501. // Deletes a file (on the WritePath)
  502. virtual void RemoveFile( char const* pRelativePath, const char *pathID = 0 ) = 0;
  503. // Renames a file (on the WritePath)
  504. virtual bool RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID = 0 ) = 0;
  505. // create a local directory structure
  506. virtual void CreateDirHierarchy( const char *path, const char *pathID = 0 ) = 0;
  507. // File I/O and info
  508. virtual bool IsDirectory( const char *pFileName, const char *pathID = 0 ) = 0;
  509. virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, long fileTime ) = 0;
  510. //--------------------------------------------------------
  511. // Open file operations
  512. //--------------------------------------------------------
  513. virtual void SetBufferSize( FileHandle_t file, unsigned nBytes ) = 0;
  514. virtual bool IsOk( FileHandle_t file ) = 0;
  515. virtual bool EndOfFile( FileHandle_t file ) = 0;
  516. virtual char *ReadLine( char *pOutput, int maxChars, FileHandle_t file ) = 0;
  517. virtual int FPrintf( FileHandle_t file, PRINTF_FORMAT_STRING const char *pFormat, ... ) = 0;
  518. //--------------------------------------------------------
  519. // Dynamic library operations
  520. //--------------------------------------------------------
  521. // load/unload modules
  522. virtual CSysModule *LoadModule( const char *pFileName, const char *pPathID = 0, bool bValidatedDllOnly = true ) = 0;
  523. virtual void UnloadModule( CSysModule *pModule ) = 0;
  524. //--------------------------------------------------------
  525. // File searching operations
  526. //--------------------------------------------------------
  527. // FindFirst/FindNext. Also see FindFirstEx.
  528. virtual const char *FindFirst( const char *pWildCard, FileFindHandle_t *pHandle ) = 0;
  529. virtual const char *FindNext( FileFindHandle_t handle ) = 0;
  530. virtual bool FindIsDirectory( FileFindHandle_t handle ) = 0;
  531. virtual void FindClose( FileFindHandle_t handle ) = 0;
  532. // Same as FindFirst, but you can filter by path ID, which can make it faster.
  533. virtual const char *FindFirstEx(
  534. const char *pWildCard,
  535. const char *pPathID,
  536. FileFindHandle_t *pHandle
  537. ) = 0;
  538. //--------------------------------------------------------
  539. // File name and directory operations
  540. //--------------------------------------------------------
  541. // FIXME: This method is obsolete! Use RelativePathToFullPath instead!
  542. // converts a partial path into a full path
  543. // Prefer using the GetLocalPath_safe template wrapper to calling this directly
  544. virtual const char *GetLocalPath( const char *pFileName, OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars ) = 0;
  545. template <size_t maxLenInChars> const char *GetLocalPath_safe( const char *pFileName, OUT_Z_ARRAY char (&pDest)[maxLenInChars] )
  546. {
  547. return GetLocalPath( pFileName, pDest, (int)maxLenInChars );
  548. }
  549. // Returns true on success ( based on current list of search paths, otherwise false if
  550. // it can't be resolved )
  551. // Prefer using the FullPathToRelativePath_safe template wrapper to calling this directly
  552. virtual bool FullPathToRelativePath( const char *pFullpath, OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars ) = 0;
  553. template <size_t maxLenInChars> bool FullPathToRelativePath_safe( const char *pFullpath, OUT_Z_ARRAY char (&pDest)[maxLenInChars] )
  554. {
  555. return FullPathToRelativePath( pFullpath, pDest, (int)maxLenInChars );
  556. }
  557. // Gets the current working directory
  558. virtual bool GetCurrentDirectory( char* pDirectory, int maxlen ) = 0;
  559. //--------------------------------------------------------
  560. // Filename dictionary operations
  561. //--------------------------------------------------------
  562. virtual FileNameHandle_t FindOrAddFileName( char const *pFileName ) = 0;
  563. virtual bool String( const FileNameHandle_t& handle, char *buf, int buflen ) = 0;
  564. //--------------------------------------------------------
  565. // Asynchronous file operations
  566. //--------------------------------------------------------
  567. //------------------------------------
  568. // Global operations
  569. //------------------------------------
  570. FSAsyncStatus_t AsyncRead( const FileAsyncRequest_t &request, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultiple( &request, 1, phControl ); }
  571. virtual FSAsyncStatus_t AsyncReadMultiple( const FileAsyncRequest_t *pRequests, int nRequests, FSAsyncControl_t *phControls = NULL ) = 0;
  572. virtual FSAsyncStatus_t AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl = NULL ) = 0;
  573. virtual FSAsyncStatus_t AsyncAppendFile(const char *pAppendToFileName, const char *pAppendFromFileName, FSAsyncControl_t *pControl = NULL ) = 0;
  574. virtual void AsyncFinishAll( int iToPriority = 0 ) = 0;
  575. virtual void AsyncFinishAllWrites() = 0;
  576. virtual FSAsyncStatus_t AsyncFlush() = 0;
  577. virtual bool AsyncSuspend() = 0;
  578. virtual bool AsyncResume() = 0;
  579. /// Add async fetcher interface. This gives apps a hook to intercept async requests and
  580. /// pull the data from a source of their choosing. The immediate use case is to load
  581. /// assets from the CDN via HTTP.
  582. virtual void AsyncAddFetcher( IAsyncFileFetch *pFetcher ) = 0;
  583. virtual void AsyncRemoveFetcher( IAsyncFileFetch *pFetcher ) = 0;
  584. //------------------------------------
  585. // Functions to hold a file open if planning on doing mutiple reads. Use is optional,
  586. // and is taken only as a hint
  587. //------------------------------------
  588. virtual FSAsyncStatus_t AsyncBeginRead( const char *pszFile, FSAsyncFile_t *phFile ) = 0;
  589. virtual FSAsyncStatus_t AsyncEndRead( FSAsyncFile_t hFile ) = 0;
  590. //------------------------------------
  591. // Request management
  592. //------------------------------------
  593. virtual FSAsyncStatus_t AsyncFinish( FSAsyncControl_t hControl, bool wait = true ) = 0;
  594. virtual FSAsyncStatus_t AsyncGetResult( FSAsyncControl_t hControl, void **ppData, int *pSize ) = 0;
  595. virtual FSAsyncStatus_t AsyncAbort( FSAsyncControl_t hControl ) = 0;
  596. virtual FSAsyncStatus_t AsyncStatus( FSAsyncControl_t hControl ) = 0;
  597. // set a new priority for a file already in the queue
  598. virtual FSAsyncStatus_t AsyncSetPriority(FSAsyncControl_t hControl, int newPriority) = 0;
  599. virtual void AsyncAddRef( FSAsyncControl_t hControl ) = 0;
  600. virtual void AsyncRelease( FSAsyncControl_t hControl ) = 0;
  601. //--------------------------------------------------------
  602. // Remote resource management
  603. //--------------------------------------------------------
  604. // starts waiting for resources to be available
  605. // returns FILESYSTEM_INVALID_HANDLE if there is nothing to wait on
  606. virtual WaitForResourcesHandle_t WaitForResources( const char *resourcelist ) = 0;
  607. // get progress on waiting for resources; progress is a float [0, 1], complete is true on the waiting being done
  608. // returns false if no progress is available
  609. // any calls after complete is true or on an invalid handle will return false, 0.0f, true
  610. virtual bool GetWaitForResourcesProgress( WaitForResourcesHandle_t handle, float *progress /* out */ , bool *complete /* out */ ) = 0;
  611. // cancels a progress call
  612. virtual void CancelWaitForResources( WaitForResourcesHandle_t handle ) = 0;
  613. // hints that a set of files will be loaded in near future
  614. // HintResourceNeed() is not to be confused with resource precaching.
  615. virtual int HintResourceNeed( const char *hintlist, int forgetEverything ) = 0;
  616. // returns true if a file is on disk
  617. virtual bool IsFileImmediatelyAvailable(const char *pFileName) = 0;
  618. // copies file out of pak/bsp/steam cache onto disk (to be accessible by third-party code)
  619. virtual void GetLocalCopy( const char *pFileName ) = 0;
  620. //--------------------------------------------------------
  621. // Debugging operations
  622. //--------------------------------------------------------
  623. // Dump to printf/OutputDebugString the list of files that have not been closed
  624. virtual void PrintOpenedFiles( void ) = 0;
  625. virtual void PrintSearchPaths( void ) = 0;
  626. // output
  627. virtual void SetWarningFunc( void (*pfnWarning)( PRINTF_FORMAT_STRING const char *fmt, ... ) ) = 0;
  628. virtual void SetWarningLevel( FileWarningLevel_t level ) = 0;
  629. virtual void AddLoggingFunc( void (*pfnLogFunc)( const char *fileName, const char *accessType ) ) = 0;
  630. virtual void RemoveLoggingFunc( FileSystemLoggingFunc_t logFunc ) = 0;
  631. // Returns the file system statistics retreived by the implementation. Returns NULL if not supported.
  632. virtual const FileSystemStatistics *GetFilesystemStatistics() = 0;
  633. //--------------------------------------------------------
  634. // Start of new functions after Lost Coast release (7/05)
  635. //--------------------------------------------------------
  636. virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) = 0;
  637. // Extended version of read provides more context to allow for more optimal reading
  638. virtual int ReadEx( void* pOutput, int sizeDest, int size, FileHandle_t file ) = 0;
  639. 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;
  640. virtual FileNameHandle_t FindFileName( char const *pFileName ) = 0;
  641. #if defined( TRACK_BLOCKING_IO )
  642. virtual void EnableBlockingFileAccessTracking( bool state ) = 0;
  643. virtual bool IsBlockingFileAccessEnabled() const = 0;
  644. virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() = 0;
  645. #endif
  646. virtual void SetupPreloadData() = 0;
  647. virtual void DiscardPreloadData() = 0;
  648. // Fixme, we could do these via a string embedded into the compiled data, etc...
  649. enum KeyValuesPreloadType_t
  650. {
  651. TYPE_VMT,
  652. TYPE_SOUNDEMITTER,
  653. TYPE_SOUNDSCAPE,
  654. NUM_PRELOAD_TYPES
  655. };
  656. virtual void LoadCompiledKeyValues( KeyValuesPreloadType_t type, char const *archiveFile ) = 0;
  657. // 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.
  658. // Otherwise, it'll just fall through to the regular KeyValues loading routines
  659. virtual KeyValues *LoadKeyValues( KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0;
  660. virtual bool LoadKeyValues( KeyValues& head, KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0;
  661. virtual bool ExtractRootKeyName( KeyValuesPreloadType_t type, char *outbuf, size_t bufsize, char const *filename, char const *pPathID = 0 ) = 0;
  662. virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0;
  663. virtual FSAsyncStatus_t AsyncWriteFile(const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0;
  664. // Async read functions with memory blame
  665. FSAsyncStatus_t AsyncReadCreditAlloc( const FileAsyncRequest_t &request, const char *pszFile, int line, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultipleCreditAlloc( &request, 1, pszFile, line, phControl ); }
  666. virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *phControls = NULL ) = 0;
  667. virtual bool GetFileTypeForFullPath( char const *pFullPath, OUT_Z_BYTECAP(bufSizeInBytes) wchar_t *buf, size_t bufSizeInBytes ) = 0;
  668. //--------------------------------------------------------
  669. //--------------------------------------------------------
  670. virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0;
  671. //--------------------------------------------------------
  672. // Optimal IO operations
  673. //--------------------------------------------------------
  674. virtual bool GetOptimalIOConstraints( FileHandle_t hFile, unsigned *pOffsetAlign, unsigned *pSizeAlign, unsigned *pBufferAlign ) = 0;
  675. inline unsigned GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize );
  676. virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize = 0, unsigned nOffset = 0 ) = 0;
  677. virtual void FreeOptimalReadBuffer( void * ) = 0;
  678. //--------------------------------------------------------
  679. //
  680. //--------------------------------------------------------
  681. virtual void BeginMapAccess() = 0;
  682. virtual void EndMapAccess() = 0;
  683. // Returns true on success, otherwise false if it can't be resolved
  684. // Prefer using the FullPathToRelativePathEx_safe template wrapper to calling this directly
  685. virtual bool FullPathToRelativePathEx( const char *pFullpath, const char *pPathId, OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars ) = 0;
  686. template <size_t maxLenInChars> bool FullPathToRelativePathEx_safe( const char *pFullpath, OUT_Z_ARRAY char (&pDest)[maxLenInChars] )
  687. {
  688. return FullPathToRelativePathEx( pFullpath, pDest, (int)maxLenInChars );
  689. }
  690. virtual int GetPathIndex( const FileNameHandle_t &handle ) = 0;
  691. virtual long GetPathTime( const char *pPath, const char *pPathID ) = 0;
  692. virtual DVDMode_t GetDVDMode() = 0;
  693. //--------------------------------------------------------
  694. // Whitelisting for pure servers.
  695. //--------------------------------------------------------
  696. // This should be called ONCE at startup. Multiplayer games (gameinfo.txt does not contain singleplayer_only)
  697. // want to enable this so sv_pure works.
  698. virtual void EnableWhitelistFileTracking( bool bEnable, bool bCacheAllVPKHashes, bool bRecalculateAndCheckHashes ) = 0;
  699. // This is called when the client connects to a server using a pure_server_whitelist.txt file.
  700. virtual void RegisterFileWhitelist( IPureServerWhitelist *pWhiteList, IFileList **pFilesToReload ) = 0;
  701. // Called when the client logs onto a server. Any files that came off disk should be marked as
  702. // unverified because this server may have a different set of files it wants to guarantee.
  703. virtual void MarkAllCRCsUnverified() = 0;
  704. // As the server loads whitelists when it transitions maps, it calls this to calculate CRCs for any files marked
  705. // with check_crc. Then it calls CheckCachedFileCRC later when it gets client requests to verify CRCs.
  706. virtual void CacheFileCRCs( const char *pPathname, ECacheCRCType eType, IFileList *pFilter ) = 0;
  707. virtual EFileCRCStatus CheckCachedFileHash( const char *pPathID, const char *pRelativeFilename, int nFileFraction, FileHash_t *pFileHash ) = 0;
  708. // Fills in the list of files that have been loaded off disk and have not been verified.
  709. // Returns the number of files filled in (between 0 and nMaxFiles).
  710. //
  711. // This also removes any files it's returning from the unverified CRC list, so they won't be
  712. // returned from here again.
  713. // The client sends batches of these to the server to verify.
  714. virtual int GetUnverifiedFileHashes( CUnverifiedFileHash *pFiles, int nMaxFiles ) = 0;
  715. // Control debug message output.
  716. // Pass a combination of WHITELIST_SPEW_ flags.
  717. virtual int GetWhitelistSpewFlags() = 0;
  718. virtual void SetWhitelistSpewFlags( int flags ) = 0;
  719. // Installs a callback used to display a dirty disk dialog
  720. virtual void InstallDirtyDiskReportFunc( FSDirtyDiskReportFunc_t func ) = 0;
  721. //--------------------------------------------------------
  722. // Low-level file caching. Cached files are loaded into memory and used
  723. // to satisfy read requests (sync and async) until the cache is destroyed.
  724. // NOTE: this could defeat file whitelisting, if a file were loaded in
  725. // a non-whitelisted environment and then reused. Clients should not cache
  726. // files across moves between pure/non-pure environments.
  727. //--------------------------------------------------------
  728. virtual FileCacheHandle_t CreateFileCache() = 0;
  729. virtual void AddFilesToFileCache( FileCacheHandle_t cacheId, const char **ppFileNames, int nFileNames, const char *pPathID ) = 0;
  730. virtual bool IsFileCacheFileLoaded( FileCacheHandle_t cacheId, const char* pFileName ) = 0;
  731. virtual bool IsFileCacheLoaded( FileCacheHandle_t cacheId ) = 0;
  732. virtual void DestroyFileCache( FileCacheHandle_t cacheId ) = 0;
  733. // XXX For now, we assume that all path IDs are "GAME", never cache files
  734. // outside of the game search path, and preferentially return those files
  735. // whenever anyone searches for a match even if an on-disk file in another
  736. // folder would have been found first in a traditional search. extending
  737. // the memory cache to cover non-game files isn't necessary right now, but
  738. // should just be a matter of defining a more complex key type. (henryg)
  739. // Register a CMemoryFileBacking; must balance with UnregisterMemoryFile.
  740. // Returns false and outputs an ref-bumped pointer to the existing entry
  741. // if the same file has already been registered by someone else; this must
  742. // be Unregistered to maintain the balance.
  743. virtual bool RegisterMemoryFile( CMemoryFileBacking *pFile, CMemoryFileBacking **ppExistingFileWithRef ) = 0;
  744. // Unregister a CMemoryFileBacking; must balance with RegisterMemoryFile.
  745. virtual void UnregisterMemoryFile( CMemoryFileBacking *pFile ) = 0;
  746. virtual void CacheAllVPKFileHashes( bool bCacheAllVPKHashes, bool bRecalculateAndCheckHashes ) = 0;
  747. virtual bool CheckVPKFileHash( int PackFileID, int nPackFileNumber, int nFileFraction, MD5Value_t &md5Value ) = 0;
  748. // Called when we unload a file, to remove that file's info for pure server purposes.
  749. virtual void NotifyFileUnloaded( const char *pszFilename, const char *pPathId ) = 0;
  750. // Returns true on successfully retrieve case-sensitive full path, otherwise false
  751. // Prefer using the GetCaseCorrectFullPath template wrapper to calling this directly
  752. virtual bool GetCaseCorrectFullPath_Ptr( const char *pFullPath, OUT_Z_CAP( maxLenInChars ) char *pDest, int maxLenInChars ) = 0;
  753. template <size_t maxLenInChars> bool GetCaseCorrectFullPath( const char *pFullPath, OUT_Z_ARRAY char( &pDest )[maxLenInChars] )
  754. {
  755. return GetCaseCorrectFullPath_Ptr( pFullPath, pDest, (int)maxLenInChars );
  756. }
  757. };
  758. //-----------------------------------------------------------------------------
  759. // Memory file backing, which you can use to fake out the filesystem, caching data
  760. // in memory and have it associated with a file
  761. //-----------------------------------------------------------------------------
  762. class CMemoryFileBacking : public CRefCounted<CRefCountServiceMT>
  763. {
  764. public:
  765. // malloc and free in headers with our janky memdbg system. What could go wrong. Except everything.
  766. // (this free can't skip memdbg if paired malloc used memdbg)
  767. #include <memdbgon.h>
  768. CMemoryFileBacking( IFileSystem* pFS ) : m_pFS( pFS ), m_nRegistered( 0 ), m_pFileName( NULL ), m_pData( NULL ), m_nLength( 0 ) { }
  769. ~CMemoryFileBacking() { free( (char*) m_pFileName ); if ( m_pData ) m_pFS->FreeOptimalReadBuffer( (char*) m_pData ); }
  770. #include <memdbgoff.h>
  771. IFileSystem* m_pFS;
  772. int m_nRegistered;
  773. const char* m_pFileName;
  774. const char* m_pData;
  775. int m_nLength;
  776. private:
  777. CMemoryFileBacking( const CMemoryFileBacking& ); // not defined
  778. CMemoryFileBacking& operator=( const CMemoryFileBacking& ); // not defined
  779. };
  780. //-----------------------------------------------------------------------------
  781. #if defined( _X360 ) && !defined( _RETAIL )
  782. extern char g_szXboxProfileLastFileOpened[MAX_PATH];
  783. #define SetLastProfileFileRead( s ) Q_strncpy( g_szXboxProfileLastFileOpened, sizeof( g_szXboxProfileLastFileOpened), pFileName )
  784. #define GetLastProfileFileRead() (&g_szXboxProfileLastFileOpened[0])
  785. #else
  786. #define SetLastProfileFileRead( s ) ((void)0)
  787. #define GetLastProfileFileRead() NULL
  788. #endif
  789. #if defined( _X360 ) && defined( _BASETSD_H_ )
  790. class CXboxDiskCacheSetter
  791. {
  792. public:
  793. CXboxDiskCacheSetter( SIZE_T newSize )
  794. {
  795. m_oldSize = XGetFileCacheSize();
  796. XSetFileCacheSize( newSize );
  797. }
  798. ~CXboxDiskCacheSetter()
  799. {
  800. XSetFileCacheSize( m_oldSize );
  801. }
  802. private:
  803. SIZE_T m_oldSize;
  804. };
  805. #define DISK_INTENSIVE() CXboxDiskCacheSetter cacheSetter( 1024*1024 )
  806. #else
  807. #define DISK_INTENSIVE() ((void)0)
  808. #endif
  809. //-----------------------------------------------------------------------------
  810. inline unsigned IFileSystem::GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize )
  811. {
  812. unsigned align;
  813. if ( GetOptimalIOConstraints( hFile, &align, NULL, NULL ) )
  814. return AlignValue( nLogicalSize, align );
  815. else
  816. return nLogicalSize;
  817. }
  818. //-----------------------------------------------------------------------------
  819. // We include this here so it'll catch compile errors in VMPI early.
  820. #include "filesystem_passthru.h"
  821. //-----------------------------------------------------------------------------
  822. // Async memory tracking
  823. //-----------------------------------------------------------------------------
  824. #if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
  825. #define AsyncRead( a, b ) AsyncReadCreditAlloc( a, __FILE__, __LINE__, b )
  826. #define AsyncReadMutiple( a, b, c ) AsyncReadMultipleCreditAlloc( a, b, __FILE__, __LINE__, c )
  827. #endif
  828. extern IFileSystem *g_pFullFileSystem;
  829. #endif // FILESYSTEM_H