uid issue
This commit is contained in:
2145
filesystem/QueuedLoader.cpp
Normal file
2145
filesystem/QueuedLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1703
filesystem/XboxInstaller.cpp
Normal file
1703
filesystem/XboxInstaller.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,64 @@
|
||||
// ----------------------------------------- //
|
||||
// File generated by VPC //
|
||||
// ----------------------------------------- //
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\basefilesystem.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\basefilesystem.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\basefilesystem.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\basefilesystemasync.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\basefilesystemasync.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\basefilesystemasync.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\common\debug_dll_check.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\common\debug_dll_check.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\common\debug_dll_check.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filesystem_stdio.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filesystem_stdio.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filesystem_stdio.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filesystemasync.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filesystemasync.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filesystemasync.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filetracker.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filetracker.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\filetracker.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\kevvaluescompiler.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\kevvaluescompiler.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\kevvaluescompiler.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\tier0\memoverride.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\tier0\memoverride.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\tier0\memoverride.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\QueuedLoader.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\QueuedLoader.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\filesystem\QueuedLoader.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\zip_utils.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\zip_utils.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\public\zip_utils.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
9480
filesystem/basefilesystem.cpp
Normal file
9480
filesystem/basefilesystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1396
filesystem/basefilesystem.h
Normal file
1396
filesystem/basefilesystem.h
Normal file
File diff suppressed because it is too large
Load Diff
1481
filesystem/basefilesystemasync.cpp
Normal file
1481
filesystem/basefilesystemasync.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2060
filesystem/filegroup.cpp
Normal file
2060
filesystem/filegroup.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1348
filesystem/filesystem_async.cpp
Normal file
1348
filesystem/filesystem_async.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2125
filesystem/filesystem_stdio.cpp
Normal file
2125
filesystem/filesystem_stdio.cpp
Normal file
File diff suppressed because it is too large
Load Diff
98
filesystem/filesystem_stdio.vpc
Normal file
98
filesystem/filesystem_stdio.vpc
Normal file
@ -0,0 +1,98 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// FILESYSTEM_STDIO.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$macro SRCDIR ".."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration "Debug"
|
||||
{
|
||||
$General
|
||||
{
|
||||
$OutputDirectory "Debug_Stdio$PLATSUBDIR" [$WINDOWS]
|
||||
$IntermediateDirectory "Debug_Stdio$PLATSUBDIR" [$WINDOWS]
|
||||
$OutputDirectory "Debug_Stdio_360" [$X360]
|
||||
$IntermediateDirectory "Debug_Stdio_360" [$X360]
|
||||
}
|
||||
}
|
||||
|
||||
$Configuration "Release"
|
||||
{
|
||||
$General
|
||||
{
|
||||
$OutputDirectory "Release_Stdio$PLATSUBDIR" [$WINDOWS]
|
||||
$IntermediateDirectory "Release_Stdio$PLATSUBDIR" [$WINDOWS]
|
||||
$OutputDirectory "Release_Stdio_360" [$X360]
|
||||
$IntermediateDirectory "Release_Stdio_360" [$X360]
|
||||
}
|
||||
}
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$PreprocessorDefinitions "$BASE;FILESYSTEM_STDIO_EXPORTS;DONT_PROTECT_FILEIO_FUNCTIONS;PROTECTED_THINGS_ENABLE"
|
||||
$PreprocessorDefinitions "$BASE;_USE_32BIT_TIME_T" [$WIN32]
|
||||
}
|
||||
$Linker [!$PS3]
|
||||
{
|
||||
$SystemLibraries "iconv" [$OSXALL]
|
||||
}
|
||||
}
|
||||
|
||||
$Project "filesystem_stdio"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "basefilesystem.cpp"
|
||||
$File "basefilesystemasync.cpp"
|
||||
$File "filetracker.cpp"
|
||||
$File "filesystemasync.cpp" [!$PS3]
|
||||
$File "filesystem_stdio.cpp"
|
||||
$File "$SRCDIR\public\kevvaluescompiler.cpp" [!$PS3]
|
||||
$File "$SRCDIR\public\zip_utils.cpp" [!$PS3]
|
||||
$File "QueuedLoader.cpp"
|
||||
$File "xboxinstaller.cpp" [$X360]
|
||||
$File "linux_support.cpp" [$POSIX]
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "basefilesystem.h"
|
||||
$File "filesystemasync.h"
|
||||
$File "filetracker.h"
|
||||
$File "threadsaferefcountedobject.h"
|
||||
$File "$SRCDIR\public\tier0\basetypes.h"
|
||||
$File "$SRCDIR\public\bspfile.h"
|
||||
$File "$SRCDIR\public\bspflags.h"
|
||||
$File "$SRCDIR\public\tier1\characterset.h"
|
||||
$File "$SRCDIR\public\tier0\dbg.h"
|
||||
$File "$SRCDIR\public\tier0\fasttimer.h"
|
||||
$File "$SRCDIR\public\filesystem.h"
|
||||
$File "$SRCDIR\public\filesystem\iasyncfilesystem.h"
|
||||
$File "$SRCDIR\public\ifilelist.h"
|
||||
$File "$SRCDIR\public\appframework\iappsystem.h"
|
||||
$File "$SRCDIR\public\tier1\interface.h"
|
||||
$File "$SRCDIR\public\tier0\platform.h"
|
||||
$File "$SRCDIR\public\tier1\strtools.h"
|
||||
$File "$SRCDIR\public\tier1\utlmemory.h"
|
||||
$File "$SRCDIR\public\tier1\utlrbtree.h"
|
||||
$File "$SRCDIR\public\tier1\utlsymbol.h"
|
||||
$File "$SRCDIR\public\tier1\utlvector.h"
|
||||
$File "$SRCDIR\public\vstdlib\vstdlib.h"
|
||||
$File "$SRCDIR\public\keyvaluescompiler.h"
|
||||
$File "$SRCDIR\public\filesystem\IQueuedLoader.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$lib tier2
|
||||
$lib vpklib [!$X360 && !$PS3]
|
||||
}
|
||||
|
||||
|
||||
}
|
13
filesystem/filesystem_stdio.vpc.vpc_cache
Normal file
13
filesystem/filesystem_stdio.vpc.vpc_cache
Normal file
@ -0,0 +1,13 @@
|
||||
"vpc_cache"
|
||||
{
|
||||
"CacheVersion" "1"
|
||||
"win32"
|
||||
{
|
||||
"CRCFile" "filesystem_stdio.vcxproj.vpc_crc"
|
||||
"OutputFiles"
|
||||
{
|
||||
"0" "filesystem_stdio.vcxproj"
|
||||
"1" "filesystem_stdio.vcxproj.filters"
|
||||
}
|
||||
}
|
||||
}
|
532
filesystem/filesystem_stdio/FileTracker.cpp
Normal file
532
filesystem/filesystem_stdio/FileTracker.cpp
Normal file
@ -0,0 +1,532 @@
|
||||
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "basefilesystem.h"
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
|
||||
bool CompareFilenames( const char *pa, const char *pb )
|
||||
{
|
||||
// Case-insensitive and path separator-insensitive compare.
|
||||
const char *a = pa;
|
||||
const char *b = pb;
|
||||
while ( *a && *b )
|
||||
{
|
||||
char ca = *a;
|
||||
char cb = *b;
|
||||
|
||||
if ( ca >= 'a' && ca <= 'z' )
|
||||
ca = 'A' + (ca - 'a');
|
||||
else if ( ca == '/' )
|
||||
ca = '\\';
|
||||
|
||||
if ( cb >= 'a' && cb <= 'z' )
|
||||
cb = 'A' + (cb - 'a');
|
||||
else if ( cb == '/' )
|
||||
cb = '\\';
|
||||
|
||||
if ( ca != cb )
|
||||
return false;
|
||||
|
||||
++a;
|
||||
++b;
|
||||
}
|
||||
|
||||
// Filenames also must be the same length.
|
||||
if ( *a != *b )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CFileTracker.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CFileTracker::CFileTracker( CBaseFileSystem *pFileSystem )
|
||||
{
|
||||
m_pFileSystem = pFileSystem;
|
||||
}
|
||||
|
||||
CFileTracker::~CFileTracker()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CFileTracker::NoteFileLoadedFromDisk( const char *pFilename, const char *pPathID, FileHandle_t fp )
|
||||
{
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
if ( !pPathID )
|
||||
pPathID = "";
|
||||
|
||||
CPathIDFileList *pPath = GetPathIDFileList( pPathID );
|
||||
CFileInfo *pInfo = pPath->FindFileInfo( pFilename );
|
||||
|
||||
if ( m_pFileSystem->m_WhitelistSpewFlags & WHITELIST_SPEW_WHILE_LOADING )
|
||||
{
|
||||
if ( pInfo )
|
||||
Warning( "(Duplicate): [%s]\\%s", pPathID, pFilename );
|
||||
else
|
||||
Warning( "(Unique ): [%s]\\%s", pPathID, pFilename );
|
||||
}
|
||||
|
||||
if ( pInfo )
|
||||
{
|
||||
// Clear all the flags, but remember if we ever had a CRC.
|
||||
pInfo->m_Flags &= k_eFileFlagsGotCRCOnce;
|
||||
pInfo->m_Flags &= ~k_eFileFlagsFailedToLoadLastTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
pInfo = pPath->AddFileInfo( pFilename );
|
||||
pInfo->m_Flags = (EFileFlags)0;
|
||||
}
|
||||
|
||||
if ( !fp )
|
||||
{
|
||||
if ( m_pFileSystem->m_WhitelistSpewFlags & WHITELIST_SPEW_WHILE_LOADING )
|
||||
{
|
||||
Warning( "\n" );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Remember that we calculated the CRC and that it is unverified.
|
||||
pInfo->m_CRC = CalculateCRCForFile( fp );
|
||||
pInfo->m_Flags |= k_eFileFlagsHasCRC | k_eFileFlagsGotCRCOnce;
|
||||
if ( pInfo->m_iNeedsVerificationListIndex == -1 )
|
||||
pInfo->m_iNeedsVerificationListIndex = m_NeedsVerificationList.AddToTail( pInfo );
|
||||
|
||||
if ( m_pFileSystem->m_WhitelistSpewFlags & WHITELIST_SPEW_WHILE_LOADING )
|
||||
{
|
||||
Warning( " - %u\n", pInfo->m_CRC );
|
||||
}
|
||||
}
|
||||
|
||||
void CFileTracker::NoteFileFailedToLoad( const char *pFilename, const char *pPathID )
|
||||
{
|
||||
CPathIDFileList *pPath = GetPathIDFileList( pPathID );
|
||||
CFileInfo *pInfo = pPath->FindFileInfo( pFilename );
|
||||
if ( pInfo )
|
||||
{
|
||||
pInfo->m_Flags |= k_eFileFlagsFailedToLoadLastTime;
|
||||
}
|
||||
}
|
||||
|
||||
CRC32_t CFileTracker::CalculateCRCForFile( FileHandle_t fp )
|
||||
{
|
||||
CRC32_t crc;
|
||||
|
||||
// Calculate the CRC.
|
||||
unsigned int initialFilePos = m_pFileSystem->Tell( fp );
|
||||
m_pFileSystem->Seek( fp, 0, FILESYSTEM_SEEK_HEAD );
|
||||
|
||||
#define CRC_CHUNK_SIZE (32*1024)
|
||||
char tempBuf[CRC_CHUNK_SIZE];
|
||||
|
||||
CRC32_Init( &crc );
|
||||
|
||||
unsigned int fileLength = m_pFileSystem->Size( fp );
|
||||
|
||||
int nChunks = fileLength / CRC_CHUNK_SIZE + 1;
|
||||
unsigned int curStartByte = 0;
|
||||
for ( int iChunk=0; iChunk < nChunks; iChunk++ )
|
||||
{
|
||||
int curEndByte = min( curStartByte + CRC_CHUNK_SIZE, fileLength );
|
||||
int chunkLen = curEndByte - curStartByte;
|
||||
if ( chunkLen == 0 )
|
||||
break;
|
||||
|
||||
m_pFileSystem->Read( tempBuf, chunkLen, fp ); // TODO: handle errors here..
|
||||
CRC32_ProcessBuffer( &crc, tempBuf, chunkLen );
|
||||
|
||||
curStartByte += CRC_CHUNK_SIZE;
|
||||
}
|
||||
CRC32_Final( &crc );
|
||||
|
||||
// Go back to where we started.
|
||||
m_pFileSystem->Seek( fp, initialFilePos, FILESYSTEM_SEEK_HEAD );
|
||||
return crc;
|
||||
}
|
||||
|
||||
CFileInfo* CFileTracker::GetFileInfo( const char *pFilename, const char *pPathID )
|
||||
{
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
CPathIDFileList *pPath = GetPathIDFileList( pPathID, false );
|
||||
if ( !pPath )
|
||||
return NULL;
|
||||
|
||||
return pPath->FindFileInfo( pFilename );
|
||||
}
|
||||
|
||||
int CFileTracker::GetFileInfos( CFileInfo **ppFileInfos, int nMaxFileInfos, const char *pFilename )
|
||||
{
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
int nOut = 0;
|
||||
for ( int i=m_PathIDs.First(); i != m_PathIDs.InvalidIndex(); i=m_PathIDs.Next( i ) )
|
||||
{
|
||||
CFileInfo *pCur = m_PathIDs[i]->FindFileInfo( pFilename );
|
||||
if ( pCur )
|
||||
{
|
||||
if ( nOut < nMaxFileInfos )
|
||||
{
|
||||
ppFileInfos[nOut++] = pCur;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( !"CFileTracker::GetFileInfos - overflowed list!" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nOut;
|
||||
}
|
||||
|
||||
void CFileTracker::NoteFileLoadedFromSteam( const char *pFilename, const char *pPathID, bool bForcedLoadFromSteam )
|
||||
{
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
if ( !pPathID )
|
||||
pPathID = "";
|
||||
|
||||
CPathIDFileList *pPath = GetPathIDFileList( pPathID );
|
||||
CFileInfo *pInfo = pPath->FindFileInfo( pFilename );
|
||||
if ( !pInfo )
|
||||
pInfo = pPath->AddFileInfo( pFilename );
|
||||
|
||||
if ( m_pFileSystem->m_WhitelistSpewFlags & WHITELIST_SPEW_WHILE_LOADING )
|
||||
{
|
||||
Warning( "From Steam: [%s]\\%s\n", pPathID, pFilename );
|
||||
}
|
||||
|
||||
pInfo->m_Flags = k_eFileFlagsLoadedFromSteam;
|
||||
if ( bForcedLoadFromSteam )
|
||||
pInfo->m_Flags |= k_eFileFlagsForcedLoadFromSteam;
|
||||
}
|
||||
|
||||
|
||||
void CFileTracker::CalculateMissingCRCs( IFileList *pWantCRCList )
|
||||
{
|
||||
// First build a list of files that need a CRC and don't have one.
|
||||
m_Mutex.Lock();
|
||||
CUtlLinkedList<CFileInfo*,int> needCRCList;
|
||||
|
||||
for ( int i=m_PathIDs.First(); i != m_PathIDs.InvalidIndex(); i=m_PathIDs.Next( i ) )
|
||||
{
|
||||
CPathIDFileList *pPath = m_PathIDs[i];
|
||||
FOR_EACH_LL( pPath->m_Files, j )
|
||||
{
|
||||
CFileInfo *pInfo = pPath->m_Files[j];
|
||||
|
||||
if ( !( pInfo->m_Flags & k_eFileFlagsLoadedFromSteam ) && !( pInfo->m_Flags & k_eFileFlagsHasCRC ) )
|
||||
{
|
||||
// If the new "force match" list doesn't care whether the file has a CRC or not, then don't bother to calculate it.
|
||||
if ( !pWantCRCList->IsFileInList( pInfo->m_pFilename ) )
|
||||
continue;
|
||||
|
||||
needCRCList.AddToTail( pInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Mutex.Unlock();
|
||||
|
||||
// Then, when the mutex is not locked, go generate the CRCs for them.
|
||||
FOR_EACH_LL( needCRCList, i )
|
||||
{
|
||||
CFileInfo *pInfo = needCRCList[i];
|
||||
CalculateMissingCRC( pInfo->m_pFilename, pInfo->GetPathIDString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CFileTracker::CacheFileCRC( const char *pPathID, const char *pRelativeFilename )
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
|
||||
// Get the file's info. Load the file if necessary.
|
||||
CFileInfo *pInfo = GetFileInfo( pRelativeFilename, pPathID );
|
||||
if ( !pInfo )
|
||||
{
|
||||
CalculateMissingCRC( pRelativeFilename, pPathID );
|
||||
pInfo = GetFileInfo( pRelativeFilename, pPathID );
|
||||
}
|
||||
|
||||
if ( !pInfo )
|
||||
return;
|
||||
|
||||
// Already cached a CRC for this file?
|
||||
if ( !( pInfo->m_Flags & k_eFileFlagsGotCRCOnce ) )
|
||||
{
|
||||
// Ok, it's from disk but we don't have the CRC.
|
||||
CalculateMissingCRC( pInfo->GetFilename(), pInfo->GetPathIDString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CFileTracker::CacheFileCRC_Copy( const char *pPathID, const char *pRelativeFilename, const char *pPathIDToCopyFrom )
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
|
||||
// Get the file's info. Load the file if necessary.
|
||||
CFileInfo *pSourceInfo = GetFileInfo( pRelativeFilename, pPathIDToCopyFrom );
|
||||
if ( !pSourceInfo || !( pSourceInfo->m_Flags & k_eFileFlagsGotCRCOnce ) )
|
||||
{
|
||||
// Strange, we don't have a CRC for the one they wanted to copy from, so calculate that CRC.
|
||||
CacheFileCRC( pPathIDToCopyFrom, pRelativeFilename );
|
||||
if ( !( pSourceInfo->m_Flags & k_eFileFlagsGotCRCOnce ) )
|
||||
{
|
||||
// Still didn't get it. Ok.. well get a CRC for the target one anyway.
|
||||
CacheFileCRC( pPathID, pRelativeFilename );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup a CFileInfo for the target..
|
||||
CPathIDFileList *pPath = GetPathIDFileList( pPathID );
|
||||
CFileInfo *pDestInfo = pPath->FindFileInfo( pRelativeFilename );
|
||||
if ( !pDestInfo )
|
||||
pDestInfo = pPath->AddFileInfo( pRelativeFilename );
|
||||
|
||||
pDestInfo->m_CRC = pSourceInfo->m_CRC;
|
||||
pDestInfo->m_Flags = pSourceInfo->m_Flags;
|
||||
}
|
||||
|
||||
|
||||
EFileCRCStatus CFileTracker::CheckCachedFileCRC( const char *pPathID, const char *pRelativeFilename, CRC32_t *pCRC )
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
|
||||
// Get the file's info. Load the file if necessary.
|
||||
CFileInfo *pInfo = GetFileInfo( pRelativeFilename, pPathID );
|
||||
if ( pInfo && (pInfo->m_Flags & k_eFileFlagsGotCRCOnce) )
|
||||
{
|
||||
*pCRC = pInfo->m_CRC;
|
||||
return k_eFileCRCStatus_GotCRC;
|
||||
}
|
||||
else
|
||||
{
|
||||
return k_eFileCRCStatus_CantOpenFile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CFileTracker::CalculateMissingCRC( const char *pFilename, const char *pPathID )
|
||||
{
|
||||
// Force it to make a CRC of disk files.
|
||||
FileHandle_t fh = m_pFileSystem->FindFileInSearchPaths( pFilename, "rb", pPathID, FSOPEN_FORCE_TRACK_CRC, NULL, true );
|
||||
if ( !fh )
|
||||
return;
|
||||
|
||||
CFileInfo *pInfo = GetFileInfo( pFilename, pPathID );
|
||||
if ( pInfo )
|
||||
{
|
||||
// Now we're about to modify the file itself.. lock the mutex.
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
// The FindFileInSearchPaths call might have done the CRC for us.
|
||||
if ( !( pInfo->m_Flags & k_eFileFlagsHasCRC ) )
|
||||
{
|
||||
pInfo->m_CRC = CalculateCRCForFile( fh );
|
||||
pInfo->m_Flags |= k_eFileFlagsHasCRC | k_eFileFlagsGotCRCOnce;
|
||||
if ( pInfo->m_iNeedsVerificationListIndex == -1 )
|
||||
{
|
||||
pInfo->m_iNeedsVerificationListIndex = m_NeedsVerificationList.AddToTail( pInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( false );
|
||||
}
|
||||
|
||||
m_pFileSystem->Close( fh );
|
||||
}
|
||||
|
||||
|
||||
void CFileTracker::MarkAllCRCsUnverified()
|
||||
{
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
// First clear the 'needs verification' list.
|
||||
MarkAllCRCsVerified();
|
||||
|
||||
Assert( m_NeedsVerificationList.Count() == 0 );
|
||||
for ( int i=m_PathIDs.First(); i != m_PathIDs.InvalidIndex(); i=m_PathIDs.Next( i ) )
|
||||
{
|
||||
CPathIDFileList *pPath = m_PathIDs[i];
|
||||
FOR_EACH_LL( pPath->m_Files, j )
|
||||
{
|
||||
CFileInfo *pInfo = pPath->m_Files[j];
|
||||
|
||||
if ( !(pInfo->m_Flags & k_eFileFlagsLoadedFromSteam) && ( pInfo->m_Flags & k_eFileFlagsHasCRC ) )
|
||||
{
|
||||
pInfo->m_iNeedsVerificationListIndex = m_NeedsVerificationList.AddToTail( pInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CFileTracker::MarkAllCRCsVerified( bool bLockMutex )
|
||||
{
|
||||
if ( bLockMutex )
|
||||
m_Mutex.Lock();
|
||||
|
||||
FOR_EACH_LL( m_NeedsVerificationList, i )
|
||||
{
|
||||
m_NeedsVerificationList[i]->m_iNeedsVerificationListIndex = -1;
|
||||
}
|
||||
|
||||
m_NeedsVerificationList.Purge();
|
||||
|
||||
if ( bLockMutex )
|
||||
m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
|
||||
int CFileTracker::GetUnverifiedCRCFiles( CUnverifiedCRCFile *pFiles, int nMaxFiles )
|
||||
{
|
||||
Assert( nMaxFiles > 0 );
|
||||
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
int iOutFile = 0;
|
||||
int iNext = 0;
|
||||
for ( int i=m_NeedsVerificationList.Head(); i != m_NeedsVerificationList.InvalidIndex(); i=iNext )
|
||||
{
|
||||
iNext = m_NeedsVerificationList.Next( i );
|
||||
|
||||
CFileInfo *pInfo = m_NeedsVerificationList[i];
|
||||
|
||||
// Remove this entry from the list.
|
||||
m_NeedsVerificationList.Remove( i );
|
||||
pInfo->m_iNeedsVerificationListIndex = -1;
|
||||
|
||||
// This can happen if a file that was in this list was loaded from Steam since it got added to the list.
|
||||
// In that case, just act like it's not in the list.
|
||||
if ( pInfo->m_Flags & k_eFileFlagsLoadedFromSteam )
|
||||
continue;
|
||||
|
||||
Assert( pInfo->m_Flags & k_eFileFlagsHasCRC );
|
||||
|
||||
// Add this file to their list.
|
||||
CUnverifiedCRCFile *pOutFile = &pFiles[iOutFile];
|
||||
|
||||
V_strncpy( pOutFile->m_Filename, pInfo->m_pFilename, sizeof( pOutFile->m_Filename ) );
|
||||
V_strncpy( pOutFile->m_PathID, pInfo->m_pPathIDFileList->m_PathID.String(), sizeof( pOutFile->m_PathID ) );
|
||||
pOutFile->m_CRC = pInfo->m_CRC;
|
||||
|
||||
|
||||
++iOutFile;
|
||||
if ( iOutFile >= nMaxFiles )
|
||||
return iOutFile;
|
||||
}
|
||||
|
||||
return iOutFile;
|
||||
}
|
||||
|
||||
|
||||
void CFileTracker::Clear()
|
||||
{
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
m_PathIDs.PurgeAndDeleteElements();
|
||||
}
|
||||
|
||||
CPathIDFileList* CFileTracker::GetPathIDFileList( const char *pPathID, bool bAutoAdd )
|
||||
{
|
||||
AUTO_LOCK( m_Mutex );
|
||||
|
||||
if ( !pPathID )
|
||||
pPathID = "";
|
||||
|
||||
int i = m_PathIDs.Find( pPathID );
|
||||
if ( i == m_PathIDs.InvalidIndex() )
|
||||
{
|
||||
if ( bAutoAdd )
|
||||
{
|
||||
CPathIDFileList *pPath = new CPathIDFileList;
|
||||
pPath->m_PathID = pPathID;
|
||||
m_PathIDs.Insert( pPathID, pPath );
|
||||
return pPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_PathIDs[i];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CFileInfo implementation.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CFileInfo::CFileInfo( const char *pFilename )
|
||||
{
|
||||
int len = V_strlen( pFilename ) + 1;
|
||||
m_pFilename = new char[ len ];
|
||||
Q_strncpy( m_pFilename, pFilename, len );
|
||||
m_iNeedsVerificationListIndex = -1;
|
||||
}
|
||||
|
||||
CFileInfo::~CFileInfo()
|
||||
{
|
||||
delete [] m_pFilename;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CPathIDFileList implementation..
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CPathIDFileList::~CPathIDFileList()
|
||||
{
|
||||
m_Files.PurgeAndDeleteElements();
|
||||
}
|
||||
|
||||
CFileInfo* CPathIDFileList::FindFileInfo( const char *pFilename )
|
||||
{
|
||||
Assert( !V_IsAbsolutePath( pFilename ) );
|
||||
|
||||
FOR_EACH_LL( m_Files, i )
|
||||
{
|
||||
CFileInfo *pFileInfo = m_Files[i];
|
||||
|
||||
if ( CompareFilenames( pFilename, pFileInfo->GetFilename() ) )
|
||||
return m_Files[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFileInfo* CPathIDFileList::AddFileInfo( const char *pFilename )
|
||||
{
|
||||
Assert( !V_IsAbsolutePath( pFilename ) );
|
||||
|
||||
CFileInfo *pFileInfo = new CFileInfo( pFilename );
|
||||
pFileInfo->m_pPathIDFileList = this;
|
||||
m_Files.AddToTail( pFileInfo );
|
||||
return pFileInfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
161
filesystem/filesystem_stdio/FileTracker.h
Normal file
161
filesystem/filesystem_stdio/FileTracker.h
Normal file
@ -0,0 +1,161 @@
|
||||
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef FILETRACKER_H
|
||||
#define FILETRACKER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "ifilelist.h"
|
||||
|
||||
|
||||
class CBaseFileSystem;
|
||||
class CFileHandle;
|
||||
|
||||
|
||||
enum EFileFlags
|
||||
{
|
||||
k_eFileFlagsLoadedFromSteam = 0x0001,
|
||||
|
||||
k_eFileFlagsHasCRC = 0x0002, // m_CRC represents the most recently-loaded version of the file. This might be
|
||||
// unset but m_CRC (and k_eFileFlagsGotCRCOnce) could be set, signifying that
|
||||
// the file has been opened since last time we calculated the CRC but we didn't
|
||||
// calculate a CRC for that file version.
|
||||
|
||||
k_eFileFlagsForcedLoadFromSteam = 0x0004, // Set if k_eFileFlagsLoadedFromSteam is set AND we forced Steam to not check the disk for this file.
|
||||
|
||||
k_eFileFlagsGotCRCOnce = 0x0008, // This is set if we EVER had k_eFileFlagsHasCRC set.. m_CRC will still be set in that case,
|
||||
// but it'll be the last CRC we calculated and not necessarily
|
||||
|
||||
k_eFileFlagsFailedToLoadLastTime = 0x0010 // This is used if we had a record of the file and the game tried to open it, but
|
||||
// it couldn't be opened. This will happen if the file was loaded from disk, then
|
||||
// sv_pure is turned on and the file is forced to come from Steam, but there is no
|
||||
// Steam version. In that case, the game should be told to retry the file
|
||||
// next time sv_pure is changed because if sv_pure goes back to 0 it -would- load
|
||||
// the file legitimately.
|
||||
};
|
||||
|
||||
|
||||
class CPathIDFileList;
|
||||
|
||||
|
||||
class CFileInfo
|
||||
{
|
||||
public:
|
||||
CFileInfo( const char *pFilename );
|
||||
~CFileInfo();
|
||||
|
||||
const char* GetFilename();
|
||||
const char* GetPathIDString();
|
||||
|
||||
public:
|
||||
//TODO: Optimize this. Probably should use a hierarchical structure with a list of files in each directory.
|
||||
char *m_pFilename;
|
||||
unsigned short m_Flags; // This is a combination of EFileFlags.
|
||||
CRC32_t m_CRC; // The CRC for this file.
|
||||
CPathIDFileList *m_pPathIDFileList;
|
||||
int m_iNeedsVerificationListIndex; // Index into m_NeedsVerificationList or -1 if not in the list.
|
||||
};
|
||||
|
||||
|
||||
// This tracks a list of files for the specified path ID.
|
||||
class CPathIDFileList
|
||||
{
|
||||
public:
|
||||
~CPathIDFileList();
|
||||
CFileInfo* FindFileInfo( const char *pFilename );
|
||||
CFileInfo* AddFileInfo( const char *pFilename );
|
||||
|
||||
public:
|
||||
CUtlSymbol m_PathID; // "" for a null path ID.
|
||||
CUtlLinkedList<CFileInfo*,int> m_Files;
|
||||
CUtlLinkedList<CFileInfo*,int> m_UnverifiedCRCFiles; // These are the files whose CRCs have not been verified yet.
|
||||
// These just point at entries in m_Files.
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This tracks the files that have been opened by the filesystem.
|
||||
// It remembers if they were loaded from Steam or off-disk.
|
||||
// If the filesystem is tracking CRCs, then it will calculate a CRC
|
||||
// for each file that came off disk.
|
||||
//
|
||||
// TODO: This is similar to CBaseFileSystem::m_OpenedFiles - it could probably
|
||||
// manage both sets of files in the same list. Having 2 separate lists might
|
||||
// be confusing.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CFileTracker
|
||||
{
|
||||
public:
|
||||
CFileTracker( CBaseFileSystem *pFileSystem );
|
||||
~CFileTracker();
|
||||
|
||||
// If this is true, then we'll calculate CRCs for each file that came off disk.
|
||||
void SetWantFileCRCs( bool bWantCRCs );
|
||||
|
||||
// As files are opened, if it is calculating CRCs, it will add those files and their
|
||||
// CRCs to the "unverified CRC" list. The client can then ask the server to verify
|
||||
// those CRCs to make sure the client is "pure".
|
||||
void MarkAllCRCsUnverified();
|
||||
void MarkAllCRCsVerified( bool bLockMutex=true );
|
||||
|
||||
// Cache a file's CRC. Loads the file and calculates the CRC if we don't have it yet.
|
||||
void CacheFileCRC( const char *pPathID, const char *pRelativeFilename );
|
||||
EFileCRCStatus CheckCachedFileCRC( const char *pPathID, const char *pRelativeFilename, CRC32_t *pCRC );
|
||||
|
||||
// This is like CacheFileCRC, but it assumes that the same file would be found by pPathIDToCopyFrom, so it just
|
||||
// copies the CRC record from that path ID into the one in pPathID and avoids a redundant CRC calculation.
|
||||
void CacheFileCRC_Copy( const char *pPathID, const char *pRelativeFilename, const char *pPathIDToCopyFrom );
|
||||
|
||||
// When we don't have a whitelist, it loads files without bothering to calculate their CRCs (we'd only
|
||||
// need them on a pure server), but when we get a whitelist, we'll want the CRCs, so it goes back, opens those
|
||||
// files, and calculates the CRCs for them.
|
||||
void CalculateMissingCRCs( IFileList *pForceMatchList );
|
||||
|
||||
int GetUnverifiedCRCFiles( CUnverifiedCRCFile *pFiles, int nMaxFiles );
|
||||
|
||||
// Note that we just opened this file and calculate a CRC for it.
|
||||
void NoteFileLoadedFromDisk( const char *pFilename, const char *pPathID, FileHandle_t fp );
|
||||
void NoteFileLoadedFromSteam( const char *pFilename, const char *pPathID, bool bForcedLoadFromSteam );
|
||||
void NoteFileFailedToLoad( const char *pFilename, const char *pPathID );
|
||||
|
||||
// Get a file info from a specific path ID.
|
||||
CFileInfo* GetFileInfo( const char *pFilename, const char *pPathID );
|
||||
|
||||
// Get all file infos with the specified filename (i.e. in all path IDs).
|
||||
int GetFileInfos( CFileInfo **ppFileInfos, int nMaxFileInfos, const char *pFilename );
|
||||
|
||||
// Clear everything.
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
void CalculateMissingCRC( const char *pFilename, const char *pPathID );
|
||||
CPathIDFileList* GetPathIDFileList( const char *pPathID, bool bAutoAdd=true );
|
||||
|
||||
CRC32_t CalculateCRCForFile( FileHandle_t fp );
|
||||
|
||||
private:
|
||||
CUtlLinkedList<CFileInfo*> m_NeedsVerificationList; // The list of files that need CRCs verified.
|
||||
CUtlDict<CPathIDFileList*,int> m_PathIDs;
|
||||
CBaseFileSystem *m_pFileSystem;
|
||||
CThreadMutex m_Mutex; // Threads call into here, so we need to be safe.
|
||||
};
|
||||
|
||||
|
||||
inline const char* CFileInfo::GetFilename()
|
||||
{
|
||||
return m_pFilename;
|
||||
}
|
||||
|
||||
inline const char* CFileInfo::GetPathIDString()
|
||||
{
|
||||
return m_pPathIDFileList->m_PathID.String();
|
||||
}
|
||||
|
||||
|
||||
#endif // FILETRACKER_H
|
85
filesystem/filesystem_stdio/ThreadSafeRefCountedObject.h
Normal file
85
filesystem/filesystem_stdio/ThreadSafeRefCountedObject.h
Normal file
@ -0,0 +1,85 @@
|
||||
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef THREADSAFEREFCOUNTEDOBJECT_H
|
||||
#define THREADSAFEREFCOUNTEDOBJECT_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
// This class can be used for fast access to an object from multiple threads,
|
||||
// and the main thread can wait until the threads are done using the object before it frees the object.
|
||||
template< class T >
|
||||
class CThreadSafeRefCountedObject
|
||||
{
|
||||
public:
|
||||
CThreadSafeRefCountedObject( T initVal )
|
||||
{
|
||||
m_RefCount = 0;
|
||||
m_pObject = initVal;
|
||||
m_RefCount = 0;
|
||||
}
|
||||
|
||||
void Init( T pObj )
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
Assert( !m_pObject );
|
||||
m_RefCount = 0;
|
||||
m_pObject = pObj;
|
||||
m_RefCount = 1;
|
||||
}
|
||||
|
||||
// Threads that access the object need to use AddRef/Release to access it.
|
||||
T AddRef()
|
||||
{
|
||||
if ( ++m_RefCount > 1 )
|
||||
{
|
||||
return m_pObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the refcount was 0 when we called this, then the whitelist is about to be freed.
|
||||
--m_RefCount;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
void ReleaseRef( T pObj )
|
||||
{
|
||||
if ( --m_RefCount >= 1 )
|
||||
{
|
||||
Assert( m_pObject == pObj );
|
||||
}
|
||||
}
|
||||
|
||||
// The main thread can use this to access the object, since only it can Init() and Free() the object.
|
||||
T GetInMainThread()
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
return m_pObject;
|
||||
}
|
||||
|
||||
// The main thread calls this after it has released its last reference to the object.
|
||||
void ResetWhenNoRemainingReferences( T newValue )
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
|
||||
// Wait until we can free it.
|
||||
while ( m_RefCount > 0 )
|
||||
{
|
||||
CThread::Sleep( 20 );
|
||||
}
|
||||
|
||||
m_pObject = newValue;
|
||||
}
|
||||
|
||||
private:
|
||||
CInterlockedIntT<long> m_RefCount;
|
||||
T m_pObject;
|
||||
};
|
||||
|
||||
|
||||
#endif // THREADSAFEREFCOUNTEDOBJECT_H
|
1502
filesystem/filesystem_steam.cpp
Normal file
1502
filesystem/filesystem_steam.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2546
filesystem/filesystemasync.cpp
Normal file
2546
filesystem/filesystemasync.cpp
Normal file
File diff suppressed because it is too large
Load Diff
596
filesystem/filesystemasync.h
Normal file
596
filesystem/filesystemasync.h
Normal file
@ -0,0 +1,596 @@
|
||||
//===== Copyright <20> 2009, Valve Corporation, All rights reserved. ======//
|
||||
// filesyste_newasync.h
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $async file system
|
||||
//===========================================================================//
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "tier0/threadtools.h"
|
||||
#include "tier0/memalloc.h"
|
||||
#include "tier1/interface.h"
|
||||
#include "tier1/utlsymbol.h"
|
||||
#include "appframework/iappsystem.h"
|
||||
#include "tier1/checksum_crc.h"
|
||||
#include "filesystem/iasyncfilesystem.h"
|
||||
|
||||
#ifndef FILESYSTEMASYNC_H
|
||||
#define FILESYSTEMASYNC_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef OSX
|
||||
#pragma GCC diagnostic ignored "-Wreturn-type" // control reaches end of non-void function, for unsupported assignment operators below
|
||||
#endif
|
||||
|
||||
class CAsyncGroupRequest;
|
||||
|
||||
|
||||
struct CAsyncResultInfo_t
|
||||
{
|
||||
public:
|
||||
void* m_pAllocatedBuffer;
|
||||
int m_nBytesTransferred;
|
||||
FSAsyncStatus_t m_ErrorCode;
|
||||
|
||||
CAsyncResultInfo_t() : m_pAllocatedBuffer(NULL), m_nBytesTransferred(0) {}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAsyncRequestBase - Common items to all async filesystem requests
|
||||
//
|
||||
// Allows the async filesystem to have a standard way to deal with different
|
||||
// types of requests equally re: priority, callbacks, state, aborting, etc
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAsyncRequestBase
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
void* m_pOuter; // pointer to object containing this base
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Members to set by the user before submission
|
||||
|
||||
CFunctor* m_pCallback; // Optional Callback object (we own this)
|
||||
CIOCompletionQueue* m_pResultQueue; // Message Queue object to send results to
|
||||
|
||||
AsyncFileOperation_t m_Operation; // operation to perform
|
||||
int32 m_priority; // inter list priority, 0=lowest??
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Used internally by the filesystem to keep track of the request
|
||||
|
||||
CAsyncRequestBase* m_pNext; // used to maintain the priority linked list
|
||||
CAsyncRequestBase* m_pPrev;
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Members which get set by the file system after submission
|
||||
|
||||
AsyncRequestState_t m_RequestState; // State of this request (which stage it is n)
|
||||
AsyncRequestStatus_t m_RequestStatus; // Error/Success Status from the last operation attempted on this request
|
||||
|
||||
bool m_bAbortRequest; // Flag indicating this request is to be aborted
|
||||
bool m_bProcessingCallback; // Flag indicating a callback is being processed
|
||||
bool m_bDontAutoRelease; // Flag indicating not to automatically release the request once the callback finishes
|
||||
// bool m_bIsAContainer
|
||||
|
||||
CThreadEvent* m_pSyncThreadEvent; // Thread event to signal in synchronous mode...
|
||||
|
||||
FSAsyncControl_t m_pOldAsyncControl; // old Async System control Handle
|
||||
FSAsyncStatus_t m_pOldAsyncStatus; // old Async System IO Status
|
||||
|
||||
CAsyncGroupRequest* m_pGroup; // group this request belongs to
|
||||
|
||||
|
||||
public:
|
||||
CAsyncRequestBase(); // Default Constructor - We want NO implicit constructions
|
||||
~CAsyncRequestBase(); // Destructor - not virtual anymore
|
||||
|
||||
void SetOuter( void* pOuter ) { m_pOuter = pOuter; }
|
||||
void* GetOuter() { return m_pOuter; }
|
||||
|
||||
IAsyncRequestBase* GetInterfaceBase();
|
||||
|
||||
// functions to query operation
|
||||
AsyncFileOperation_t GetAsyncOperationType() { return m_Operation; }
|
||||
|
||||
// Set completion options
|
||||
void AssignCallback( CFunctor* pCallback ); // Add a completion callback to this request
|
||||
void AssignResultQueue( CIOCompletionQueue* pMsgQueue ); // Send the results to this queue object
|
||||
void AssignCallbackAndQueue( CIOCompletionQueue* pMsgQueue, CFunctor* pCallback );
|
||||
|
||||
// Completion processing functions
|
||||
void ProcessCallback( bool bRelease = true ); // Execute the optional callback functor
|
||||
|
||||
void KeepRequestPostCallback() { m_bDontAutoRelease = true; } // User wants to keep request alive after the callback completes
|
||||
void DontKeepRequestPostCallback() { m_bDontAutoRelease = false; } // User doesn't want to keep request after the callback completes
|
||||
|
||||
void Release(); // lets user manually release the async request (only valid when completed)
|
||||
void DeleteOuter(); // Used by async filesystem to delete the containing object (as well as the CAsyncRequestBase)
|
||||
|
||||
// Priority Functions
|
||||
void SetPriority( int32 nPriority );
|
||||
int32 GetPriority() { return m_priority; }
|
||||
|
||||
// Status & Results functions
|
||||
AsyncRequestState_t GetRequestState() { return m_RequestState; }
|
||||
AsyncRequestStatus_t GetRequestStatus() { return m_RequestStatus; }
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Gateway to outer's Public Methods not included in the interface, used by Async FileSystem
|
||||
|
||||
void AbortAfterServicing( CAsyncResultInfo_t& results ); // Handle a request that got aborted while being serviced
|
||||
void UpdateAfterServicing( CAsyncResultInfo_t& results ); // Handle a request that got aborted while being serviced
|
||||
AsyncRequestStatus_t ValidateSubmittedRequest( bool bPerformSync ); // Validates the derived object data at request submission
|
||||
bool ValidateRequestModification(); // core check to determine if modification is allowed at this time
|
||||
|
||||
protected:
|
||||
// Helper functions for repeated operations
|
||||
void RefreshCallback( CFunctor* pCallback );
|
||||
|
||||
private:
|
||||
|
||||
explicit CAsyncRequestBase( const CAsyncRequestBase& rhs ); // copy constructor - NOT SUPPORTED
|
||||
CAsyncRequestBase& operator=( const CAsyncRequestBase& rhs ); // assignment operator - NOT SUPPORTED
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAsyncGroupRequest - Concrete implementation for a group of async requests
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAsyncGroupRequest : public IAsyncGroupRequest
|
||||
{
|
||||
public:
|
||||
|
||||
CAsyncRequestBase m_Base; // Base request - we can't derive from due to multiple inheritance problems
|
||||
|
||||
CUtlVector<IAsyncRequestBase*> m_RequestList; // List of requests to process
|
||||
CUtlVector<bool> m_ValidList; // List of requests which are valid
|
||||
|
||||
CInterlockedInt m_nNumRequestsOutstanding;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
CAsyncGroupRequest(); // Default Constructor - We want NO implicit constructions
|
||||
virtual ~CAsyncGroupRequest(); // Destructor
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// methods from the IAsyncRequestBase Interface
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// functions to query operation
|
||||
virtual AsyncFileOperation_t GetAsyncOperationType() { return m_Base.GetAsyncOperationType(); }
|
||||
|
||||
// Set completion options
|
||||
virtual void AssignCallback( CFunctor* pCallback ) { m_Base.AssignCallback( pCallback ); }
|
||||
virtual void AssignResultQueue( CIOCompletionQueue* pMsgQueue ) { m_Base.AssignResultQueue( pMsgQueue ); }
|
||||
virtual void AssignCallbackAndQueue( CIOCompletionQueue* pMsgQueue, CFunctor* pCallback ) { m_Base.AssignCallbackAndQueue( pMsgQueue, pCallback); }
|
||||
|
||||
// Completion processing functions
|
||||
virtual void ProcessCallback( bool bRelease = true ) { m_Base.ProcessCallback( bRelease ); }
|
||||
|
||||
virtual void KeepRequestPostCallback() { m_Base.KeepRequestPostCallback(); }
|
||||
virtual void DontKeepRequestPostCallback() { m_Base.DontKeepRequestPostCallback(); }
|
||||
|
||||
virtual void Release() { m_Base.Release(); }
|
||||
|
||||
// Priority Functions
|
||||
virtual void SetPriority( int32 nPriority ) { m_Base.SetPriority( nPriority ); }
|
||||
virtual int32 GetPriority() { return m_Base.GetPriority(); }
|
||||
|
||||
// Status & Results functions
|
||||
virtual AsyncRequestState_t GetRequestState() { return m_Base.GetRequestState(); }
|
||||
virtual AsyncRequestStatus_t GetRequestStatus() { return m_Base.GetRequestStatus(); }
|
||||
|
||||
private:
|
||||
virtual CAsyncRequestBase* GetBase() { return (CAsyncRequestBase*) &m_Base; }
|
||||
|
||||
// ----------------------------------------------------
|
||||
// methods from the IAsyncGroupRequest Interface
|
||||
// ----------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
virtual void AddAsyncRequest( IAsyncRequestBase* pRequest );
|
||||
|
||||
virtual int32 GetAsyncRequestCount() { return m_RequestList.Count(); }
|
||||
virtual IAsyncRequestBase* GetAsyncRequest( int32 nRNum );
|
||||
virtual IAsyncFileRequest* GetAsyncFileRequest( int32 nRNum );
|
||||
virtual IAsyncSearchRequest* GetAsyncSearchRequest( int32 nRNum );
|
||||
|
||||
virtual void ReleaseAsyncRequest( int32 nRNum );
|
||||
|
||||
void NotifyOfCompletion( IAsyncRequestBase* pRequest );
|
||||
|
||||
private:
|
||||
|
||||
explicit CAsyncGroupRequest( const CAsyncRequestBase& rhs ); // copy constructor - NOT SUPPORTED
|
||||
CAsyncRequestBase& operator=( const CAsyncGroupRequest& rhs ); // assignment operator - NOT SUPPORTED
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAsyncFileRequest - Concrete implementation for the IAsyncFileRequest interface
|
||||
//
|
||||
// Manages a read or write to file request
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAsyncFileRequest : public IAsyncFileRequest
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
CAsyncRequestBase m_Base; // Base request - we can't derive from due to multiple inheritance problems
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Members to set by the user before submission
|
||||
|
||||
const char* m_pFileName; // file system name (copy of string that we own)
|
||||
|
||||
void* m_pUserProvidedDataBuffer; // optional (if read op), system will alloc one if NULL/free if NULL
|
||||
size_t m_nUserProvidedBufferSize; // size of the memory buffer
|
||||
|
||||
int64 m_nFileSeekOffset; // (optional) position in the file to seek to/begin xfer at, 0=beginning
|
||||
int64 m_nMaxIOSizeInBytes; // optional read clamp, 0=full read
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Members which get set by the file system after submission
|
||||
|
||||
void* m_pResultsBuffer; // Buffer results were placed in, could be from user (or not)
|
||||
size_t m_nResultsBufferSize; // size of results buffer
|
||||
size_t m_nIOActualSize; // actual size of IO performed
|
||||
|
||||
bool m_bDeleteBufferMemory; // Flag indicating the memory holding the file data is deleted when the request is released
|
||||
|
||||
public:
|
||||
|
||||
CAsyncFileRequest(); // Default Constructor - We want NO implicit constructions
|
||||
virtual ~CAsyncFileRequest(); // Destructor
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// methods from the IAsyncRequestBase Interface
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// functions to query operation
|
||||
virtual AsyncFileOperation_t GetAsyncOperationType() { return m_Base.GetAsyncOperationType(); }
|
||||
|
||||
// Set completion options
|
||||
virtual void AssignCallback( CFunctor* pCallback ) { m_Base.AssignCallback( pCallback ); }
|
||||
virtual void AssignResultQueue( CIOCompletionQueue* pMsgQueue ) { m_Base.AssignResultQueue( pMsgQueue ); }
|
||||
virtual void AssignCallbackAndQueue( CIOCompletionQueue* pMsgQueue, CFunctor* pCallback ) { m_Base.AssignCallbackAndQueue( pMsgQueue, pCallback); }
|
||||
|
||||
// Completion processing functions
|
||||
virtual void ProcessCallback( bool bRelease = true ) { m_Base.ProcessCallback( bRelease ); }
|
||||
|
||||
virtual void KeepRequestPostCallback() { m_Base.KeepRequestPostCallback(); }
|
||||
virtual void DontKeepRequestPostCallback() { m_Base.DontKeepRequestPostCallback(); }
|
||||
|
||||
virtual void Release() { m_Base.Release(); }
|
||||
|
||||
// Priority Functions
|
||||
virtual void SetPriority( int32 nPriority ) { m_Base.SetPriority( nPriority ); }
|
||||
virtual int32 GetPriority() { return m_Base.GetPriority(); }
|
||||
|
||||
// Status & Results functions
|
||||
virtual AsyncRequestState_t GetRequestState() { return m_Base.GetRequestState(); }
|
||||
virtual AsyncRequestStatus_t GetRequestStatus() { return m_Base.GetRequestStatus(); }
|
||||
|
||||
private:
|
||||
virtual CAsyncRequestBase* GetBase() { return (CAsyncRequestBase*) &m_Base; }
|
||||
|
||||
// ----------------------------------------------------
|
||||
// methods from the IAsyncFileRequest Interface
|
||||
// ----------------------------------------------------
|
||||
|
||||
public:
|
||||
// functions to set filename and operation
|
||||
virtual void LoadFile( const char* pFileName ); // make this a 'read data from file' request
|
||||
virtual void SaveFile( const char* pFileName ); // make this a 'write data to file' request
|
||||
virtual void AppendFile( const char* pFileName ); // make this a 'append data to file' request
|
||||
|
||||
virtual void SetFileName( const char* pFileName ); // assign the filename to use
|
||||
virtual const char* GetFileName() { return m_pFileName; } // get the filename we've assigned
|
||||
|
||||
// Buffer control functions
|
||||
virtual void SetUserBuffer( void* pDataBuffer, size_t nBufferSize ); // User supplies a memory buffer to use, which they own the memory for
|
||||
virtual void* GetUserBuffer() { return m_pUserProvidedDataBuffer; } // returns the address of the user supplied buffer
|
||||
virtual size_t GetUserBufferSize() { return m_nUserProvidedBufferSize; } // returns the size of the user supplied buffer
|
||||
|
||||
virtual void ProvideDataBuffer(); // file system provide a buffer with the results
|
||||
|
||||
// returned buffer (read) functions
|
||||
virtual void* GetResultBuffer() { return m_pResultsBuffer; } // Returns the address of the data transferred
|
||||
virtual size_t GetResultBufferSize() { return m_nResultsBufferSize; } // Returns the size of the buffer holding the data transferred
|
||||
virtual size_t GetIOTransferredSize() { return m_nIOActualSize; } // Returns the number of bytes of data actually transferred
|
||||
|
||||
// Memory control functions for buffers allocated by the async file system
|
||||
virtual void KeepResultBuffer() { m_bDeleteBufferMemory = false; } // User wants to keeps buffer allocated by the file system
|
||||
virtual void ReleaseResultBuffer() { m_bDeleteBufferMemory = true; } // User decides they want the request to take care of releasing the buffer
|
||||
|
||||
// file position functions
|
||||
virtual void ReadFileDataAt( int64 nOffset, size_t nReadSize = 0 ); // Read file data starting at supplied offset, optional max size to read
|
||||
virtual void WriteFileDataAt( int64 nOffset, size_t nWriteSize = 0 ); // Write data to file at supplied offset, optional size to write (max size of buffer)
|
||||
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Public Methods not included in the interface, used by Async FileSystem
|
||||
|
||||
void AbortAfterServicing( CAsyncResultInfo_t& results ); // Handle a request that got aborted while being serviced
|
||||
void UpdateAfterServicing( CAsyncResultInfo_t& results ); // Handle a request that got aborted while being serviced
|
||||
AsyncRequestStatus_t ValidateSubmittedRequest( bool bPerformSync ); // Validates the derived object data at request submission
|
||||
bool ValidateRequestModification(); // Check to determine if modification is allowed at this time
|
||||
|
||||
protected:
|
||||
// Helper functions for repeated operations
|
||||
void RefreshFileName( const char* pNewFileName );
|
||||
|
||||
private:
|
||||
// disabled functions
|
||||
explicit CAsyncFileRequest( const CAsyncFileRequest& rhs ); // copy constructor - NOT SUPPORTED
|
||||
CAsyncFileRequest& operator=( const CAsyncFileRequest& rhs ); // assignment operator - NOT SUPPORTED
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAsyncSearchRequest - Implementation of the Interface for setting and reading
|
||||
// the results of an asynchronous directory search request
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAsyncSearchRequest : public IAsyncSearchRequest
|
||||
{
|
||||
|
||||
public:
|
||||
CAsyncRequestBase m_Base; // Base request - we can't derive from due to multiple inheritance problems
|
||||
|
||||
// CUtlStringList m_DirectoryList; // List of directories we have scanned
|
||||
|
||||
int32 m_nNumResults; // number of results
|
||||
bool m_bRecurseSubdirs; // flag to activate recursing of subdirectories
|
||||
|
||||
CUtlVector<CDirectoryEntryInfo_t> m_Results; // Search results...
|
||||
|
||||
char m_FileSpec[MAX_PATH]; // filespec of the files we are looking for
|
||||
char m_PathID[MAX_PATH];
|
||||
char m_SearchPath[MAX_PATH];
|
||||
|
||||
char m_SearchSpec[MAX_PATH];
|
||||
|
||||
public:
|
||||
|
||||
CAsyncSearchRequest(); // Default Constructor - We want NO implicit constructions
|
||||
virtual ~CAsyncSearchRequest(); // Destructor
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// methods from the IAsyncRequestBase Interface
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// functions to query operation
|
||||
virtual AsyncFileOperation_t GetAsyncOperationType() { return m_Base.GetAsyncOperationType(); }
|
||||
|
||||
// Set completion options
|
||||
virtual void AssignCallback( CFunctor* pCallback ) { m_Base.AssignCallback( pCallback ); }
|
||||
virtual void AssignResultQueue( CIOCompletionQueue* pMsgQueue ) { m_Base.AssignResultQueue( pMsgQueue ); }
|
||||
virtual void AssignCallbackAndQueue( CIOCompletionQueue* pMsgQueue, CFunctor* pCallback ) { m_Base.AssignCallbackAndQueue( pMsgQueue, pCallback); }
|
||||
|
||||
// Completion processing functions
|
||||
virtual void ProcessCallback( bool bRelease = true ) { m_Base.ProcessCallback( bRelease ); }
|
||||
|
||||
virtual void KeepRequestPostCallback() { m_Base.KeepRequestPostCallback(); }
|
||||
virtual void DontKeepRequestPostCallback() { m_Base.DontKeepRequestPostCallback(); }
|
||||
|
||||
virtual void Release() { m_Base.Release(); }
|
||||
|
||||
// Priority Functions
|
||||
virtual void SetPriority( int32 nPriority ) { m_Base.SetPriority( nPriority ); }
|
||||
virtual int32 GetPriority() { return m_Base.GetPriority(); }
|
||||
|
||||
// Status & Results functions
|
||||
virtual AsyncRequestState_t GetRequestState() { return m_Base.GetRequestState(); }
|
||||
virtual AsyncRequestStatus_t GetRequestStatus() { return m_Base.GetRequestStatus(); }
|
||||
|
||||
private:
|
||||
virtual CAsyncRequestBase* GetBase() { return (CAsyncRequestBase*) &m_Base; }
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// methods from the IAsyncSearchRequest Interface
|
||||
// ---------------------------------------------------------
|
||||
|
||||
public:
|
||||
// functions to define the request
|
||||
|
||||
virtual void SetSearchFilespec( const char* pFullSearchSpec );
|
||||
virtual void SetSearchPathAndFileSpec( const char* pPathId, const char* pRelativeSearchSpec );
|
||||
virtual void SetSearchPathAndFileSpec( const char* pPathId, const char* pRelativeSearchPath, const char* pSearchSpec );
|
||||
|
||||
virtual void SetSubdirectoryScan( const bool bInclude );
|
||||
virtual bool GetSubdirectoryScan() { return m_bRecurseSubdirs; }
|
||||
|
||||
// Functions to return the results.
|
||||
|
||||
virtual int GetResultCount() { return m_nNumResults; }
|
||||
virtual CDirectoryEntryInfo_t* GetResult( int rNum = 0 );
|
||||
virtual const char* GetMatchedFile( int rNum = 0 );
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Public Methods not included in the interface, used by Async FileSystem
|
||||
|
||||
void AbortAfterServicing( CAsyncResultInfo_t& results ); // Handle a request that got aborted while being serviced
|
||||
void UpdateAfterServicing( CAsyncResultInfo_t& results ); // Handle a request that got aborted while being serviced
|
||||
AsyncRequestStatus_t ValidateSubmittedRequest( bool bPerformSync ); // Validates the derived object data at request submission
|
||||
bool ValidateRequestModification(); // Check to determine if modification is allowed at this time
|
||||
|
||||
private:
|
||||
// disabled functions
|
||||
explicit CAsyncSearchRequest( const CAsyncSearchRequest& rhs ); // copy constructor - NOT SUPPORTED
|
||||
CAsyncSearchRequest& operator=( const CAsyncSearchRequest& rhs ); // assignment operator - NOT SUPPORTED
|
||||
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAsyncRequestQueue
|
||||
// Helper object for filesystem - Linked list of objects
|
||||
// dreeived from CAsyncRequestBase
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAsyncRequestQueue
|
||||
{
|
||||
private:
|
||||
CThreadFastMutex m_Mutex;
|
||||
int32 m_nQueueSize;
|
||||
CAsyncRequestBase* m_pHead;
|
||||
CAsyncRequestBase* m_pTail;
|
||||
|
||||
public:
|
||||
CAsyncRequestQueue();
|
||||
~CAsyncRequestQueue();
|
||||
|
||||
int32 GetSize() { return m_nQueueSize; }
|
||||
bool IsInQueue( CAsyncRequestBase* pItem );
|
||||
bool IsInQueueIp( const IAsyncRequestBase* pInterfaceBase );
|
||||
|
||||
void AddToHead( CAsyncRequestBase* pItem );
|
||||
void AddToTail( CAsyncRequestBase* pItem );
|
||||
void InsertBefore( CAsyncRequestBase* pItem, CAsyncRequestBase* pInsertAt );
|
||||
void InsertAfter( CAsyncRequestBase* pItem, CAsyncRequestBase* pInsertAt );
|
||||
|
||||
void PriorityInsert( CAsyncRequestBase* pItem );
|
||||
|
||||
void Remove( CAsyncRequestBase* pItem );
|
||||
CAsyncRequestBase* RemoveHead();
|
||||
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAsyncFileSystem - implements IAsyncFileSystem interface
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAsyncFileSystem : public CTier2AppSystem< IAsyncFileSystem >
|
||||
{
|
||||
typedef CTier2AppSystem< IAsyncFileSystem > BaseClass;
|
||||
|
||||
friend class CAsyncGroupRequest;
|
||||
|
||||
public:
|
||||
|
||||
static const int s_MaxPlatformFileNameLength = 40;
|
||||
|
||||
public:
|
||||
CAsyncFileSystem();
|
||||
~CAsyncFileSystem();
|
||||
|
||||
//--------------------------------------------------
|
||||
// Interface methods exposed with IAsyncFileSystem
|
||||
//--------------------------------------------------
|
||||
|
||||
virtual AsyncRequestStatus_t SubmitAsyncFileRequest( const IAsyncRequestBase* pRequest );
|
||||
virtual AsyncRequestStatus_t SubmitSyncFileRequest( const IAsyncRequestBase* pRequest );
|
||||
|
||||
virtual AsyncRequestStatus_t GetAsyncFileRequestStatus( const IAsyncRequestBase* pRequest );
|
||||
virtual AsyncRequestStatus_t AbortAsyncFileRequest( const IAsyncRequestBase* pRequest );
|
||||
|
||||
virtual void SuspendAllAsyncIO( bool bWaitForIOCompletion = true );
|
||||
virtual void ResumeAllAsyncIO();
|
||||
virtual AsyncRequestStatus_t AbortAllAsyncIO( bool bWaitForIOCompletion = true );
|
||||
|
||||
virtual IAsyncFileRequest* CreateNewFileRequest();
|
||||
virtual IAsyncSearchRequest* CreateNewSearchRequest();
|
||||
virtual IAsyncGroupRequest* CreateNewAsyncRequestGroup();
|
||||
|
||||
virtual void ReleaseAsyncRequest( const IAsyncRequestBase* pRequest );
|
||||
virtual bool BlockUntilAsyncIOComplete( const IAsyncRequestBase* pRequest );
|
||||
|
||||
virtual void* AllocateBuffer( size_t nBufferSize, int nAlignment = 4 );
|
||||
virtual void ReleaseBuffer( void* pBuffer );
|
||||
|
||||
//--------------------------------------------------
|
||||
// Public Methods used inside the filesystem
|
||||
//--------------------------------------------------
|
||||
|
||||
|
||||
void* QueryInterface( const char *pInterfaceName );
|
||||
|
||||
void RemoveRequest( CAsyncRequestBase* pRequest );
|
||||
|
||||
bool ResolveAsyncRequest( const IAsyncRequestBase* pRequest, CAsyncRequestBase*& pRequestBase, AsyncRequestState_t& CurrentStage );
|
||||
|
||||
bool ValidateRequestPtr( CAsyncRequestBase* pRequest );
|
||||
|
||||
private:
|
||||
CAsyncRequestQueue m_Composing; // requests in state: Composing
|
||||
CAsyncRequestQueue m_Submitted; // requests in state: Submitted
|
||||
CAsyncRequestQueue m_InFlight; // requests in state: Serviced
|
||||
CAsyncRequestQueue m_Completed; // requests in state: Awaiting Finished, Completed*
|
||||
|
||||
|
||||
CInterlockedInt m_nJobsInflight; // number of requests currently being serviced by the old system
|
||||
CInterlockedInt m_nSuspendCount; // number of requests to suspend all Async IO outstanding (nested request support)
|
||||
bool m_bIOSuspended;
|
||||
|
||||
#if defined(_DEBUG)
|
||||
CThreadFastMutex m_MemoryTrackMutex;
|
||||
CUtlVector<void*> m_AllocList; // Debug build - track allocations
|
||||
#endif
|
||||
|
||||
CThreadFastMutex m_AsyncStateUpdateMutex;
|
||||
CThreadEvent m_CompletionSignal; // Used to signal the completion of an IO
|
||||
|
||||
AsyncRequestStatus_t ValidateRequest( CAsyncRequestBase* pRequest, bool bPerformSync = false );
|
||||
|
||||
void KickOffFileJobs();
|
||||
void WaitForServincingIOCompletion(); // Pauses until all jobs being serviced are complete
|
||||
|
||||
static void* OldAsyncAllocatorCallback( const char *pszFilename, unsigned nBytes );
|
||||
|
||||
static void AsyncIOCallbackGateway(const FileAsyncRequest_t &request, int nBytesRead, FSAsyncStatus_t err);
|
||||
static void AsyncSearchCallbackAddItem( void* pContext, char* pFoundPath, char* pFoundFile );
|
||||
static void AsyncSearchCallbackGateway( void* pContext, FSAsyncStatus_t err );
|
||||
|
||||
void AsyncIOCallBackHandler(CAsyncRequestBase* pRequest, CAsyncResultInfo_t& results );
|
||||
|
||||
void NotifyMessageQueueOrCallback( CAsyncRequestBase* pRequest );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utility functions
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
AsyncRequestStatus_t ValidateFileName( const char* pFileName );
|
||||
|
||||
|
||||
|
||||
#endif
|
1263
filesystem/filetracker.cpp
Normal file
1263
filesystem/filetracker.cpp
Normal file
File diff suppressed because it is too large
Load Diff
390
filesystem/filetracker.h
Normal file
390
filesystem/filetracker.h
Normal file
@ -0,0 +1,390 @@
|
||||
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef FILETRACKER_H
|
||||
#define FILETRACKER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "ifilelist.h"
|
||||
#include "tier1/utldict.h"
|
||||
|
||||
|
||||
class CBaseFileSystem;
|
||||
class CFileHandle;
|
||||
|
||||
|
||||
enum EFileFlags
|
||||
{
|
||||
k_eFileFlags_None = 0x0000,
|
||||
|
||||
k_eFileFlagsLoadedFromSteam = 0x0001,
|
||||
|
||||
k_eFileFlagsHasCRC = 0x0002, // m_CRC represents the most recently-loaded version of the file. This might be
|
||||
// unset but m_CRC (and k_eFileFlagsGotCRCOnce) could be set, signifying that
|
||||
// the file has been opened since last time we calculated the CRC but we didn't
|
||||
// calculate a CRC for that file version.
|
||||
|
||||
k_eFileFlagsForcedLoadFromSteam = 0x0004, // Set if k_eFileFlagsLoadedFromSteam is set AND we forced Steam to not check the disk for this file.
|
||||
|
||||
k_eFileFlagsGotCRCOnce = 0x0008, // This is set if we EVER had k_eFileFlagsHasCRC set.. m_CRC will still be set in that case,
|
||||
// but it'll be the last CRC we calculated and not necessarily
|
||||
|
||||
k_eFileFlagsFailedToLoadLastTime = 0x0010 // This is used if we had a record of the file and the game tried to open it, but
|
||||
// it couldn't be opened. This will happen if the file was loaded from disk, then
|
||||
// sv_pure is turned on and the file is forced to come from Steam, but there is no
|
||||
// Steam version. In that case, the game should be told to retry the file
|
||||
// next time sv_pure is changed because if sv_pure goes back to 0 it -would- load
|
||||
// the file legitimately.
|
||||
};
|
||||
|
||||
|
||||
class CPathIDFileList;
|
||||
|
||||
|
||||
class CFileInfo
|
||||
{
|
||||
public:
|
||||
CFileInfo();
|
||||
~CFileInfo();
|
||||
|
||||
const char* GetFilename();
|
||||
const char* GetPathIDString();
|
||||
|
||||
public:
|
||||
|
||||
unsigned short m_Flags; // This is a combination of EFileFlags.
|
||||
CRC32_t m_CRC; // The CRC for this file.
|
||||
|
||||
CPathIDFileList *m_pPathIDFileList;
|
||||
int m_PathIDFileListDictIndex; // Our index into m_pPathIDFileList->m_Files
|
||||
|
||||
int m_iNeedsVerificationListIndex; // Index into m_NeedsVerificationList or -1 if not in the list.
|
||||
};
|
||||
|
||||
|
||||
// This tracks a list of files for the specified path ID.
|
||||
class CPathIDFileList
|
||||
{
|
||||
public:
|
||||
CPathIDFileList();
|
||||
~CPathIDFileList();
|
||||
CFileInfo* FindFileInfo( const char *pFilename );
|
||||
CFileInfo* AddFileInfo( const char *pFilename );
|
||||
|
||||
public:
|
||||
CUtlSymbol m_PathID; // "" for a null path ID.
|
||||
CUtlDict<CFileInfo*,int> m_Files;
|
||||
CUtlLinkedList<CFileInfo*,int> m_UnverifiedCRCFiles; // These are the files whose CRCs have not been verified yet.
|
||||
// These just point at entries in m_Files.
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This tracks the files that have been opened by the filesystem.
|
||||
// It remembers if they were loaded from Steam or off-disk.
|
||||
// If the filesystem is tracking CRCs, then it will calculate a CRC
|
||||
// for each file that came off disk.
|
||||
//
|
||||
// TODO: This is similar to CBaseFileSystem::m_OpenedFiles - it could probably
|
||||
// manage both sets of files in the same list. Having 2 separate lists might
|
||||
// be confusing.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CFileTracker
|
||||
{
|
||||
public:
|
||||
CFileTracker( CBaseFileSystem *pFileSystem );
|
||||
~CFileTracker();
|
||||
|
||||
// If this is true, then we'll calculate CRCs for each file that came off disk.
|
||||
void SetWantFileCRCs( bool bWantCRCs );
|
||||
|
||||
// As files are opened, if it is calculating CRCs, it will add those files and their
|
||||
// CRCs to the "unverified CRC" list. The client can then ask the server to verify
|
||||
// those CRCs to make sure the client is "pure".
|
||||
void MarkAllCRCsUnverified();
|
||||
void MarkAllCRCsVerified( bool bLockMutex=true );
|
||||
|
||||
// Cache a file's CRC. Loads the file and calculates the CRC if we don't have it yet.
|
||||
void CacheFileCRC( const char *pPathID, const char *pRelativeFilename );
|
||||
EFileCRCStatus CheckCachedFileCRC( const char *pPathID, const char *pRelativeFilename, CRC32_t *pCRC );
|
||||
|
||||
// This is like CacheFileCRC, but it assumes that the same file would be found by pPathIDToCopyFrom, so it just
|
||||
// copies the CRC record from that path ID into the one in pPathID and avoids a redundant CRC calculation.
|
||||
void CacheFileCRC_Copy( const char *pPathID, const char *pRelativeFilename, const char *pPathIDToCopyFrom );
|
||||
|
||||
// When we don't have a whitelist, it loads files without bothering to calculate their CRCs (we'd only
|
||||
// need them on a pure server), but when we get a whitelist, we'll want the CRCs, so it goes back, opens those
|
||||
// files, and calculates the CRCs for them.
|
||||
void CalculateMissingCRCs( IFileList *pForceMatchList );
|
||||
|
||||
int GetUnverifiedCRCFiles( CUnverifiedCRCFile *pFiles, int nMaxFiles );
|
||||
|
||||
// Note that we just opened this file and calculate a CRC for it.
|
||||
void NoteFileLoadedFromDisk( const char *pFilename, const char *pPathID, FileHandle_t fp );
|
||||
void NoteFileLoadedFromSteam( const char *pFilename, const char *pPathID, bool bForcedLoadFromSteam );
|
||||
void NoteFileFailedToLoad( const char *pFilename, const char *pPathID );
|
||||
|
||||
// Get a file info from a specific path ID.
|
||||
CFileInfo* GetFileInfo( const char *pFilename, const char *pPathID );
|
||||
|
||||
// Get all file infos with the specified filename (i.e. in all path IDs).
|
||||
int GetFileInfos( CFileInfo **ppFileInfos, int nMaxFileInfos, const char *pFilename );
|
||||
|
||||
// Clear everything.
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
void CalculateMissingCRC( const char *pFilename, const char *pPathID );
|
||||
CPathIDFileList* GetPathIDFileList( const char *pPathID, bool bAutoAdd=true );
|
||||
|
||||
CRC32_t CalculateCRCForFile( FileHandle_t fp );
|
||||
|
||||
private:
|
||||
CUtlLinkedList<CFileInfo*> m_NeedsVerificationList; // The list of files that need CRCs verified.
|
||||
CUtlDict<CPathIDFileList*,int> m_PathIDs;
|
||||
CBaseFileSystem *m_pFileSystem;
|
||||
CThreadMutex m_Mutex; // Threads call into here, so we need to be safe.
|
||||
};
|
||||
|
||||
|
||||
inline const char* CFileInfo::GetFilename()
|
||||
{
|
||||
return m_pPathIDFileList->m_Files.GetElementName( m_PathIDFileListDictIndex );
|
||||
}
|
||||
|
||||
inline const char* CFileInfo::GetPathIDString()
|
||||
{
|
||||
return m_pPathIDFileList->m_PathID.String();
|
||||
}
|
||||
|
||||
|
||||
struct TrackedFile_t
|
||||
{
|
||||
TrackedFile_t()
|
||||
{
|
||||
m_nFileFraction = 0;
|
||||
m_nFilePos = 0;
|
||||
m_nLength = 0;
|
||||
m_cubSequentialRead = 0;
|
||||
m_PackFileID = 0;
|
||||
m_nPackFileNumber = 0;
|
||||
m_bPackOrVPKFile = false;
|
||||
m_bFileInVPK = false;
|
||||
m_cubTotalRead = 0;
|
||||
}
|
||||
CRC32_t m_crcIdentifier;
|
||||
CUtlString m_filename;
|
||||
CUtlString m_path;
|
||||
int m_nFileFraction;
|
||||
|
||||
MD5Context_t m_md5ctx;
|
||||
FileHash_t m_filehashFinal;
|
||||
FileHash_t m_filehashInProgress;
|
||||
int m_cubTotalRead;
|
||||
|
||||
int64 m_nFilePos;
|
||||
int64 m_nLength;
|
||||
int64 m_cubSequentialRead;
|
||||
int m_idxRecentFileList;
|
||||
int m_PackFileID;
|
||||
int m_nPackFileNumber;
|
||||
bool m_bPackOrVPKFile;
|
||||
bool m_bFileInVPK;
|
||||
|
||||
void RebuildFileName( const char *pFilename, const char *pPathID )
|
||||
{
|
||||
m_filename = pFilename;
|
||||
m_path = pPathID;
|
||||
|
||||
CRC32_t crcFilename;
|
||||
CRC32_Init( &crcFilename );
|
||||
CRC32_ProcessBuffer( &crcFilename, pFilename, Q_strlen( pFilename ) );
|
||||
if ( pPathID )
|
||||
CRC32_ProcessBuffer( &crcFilename, pPathID, Q_strlen( pPathID ) );
|
||||
CRC32_Final( &crcFilename );
|
||||
m_crcIdentifier = crcFilename;
|
||||
}
|
||||
static bool Less( const TrackedFile_t& lhs, const TrackedFile_t& rhs )
|
||||
{
|
||||
if ( lhs.m_crcIdentifier < rhs.m_crcIdentifier )
|
||||
return true;
|
||||
if ( lhs.m_crcIdentifier > rhs.m_crcIdentifier )
|
||||
return false;
|
||||
if ( lhs.m_nFileFraction < rhs.m_nFileFraction )
|
||||
return true;
|
||||
if ( lhs.m_nFileFraction > rhs.m_nFileFraction )
|
||||
return false;
|
||||
int nCmp = Q_strcmp( lhs.m_filename.String(), rhs.m_filename.String() );
|
||||
if ( nCmp < 0 )
|
||||
return true;
|
||||
if ( nCmp > 0 )
|
||||
return false;
|
||||
nCmp = Q_strcmp( lhs.m_path.String(), rhs.m_path.String() );
|
||||
if ( nCmp < 0 )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool GetCRCValues( FileHash_t *pFileHash );
|
||||
|
||||
void ProcessFileRead( void *dest, size_t nBytesRead );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct FileInVPK_t
|
||||
{
|
||||
FileInVPK_t()
|
||||
{
|
||||
m_PackFileID = 0;
|
||||
m_nPackFileNumber = 0;
|
||||
m_nFileOffset = 0;
|
||||
}
|
||||
int m_PackFileID;
|
||||
int m_nPackFileNumber;
|
||||
int m_nFileOffset;
|
||||
int m_idxAllOpenedFiles;
|
||||
|
||||
static bool Less( const FileInVPK_t& lhs, const FileInVPK_t& rhs )
|
||||
{
|
||||
if ( lhs.m_nFileOffset < rhs.m_nFileOffset )
|
||||
return true;
|
||||
if ( lhs.m_nFileOffset > rhs.m_nFileOffset )
|
||||
return false;
|
||||
if ( lhs.m_nPackFileNumber < rhs.m_nPackFileNumber )
|
||||
return true;
|
||||
if ( lhs.m_nPackFileNumber > rhs.m_nPackFileNumber )
|
||||
return false;
|
||||
if ( lhs.m_PackFileID < rhs.m_PackFileID )
|
||||
return true;
|
||||
if ( lhs.m_PackFileID > rhs.m_PackFileID )
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct TrackedVPKFile_t
|
||||
{
|
||||
TrackedVPKFile_t()
|
||||
{
|
||||
m_PackFileID = 0;
|
||||
m_nPackFileNumber = 0;
|
||||
}
|
||||
int m_PackFileID;
|
||||
int m_nPackFileNumber;
|
||||
int m_nFileFraction;
|
||||
int m_idxAllOpenedFiles;
|
||||
|
||||
static bool Less( const TrackedVPKFile_t& lhs, const TrackedVPKFile_t& rhs )
|
||||
{
|
||||
if ( lhs.m_nPackFileNumber < rhs.m_nPackFileNumber )
|
||||
return true;
|
||||
if ( lhs.m_nPackFileNumber > rhs.m_nPackFileNumber )
|
||||
return false;
|
||||
if ( lhs.m_nFileFraction < rhs.m_nFileFraction )
|
||||
return true;
|
||||
if ( lhs.m_nFileFraction > rhs.m_nFileFraction )
|
||||
return false;
|
||||
if ( lhs.m_PackFileID < rhs.m_PackFileID )
|
||||
return true;
|
||||
if ( lhs.m_PackFileID > rhs.m_PackFileID )
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class StuffToMD5_t
|
||||
{
|
||||
public:
|
||||
uint8 *m_pubBuffer;
|
||||
int m_cubBuffer;
|
||||
MD5Value_t m_md5Value;
|
||||
int m_PackFileID;
|
||||
int m_nPackFileNumber;
|
||||
int m_nPackFileFraction;
|
||||
int m_idxListSubmittedJobs;
|
||||
};
|
||||
|
||||
class SubmittedMd5Job_t
|
||||
{
|
||||
public:
|
||||
bool m_bFinished;
|
||||
MD5Value_t m_md5Value;
|
||||
};
|
||||
|
||||
class CFileTracker2
|
||||
#ifdef SUPPORT_VPK
|
||||
: IThreadedFileMD5Processor
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
CFileTracker2( CBaseFileSystem *pFileSystem );
|
||||
~CFileTracker2();
|
||||
void InitAsyncThread();
|
||||
void ShutdownAsync();
|
||||
|
||||
void MarkAllCRCsUnverified();
|
||||
int GetUnverifiedFileHashes( CUnverifiedFileHash *pFiles, int nMaxFiles );
|
||||
EFileCRCStatus CheckCachedFileHash( const char *pPathID, const char *pRelativeFilename, int nFileFraction, FileHash_t *pFileHash );
|
||||
|
||||
#ifdef SUPPORT_VPK
|
||||
unsigned ThreadedProcessMD5Requests();
|
||||
virtual int SubmitThreadedMD5Request( uint8 *pubBuffer, int cubBuffer, int PackFileID, int nPackFileNumber, int nPackFileFraction );
|
||||
virtual bool BlockUntilMD5RequestComplete( int iRequest, MD5Value_t *pMd5ValueOut );
|
||||
virtual bool IsMD5RequestComplete( int iRequest, MD5Value_t *pMd5ValueOut );
|
||||
|
||||
int NotePackFileOpened( const char *pRawFileName, const char *pFilename, const char *pPathID, int64 nLength );
|
||||
void NotePackFileAccess( const char *pFilename, const char *pPathID, CPackedStoreFileHandle &VPKHandle );
|
||||
void NotePackFileRead( CPackedStoreFileHandle &VPKHandle, void *pBuffer, int nReadLength );
|
||||
void AddFileHashForVPKFile( int nPackFileNumber, int nFileFraction, int cbFileLen, MD5Value_t &md5, CPackedStoreFileHandle &fhandle );
|
||||
#endif
|
||||
|
||||
void NoteFileLoadedFromDisk( const char *pFilename, const char *pPathID, FILE *fp, int64 nLength );
|
||||
void RecordFileSeek( FILE *fp, int64 pos, int seekType );
|
||||
void RecordFileClose( FILE *fp );
|
||||
void RecordFileRead( void *dest, size_t nBytesRead, size_t nBytesRequested, FILE *fp );
|
||||
int ListOpenedFiles( bool bListAll, const char *pchFilenameFind, bool bListRecentFiles );
|
||||
|
||||
private:
|
||||
int IdxFileFromName( const char *pFilename, const char *pPathID, int nFileFraction, int64 nLength, bool bPackOrVPKFile, bool bRecordInRecentList );
|
||||
|
||||
static const int k_nFileFractionSize = 0x00100000; // 1 MB
|
||||
static const int k_nFileFractionMask = 0xFFF00000; // 1 MB
|
||||
|
||||
CUtlRBTree< TrackedFile_t, int > m_treeAllOpenedFiles;
|
||||
CUtlMap< FILE *, int, int > m_mapAllOpenFiles; // points into m_treeAllOpenedFiles
|
||||
|
||||
CUtlRBTree< FileInVPK_t, int > m_treeFileInVPK;
|
||||
|
||||
CUtlRBTree< TrackedVPKFile_t, int > m_treeTrackedVPKFiles;
|
||||
|
||||
CUtlLinkedList<int> m_RecentFileList; // points into m_treeAllOpenedFiles
|
||||
int m_cMissedReads;
|
||||
CBaseFileSystem *m_pFileSystem;
|
||||
CThreadMutex m_Mutex; // Threads call into here, so we need to be safe.
|
||||
|
||||
bool m_bComputeFileHashes;
|
||||
CThreadEvent m_threadEventWorkToDo;
|
||||
CThreadEvent m_threadEventWorkCompleted;
|
||||
volatile bool m_bThreadShouldRun;
|
||||
ThreadHandle_t m_hWorkThread;
|
||||
|
||||
CTSQueue< StuffToMD5_t > m_PendingJobs;
|
||||
CTSQueue< StuffToMD5_t > m_CompletedJobs;
|
||||
CUtlLinkedList< SubmittedMd5Job_t > m_SubmittedJobs;
|
||||
|
||||
// just stats
|
||||
int m_cThreadBlocks;
|
||||
};
|
||||
|
||||
|
||||
#endif // FILETRACKER_H
|
261
filesystem/linux_support.cpp
Normal file
261
filesystem/linux_support.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/memdbgoff.h"
|
||||
#include "linux_support.h"
|
||||
|
||||
#ifdef OSX
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
char selectBuf[PATH_MAX];
|
||||
|
||||
#if defined(OSX) && !defined(MAC_OS_X_VERSION_10_9)
|
||||
int FileSelect(struct dirent *ent)
|
||||
#else
|
||||
int FileSelect(const struct dirent *ent)
|
||||
#endif
|
||||
{
|
||||
const char *mask=selectBuf;
|
||||
const char *name=ent->d_name;
|
||||
|
||||
//printf("Test:%s %s\n",mask,name);
|
||||
|
||||
if(!strcmp(name,".") || !strcmp(name,"..") ) return 0;
|
||||
|
||||
if(!strcmp(selectBuf,"*.*")) return 1;
|
||||
|
||||
while( *mask && *name )
|
||||
{
|
||||
if(*mask=='*')
|
||||
{
|
||||
mask++; // move to the next char in the mask
|
||||
if(!*mask) // if this is the end of the mask its a match
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
while(*name && toupper(*name)!=toupper(*mask))
|
||||
{ // while the two don't meet up again
|
||||
name++;
|
||||
}
|
||||
if(!*name)
|
||||
{ // end of the name
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (*mask!='?')
|
||||
{
|
||||
if( toupper(*mask) != toupper(*name) )
|
||||
{ // mismatched!
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask++;
|
||||
name++;
|
||||
if( !*mask && !*name)
|
||||
{ // if its at the end of the buffer
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else /* mask is "?", we don't care*/
|
||||
{
|
||||
mask++;
|
||||
name++;
|
||||
}
|
||||
}
|
||||
|
||||
return( !*mask && !*name ); // both of the strings are at the end
|
||||
}
|
||||
|
||||
int FillDataStruct(FIND_DATA *dat)
|
||||
{
|
||||
struct stat fileStat;
|
||||
|
||||
if(dat->numMatches<0)
|
||||
return -1;
|
||||
|
||||
char szFullPath[MAX_PATH];
|
||||
Q_snprintf( szFullPath, sizeof(szFullPath), "%s/%s", dat->cBaseDir, dat->namelist[dat->numMatches]->d_name );
|
||||
|
||||
if(!stat(szFullPath,&fileStat))
|
||||
{
|
||||
dat->dwFileAttributes=fileStat.st_mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
dat->dwFileAttributes=0;
|
||||
}
|
||||
|
||||
// now just put the filename in the output data
|
||||
Q_snprintf( dat->cFileName, sizeof(dat->cFileName), "%s", dat->namelist[dat->numMatches]->d_name );
|
||||
|
||||
//printf("%s\n", dat->namelist[dat->numMatches]->d_name);
|
||||
free(dat->namelist[dat->numMatches]);
|
||||
|
||||
dat->numMatches--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
HANDLE FindFirstFile( const char *fileName, FIND_DATA *dat)
|
||||
{
|
||||
char nameStore[PATH_MAX];
|
||||
char *dir=NULL;
|
||||
int n,iret=-1;
|
||||
|
||||
Q_strncpy(nameStore,fileName, sizeof( nameStore ) );
|
||||
|
||||
if(strrchr(nameStore,'/') )
|
||||
{
|
||||
dir=nameStore;
|
||||
while(strrchr(dir,'/') )
|
||||
{
|
||||
struct stat dirChk;
|
||||
|
||||
// zero this with the dir name
|
||||
dir=strrchr(nameStore,'/');
|
||||
*dir='\0';
|
||||
|
||||
dir=nameStore;
|
||||
stat(dir,&dirChk);
|
||||
|
||||
if( S_ISDIR( dirChk.st_mode ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// couldn't find a dir seperator...
|
||||
return (HANDLE)-1;
|
||||
}
|
||||
|
||||
if( strlen(dir)>0 )
|
||||
{
|
||||
Q_strncpy(selectBuf,fileName+strlen(dir)+1, sizeof( selectBuf ) );
|
||||
Q_strncpy(dat->cBaseDir,dir, sizeof( dat->cBaseDir ) );
|
||||
dat->namelist = NULL;
|
||||
n = scandir(dir, &dat->namelist, FileSelect, alphasort);
|
||||
if (n < 0)
|
||||
{
|
||||
// silently return, nothing interesting
|
||||
dat->namelist = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
dat->numMatches=n-1; // n is the number of matches
|
||||
iret=FillDataStruct(dat);
|
||||
if ( ( iret<0 ) && dat->namelist )
|
||||
{
|
||||
free(dat->namelist);
|
||||
dat->namelist = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// printf("Returning: %i \n",iret);
|
||||
return (HANDLE)(intp)iret;
|
||||
}
|
||||
|
||||
bool FindNextFile(HANDLE handle, FIND_DATA *dat)
|
||||
{
|
||||
if(dat->numMatches<0)
|
||||
{
|
||||
if ( dat->namelist != NULL )
|
||||
{
|
||||
free( dat->namelist );
|
||||
dat->namelist = NULL;
|
||||
}
|
||||
return false; // no matches left
|
||||
}
|
||||
|
||||
FillDataStruct(dat);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindClose(HANDLE handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char fileName[MAX_PATH];
|
||||
|
||||
#if defined(OSX) && !defined(MAC_OS_X_VERSION_10_9)
|
||||
int CheckName(struct dirent *dir)
|
||||
#else
|
||||
int CheckName(const struct dirent *dir)
|
||||
#endif
|
||||
{
|
||||
return !strcasecmp( dir->d_name, fileName );
|
||||
}
|
||||
|
||||
|
||||
const char *findFileInDirCaseInsensitive(const char *file, char *pFileNameOut)
|
||||
{
|
||||
|
||||
const char *dirSep = strrchr(file,'/');
|
||||
if( !dirSep )
|
||||
{
|
||||
dirSep=strrchr(file,'\\');
|
||||
if( !dirSep )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *dirName = static_cast<char *>( alloca( ( dirSep - file ) +1 ) );
|
||||
if( !dirName )
|
||||
return NULL;
|
||||
|
||||
strncpy( dirName , file, dirSep - file );
|
||||
dirName[ dirSep - file ] = '\0';
|
||||
|
||||
struct dirent **namelist = NULL;
|
||||
|
||||
strncpy( fileName, dirSep + 1, MAX_PATH );
|
||||
|
||||
|
||||
int n = scandir( dirName , &namelist, CheckName, alphasort );
|
||||
|
||||
// Free all entries beyond the first one, we don't care about them
|
||||
while ( n > 1 )
|
||||
{
|
||||
-- n;
|
||||
free( namelist[n] );
|
||||
}
|
||||
|
||||
if ( n > 0 )
|
||||
{
|
||||
Q_snprintf( pFileNameOut, sizeof( fileName ), "%s/%s", dirName, namelist[0]->d_name );
|
||||
free( namelist[0] );
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strncpy( pFileNameOut, file, MAX_PATH );
|
||||
Q_strlower( pFileNameOut );
|
||||
}
|
||||
|
||||
if ( ( n >= 0 ) && namelist )
|
||||
{
|
||||
free( namelist );
|
||||
}
|
||||
|
||||
return pFileNameOut;
|
||||
}
|
||||
|
40
filesystem/linux_support.h
Normal file
40
filesystem/linux_support.h
Normal file
@ -0,0 +1,40 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#ifndef LINUX_SUPPORT_H
|
||||
#define LINUX_SUPPORT_H
|
||||
|
||||
#include <ctype.h> // tolower()
|
||||
#include <limits.h> // PATH_MAX define
|
||||
#include <string.h> //strcmp, strcpy
|
||||
#include <sys/stat.h> // stat()
|
||||
#include <unistd.h>
|
||||
#include <dirent.h> // scandir()
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#define FILE_ATTRIBUTE_DIRECTORY S_IFDIR
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// public data
|
||||
int dwFileAttributes;
|
||||
char cFileName[PATH_MAX]; // the file name returned from the call
|
||||
char cBaseDir[PATH_MAX]; // the root dir for this find
|
||||
|
||||
int numMatches;
|
||||
struct dirent **namelist;
|
||||
} FIND_DATA;
|
||||
|
||||
#define WIN32_FIND_DATA FIND_DATA
|
||||
|
||||
HANDLE FindFirstFile( const char *findName, FIND_DATA *dat);
|
||||
bool FindNextFile(HANDLE handle, FIND_DATA *dat);
|
||||
bool FindClose(HANDLE handle);
|
||||
const char *findFileInDirCaseInsensitive(const char* path, char *file);
|
||||
|
||||
#endif // LINUX_SUPPORT_H
|
85
filesystem/threadsaferefcountedobject.h
Normal file
85
filesystem/threadsaferefcountedobject.h
Normal file
@ -0,0 +1,85 @@
|
||||
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef THREADSAFEREFCOUNTEDOBJECT_H
|
||||
#define THREADSAFEREFCOUNTEDOBJECT_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
// This class can be used for fast access to an object from multiple threads,
|
||||
// and the main thread can wait until the threads are done using the object before it frees the object.
|
||||
template< class T >
|
||||
class CThreadSafeRefCountedObject
|
||||
{
|
||||
public:
|
||||
CThreadSafeRefCountedObject( T initVal )
|
||||
{
|
||||
m_RefCount = 0;
|
||||
m_pObject = initVal;
|
||||
m_RefCount = 0;
|
||||
}
|
||||
|
||||
void Init( T pObj )
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
Assert( !m_pObject );
|
||||
m_RefCount = 0;
|
||||
m_pObject = pObj;
|
||||
m_RefCount = 1;
|
||||
}
|
||||
|
||||
// Threads that access the object need to use AddRef/Release to access it.
|
||||
T AddRef()
|
||||
{
|
||||
if ( ++m_RefCount > 1 )
|
||||
{
|
||||
return m_pObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the refcount was 0 when we called this, then the whitelist is about to be freed.
|
||||
--m_RefCount;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
void ReleaseRef( T pObj )
|
||||
{
|
||||
if ( --m_RefCount >= 1 )
|
||||
{
|
||||
Assert( m_pObject == pObj );
|
||||
}
|
||||
}
|
||||
|
||||
// The main thread can use this to access the object, since only it can Init() and Free() the object.
|
||||
T GetInMainThread()
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
return m_pObject;
|
||||
}
|
||||
|
||||
// The main thread calls this after it has released its last reference to the object.
|
||||
void ResetWhenNoRemainingReferences( T newValue )
|
||||
{
|
||||
Assert( ThreadInMainThread() );
|
||||
|
||||
// Wait until we can free it.
|
||||
while ( m_RefCount > 0 )
|
||||
{
|
||||
CThread::Sleep( 20 );
|
||||
}
|
||||
|
||||
m_pObject = newValue;
|
||||
}
|
||||
|
||||
private:
|
||||
CInterlockedIntT<long> m_RefCount;
|
||||
T m_pObject;
|
||||
};
|
||||
|
||||
|
||||
#endif // THREADSAFEREFCOUNTEDOBJECT_H
|
1
filesystem/vsi.nul
Normal file
1
filesystem/vsi.nul
Normal file
@ -0,0 +1 @@
|
||||
IMPORTANT: Do not remove the custom build step for this file
|
3
filesystem/xbox/xbox.def
Normal file
3
filesystem/xbox/xbox.def
Normal file
@ -0,0 +1,3 @@
|
||||
LIBRARY filesystem_stdio_360.dll
|
||||
EXPORTS
|
||||
CreateInterface @1
|
Reference in New Issue
Block a user