forked from shokunin000/te120
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilesystem.h
978 lines (792 loc) · 39 KB
/
filesystem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#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"
#ifndef FILESYSTEM_H
#define FILESYSTEM_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 long 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
virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize, PathTypeFilter_t pathFilter = FILTER_NONE, PathTypeQuery_t *pPathType = NULL ) = 0;
// Returns the search path, each path is separated by ;s. Returns the length of the string returned
virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) = 0;
// 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, long 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
virtual const char *GetLocalPath( const char *pFileName, char *pLocalPath, int localPathBufferSize ) = 0;
// Returns true on success ( based on current list of search paths, otherwise false if
// it can't be resolved )
virtual bool FullPathToRelativePath( const char *pFullpath, char *pRelative, int maxlen ) = 0;
// 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
virtual bool FullPathToRelativePathEx( const char *pFullpath, const char *pPathId, char *pRelative, int maxlen ) = 0;
virtual int GetPathIndex( const FileNameHandle_t &handle ) = 0;
virtual long 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;
};
//-----------------------------------------------------------------------------
// 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:
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 ); }
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