You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
You can now use GetStatData to get all of the stat data for a file (its timestamps, size, read-only state, and type (file or directory)) in a single file-system request. Depending on the platform, this can be much more efficient than making multiple requests. This change also adds alternate directory iteration functions (IterateDirectoryStat and IterateDirectoryStatRecursive) for when you need the stat data along with the files/directories on disk. For platforms that provide this stat data as part of the low-level directory iteration (such as Windows), this can yield much better performance than making two separate file-system requests. Platforms that do not provide this information as part of the directory iteration will just perform a stat request while iterating. #platformnotify Josh.Adams [CL 2634161 by Jamie Dale in Main branch]
602 lines
18 KiB
C++
602 lines
18 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#pragma once
|
|
|
|
/**
|
|
* Wrapper to log the low level file system
|
|
**/
|
|
DECLARE_LOG_CATEGORY_EXTERN(SandboxFile, Log, All);
|
|
|
|
|
|
class SANDBOXFILE_API FSandboxFileHandle : public IFileHandle
|
|
{
|
|
TAutoPtr<IFileHandle> FileHandle;
|
|
FString Filename;
|
|
|
|
public:
|
|
|
|
FSandboxFileHandle(IFileHandle* InFileHandle, const TCHAR* InFilename)
|
|
: FileHandle(InFileHandle)
|
|
, Filename(InFilename)
|
|
{
|
|
}
|
|
|
|
virtual ~FSandboxFileHandle()
|
|
{
|
|
}
|
|
|
|
virtual int64 Tell() override
|
|
{
|
|
return FileHandle->Tell();
|
|
}
|
|
virtual bool Seek(int64 NewPosition) override
|
|
{
|
|
return FileHandle->Seek(NewPosition);
|
|
}
|
|
virtual bool SeekFromEnd(int64 NewPositionRelativeToEnd) override
|
|
{
|
|
return FileHandle->SeekFromEnd(NewPositionRelativeToEnd);
|
|
}
|
|
virtual bool Read(uint8* Destination, int64 BytesToRead) override
|
|
{
|
|
return FileHandle->Read(Destination, BytesToRead);
|
|
}
|
|
virtual bool Write(const uint8* Source, int64 BytesToWrite) override
|
|
{
|
|
return FileHandle->Write(Source, BytesToWrite);
|
|
}
|
|
virtual int64 Size() override
|
|
{
|
|
return FileHandle->Size();
|
|
}
|
|
};
|
|
|
|
class SANDBOXFILE_API FSandboxPlatformFile : public IPlatformFile
|
|
{
|
|
/** Wrapped file */
|
|
IPlatformFile* LowerLevel;
|
|
/** Absolute path to the sandbox directory */
|
|
FString SandboxDirectory;
|
|
/** Relative path to root directory. Cached for faster access */
|
|
FString RelativeRootDirectory;
|
|
/** Absolute path to root directory. Cached for faster access */
|
|
FString AbsoluteRootDirectory;
|
|
/** Absolute path to game directory. Cached for faster access */
|
|
FString AbsoluteGameDirectory;
|
|
/** Access to any file (in unreal standard form) matching this is not allowed */
|
|
TArray<FString> FileExclusionWildcards;
|
|
/** Access to any directory (in unreal standard form) matching this is not allowed */
|
|
TArray<FString> DirectoryExclusionWildcards;
|
|
bool bEntireEngineWillUseThisSandbox;
|
|
|
|
/**
|
|
* Whether the sandbox is enabled or not.
|
|
* Defaults to true.
|
|
* Set to false when operations require writing to the actual physical location given.
|
|
*/
|
|
bool bSandboxEnabled;
|
|
|
|
/**
|
|
* Clears the contents of the specified folder
|
|
*
|
|
* @param AbsolutePath Absolute path to the folder to wipe
|
|
* @return true if the folder's contents could be deleted, false otherwise
|
|
*/
|
|
bool WipeSandboxFolder( const TCHAR* AbsolutePath );
|
|
|
|
/**
|
|
* Finds all files or folders in the given directory.
|
|
* This is partially copied from file manager but since IPlatformFile is lower level
|
|
* it's better to have local version which doesn't use the wrapped IPlatformFile.
|
|
*
|
|
* @param Result List of found files or folders.
|
|
* @param InFilename Path to the folder to look in.
|
|
* @param Files true to include files in the Result
|
|
* @param Files true to include directories in the Result
|
|
*/
|
|
void FindFiles( TArray<FString>& Result, const TCHAR* InFilename, bool Files, bool Directories );
|
|
|
|
/**
|
|
* Deletes a directory
|
|
* This is partially copied from file manager but since IPlatformFile is lower level
|
|
* it's better to have local version which doesn't use the wrapped IPlatformFile.
|
|
*
|
|
* @param Path Path to the directory to delete.
|
|
* @param Tree true to recursively delete the directory and its contents
|
|
* @return true if the operaton was successful.
|
|
*/
|
|
bool DeleteDirectory( const TCHAR* Path, bool Tree );
|
|
|
|
/**
|
|
* Check if a file or directory has been filtered, and hence is unavailable to the outside world
|
|
*
|
|
* @param FilenameOrDirectoryName
|
|
* @param bIsDirectory if true, this is a directory
|
|
* @return true if it is ok to access the non-sandboxed files here
|
|
*/
|
|
bool OkForInnerAccess(const TCHAR* InFilenameOrDirectoryName, bool bIsDirectory = false) const
|
|
{
|
|
if (DirectoryExclusionWildcards.Num() || FileExclusionWildcards.Num())
|
|
{
|
|
FString FilenameOrDirectoryName(InFilenameOrDirectoryName);
|
|
FPaths::MakeStandardFilename(FilenameOrDirectoryName);
|
|
if (bIsDirectory)
|
|
{
|
|
for (int32 Index = 0; Index < DirectoryExclusionWildcards.Num(); Index++)
|
|
{
|
|
if (FilenameOrDirectoryName.MatchesWildcard(DirectoryExclusionWildcards[Index]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int32 Index = 0; Index < FileExclusionWildcards.Num(); Index++)
|
|
{
|
|
if (FilenameOrDirectoryName.MatchesWildcard(FileExclusionWildcards[Index]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
public:
|
|
|
|
static const TCHAR* GetTypeName()
|
|
{
|
|
return TEXT("SandboxFile");
|
|
}
|
|
|
|
/**
|
|
* Converts passed in filename to use a sandbox path.
|
|
* @param InLowerLevel File system to use for actual disk access
|
|
* @param InSandboxDirectory Directory to use for the sandbox, reads are tried here first and all deletes and writes go here
|
|
* @param bEntireEngineWillUseThisSandbox If true, the we set up the engine so that subprocesses also use this subdirectory
|
|
*/
|
|
FSandboxPlatformFile(bool bInEntireEngineWillUseThisSandbox = false);
|
|
|
|
virtual ~FSandboxPlatformFile()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Set whether the sandbox is enabled or not
|
|
*
|
|
* @param bInEnabled true to enable the sandbox, false to disable it
|
|
*/
|
|
virtual void SetSandboxEnabled(bool bInEnabled) override
|
|
{
|
|
bSandboxEnabled = bInEnabled;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the sandbox is enabled or not
|
|
*
|
|
* @return bool true if enabled, false if not
|
|
*/
|
|
virtual bool IsSandboxEnabled() const override
|
|
{
|
|
return bSandboxEnabled;
|
|
}
|
|
|
|
virtual bool ShouldBeUsed(IPlatformFile* Inner, const TCHAR* CmdLine) const override;
|
|
virtual bool Initialize(IPlatformFile* Inner, const TCHAR* CmdLine) override;
|
|
|
|
virtual IPlatformFile* GetLowerLevel() override
|
|
{
|
|
return LowerLevel;
|
|
}
|
|
|
|
virtual const TCHAR* GetName() const override
|
|
{
|
|
return FSandboxPlatformFile::GetTypeName();
|
|
}
|
|
|
|
/**
|
|
* Converts passed in filename to use a sandbox path.
|
|
*
|
|
* @param Filename filename (under game directory) to convert to use a sandbox path. Can be relative or absolute.
|
|
*
|
|
* @return filename using sandbox path
|
|
*/
|
|
FString ConvertToSandboxPath( const TCHAR* Filename ) const;
|
|
|
|
/** Returns sandbox directory */
|
|
const FString& GetSandboxDirectory() const
|
|
{
|
|
return SandboxDirectory;
|
|
}
|
|
|
|
/** Returns absolute root directory */
|
|
const FString& GetAbsoluteRootDirectory() const
|
|
{
|
|
return AbsoluteRootDirectory;
|
|
}
|
|
|
|
/** Returns absolute path to game directory (without the game directory itself) */
|
|
const FString& GetAbsolutePathToGameDirectory();
|
|
|
|
/**
|
|
* Add exclusion. These files and / or directories pretend not to exist so that they cannot be accessed at all (except in the sandbox)
|
|
* @param Wildcard FString::MatchesWildcard-type wild card to test for exclusion
|
|
* @param bIsDirectory if true, this is a directory
|
|
* @Caution, these have a performance cost
|
|
*/
|
|
void AddExclusion(const TCHAR* Wildcard, bool bIsDirectory = false)
|
|
{
|
|
if (bIsDirectory)
|
|
{
|
|
DirectoryExclusionWildcards.AddUnique(FString(Wildcard));
|
|
}
|
|
else
|
|
{
|
|
FileExclusionWildcards.AddUnique(FString(Wildcard));
|
|
}
|
|
}
|
|
|
|
// IPlatformFile Interface
|
|
|
|
virtual bool FileExists(const TCHAR* Filename) override
|
|
{
|
|
// First look for the file in the user dir.
|
|
bool Result = LowerLevel->FileExists( *ConvertToSandboxPath( Filename ) );
|
|
if( Result == false && OkForInnerAccess(Filename))
|
|
{
|
|
Result = LowerLevel->FileExists( Filename );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual int64 FileSize(const TCHAR* Filename) override
|
|
{
|
|
// First look for the file in the user dir.
|
|
int64 Result = LowerLevel->FileSize( *ConvertToSandboxPath( Filename ) );
|
|
if( Result < 0 && OkForInnerAccess(Filename))
|
|
{
|
|
Result = LowerLevel->FileSize( Filename );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual bool DeleteFile(const TCHAR* Filename) override
|
|
{
|
|
// Delete only sandbox files. If the sendbox version doesn't exists
|
|
// assume the delete was successful because we only care if the sandbox version is gone.
|
|
bool Result = true;
|
|
FString SandboxFilename( *ConvertToSandboxPath( Filename ) );
|
|
if( LowerLevel->FileExists( *SandboxFilename ) )
|
|
{
|
|
Result = LowerLevel->DeleteFile( *ConvertToSandboxPath( Filename ) );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual bool IsReadOnly(const TCHAR* Filename) override
|
|
{
|
|
// If the file exists in the sandbox folder and is read-only return true
|
|
// Otherwise it can always be 'overwritten' in the sandbox
|
|
bool Result = false;
|
|
FString SandboxFilename( *ConvertToSandboxPath( Filename ) );
|
|
if( LowerLevel->FileExists( *SandboxFilename ) )
|
|
{
|
|
// If the file exists in sandbox dir check its read-only flag
|
|
Result = LowerLevel->IsReadOnly( *SandboxFilename );
|
|
}
|
|
//else
|
|
//{
|
|
// // Fall back to normal directory
|
|
// Result = LowerLevel->IsReadOnly( Filename );
|
|
//}
|
|
return Result;
|
|
}
|
|
|
|
virtual bool MoveFile(const TCHAR* To, const TCHAR* From) override
|
|
{
|
|
// Only files within the sandbox dir can be moved
|
|
bool Result = false;
|
|
FString SandboxFilename( *ConvertToSandboxPath( From ) );
|
|
if( LowerLevel->FileExists( *SandboxFilename ) )
|
|
{
|
|
Result = LowerLevel->MoveFile( *ConvertToSandboxPath( To ), *SandboxFilename );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual bool SetReadOnly(const TCHAR* Filename, bool bNewReadOnlyValue) override
|
|
{
|
|
bool Result = false;
|
|
FString UserFilename( *ConvertToSandboxPath( Filename ) );
|
|
if( LowerLevel->FileExists( *UserFilename ) )
|
|
{
|
|
Result = LowerLevel->SetReadOnly( *UserFilename, bNewReadOnlyValue );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual FDateTime GetTimeStamp(const TCHAR* Filename) override
|
|
{
|
|
FDateTime Result = FDateTime::MinValue();
|
|
FString UserFilename( *ConvertToSandboxPath( Filename ) );
|
|
if( LowerLevel->FileExists( *UserFilename ) )
|
|
{
|
|
Result = LowerLevel->GetTimeStamp( *UserFilename );
|
|
}
|
|
else if (OkForInnerAccess(Filename))
|
|
{
|
|
Result = LowerLevel->GetTimeStamp( Filename );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual void SetTimeStamp(const TCHAR* Filename, FDateTime DateTime) override
|
|
{
|
|
FString UserFilename( *ConvertToSandboxPath( Filename ) );
|
|
if( LowerLevel->FileExists( *UserFilename ) )
|
|
{
|
|
LowerLevel->SetTimeStamp( *UserFilename, DateTime );
|
|
}
|
|
else if (OkForInnerAccess(Filename))
|
|
{
|
|
LowerLevel->SetTimeStamp( Filename, DateTime );
|
|
}
|
|
}
|
|
|
|
virtual FDateTime GetAccessTimeStamp(const TCHAR* Filename) override
|
|
{
|
|
FDateTime Result = FDateTime::MinValue();
|
|
FString UserFilename( *ConvertToSandboxPath( Filename ) );
|
|
if( LowerLevel->FileExists( *UserFilename ) )
|
|
{
|
|
Result = LowerLevel->GetAccessTimeStamp( *UserFilename );
|
|
}
|
|
else if (OkForInnerAccess(Filename))
|
|
{
|
|
Result = LowerLevel->GetAccessTimeStamp( Filename );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual FString GetFilenameOnDisk(const TCHAR* Filename) override
|
|
{
|
|
FString Result;
|
|
FString UserFilename(*ConvertToSandboxPath(Filename));
|
|
if (LowerLevel->FileExists(*UserFilename))
|
|
{
|
|
Result = LowerLevel->GetFilenameOnDisk(*UserFilename);
|
|
}
|
|
else if (OkForInnerAccess(Filename))
|
|
{
|
|
Result = LowerLevel->GetFilenameOnDisk(Filename);
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual IFileHandle* OpenRead(const TCHAR* Filename, bool bAllowWrite = false) override
|
|
{
|
|
IFileHandle* Result = LowerLevel->OpenRead( *ConvertToSandboxPath(Filename), bAllowWrite );
|
|
if( !Result && OkForInnerAccess(Filename) )
|
|
{
|
|
Result = LowerLevel->OpenRead( Filename );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual IFileHandle* OpenWrite(const TCHAR* Filename, bool bAppend = false, bool bAllowRead = false) override
|
|
{
|
|
// Only files from the sandbox directory can be opened for wiriting
|
|
return LowerLevel->OpenWrite( *ConvertToSandboxPath( Filename ), bAppend, bAllowRead );
|
|
}
|
|
|
|
virtual bool DirectoryExists(const TCHAR* Directory) override
|
|
{
|
|
bool Result = LowerLevel->DirectoryExists( *ConvertToSandboxPath( Directory ) );
|
|
if( Result == false && OkForInnerAccess(Directory, true) )
|
|
{
|
|
Result = LowerLevel->DirectoryExists( Directory );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual bool CreateDirectory(const TCHAR* Directory) override
|
|
{
|
|
// Directories can be created only under the sandbox path
|
|
return LowerLevel->CreateDirectory( *ConvertToSandboxPath( Directory ) );
|
|
}
|
|
|
|
virtual bool DeleteDirectory(const TCHAR* Directory) override
|
|
{
|
|
// Directories can be deleted only under the sandbox path
|
|
return LowerLevel->DeleteDirectory( *ConvertToSandboxPath( Directory ) );
|
|
}
|
|
|
|
virtual FFileStatData GetStatData(const TCHAR* FilenameOrDirectory) override
|
|
{
|
|
FFileStatData Result = LowerLevel->GetStatData( *ConvertToSandboxPath( FilenameOrDirectory ) );
|
|
if (!Result.bIsValid && (OkForInnerAccess(FilenameOrDirectory, false) && OkForInnerAccess(FilenameOrDirectory, true)))
|
|
{
|
|
Result = LowerLevel->GetStatData( FilenameOrDirectory );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
class FSandboxVisitor : public IPlatformFile::FDirectoryVisitor
|
|
{
|
|
public:
|
|
FDirectoryVisitor& Visitor;
|
|
FSandboxPlatformFile& SandboxFile;
|
|
TSet<FString> VisitedSandboxFiles;
|
|
|
|
FSandboxVisitor( FDirectoryVisitor& InVisitor, FSandboxPlatformFile& InSandboxFile )
|
|
: Visitor( InVisitor )
|
|
, SandboxFile( InSandboxFile )
|
|
{
|
|
}
|
|
virtual bool Visit( const TCHAR* FilenameOrDirectory, bool bIsDirectory ) override
|
|
{
|
|
bool CanVisit = true;
|
|
FString LocalFilename( FilenameOrDirectory );
|
|
|
|
if( FCString::Strnicmp( *LocalFilename, *SandboxFile.GetSandboxDirectory(), SandboxFile.GetSandboxDirectory().Len() ) == 0 )
|
|
{
|
|
// FilenameOrDirectory is already pointing to the sandbox directory so add it to the list of sanbox files.
|
|
// The filename is always stored with the abslute sandbox path.
|
|
VisitedSandboxFiles.Add( *LocalFilename );
|
|
// Now convert the sandbox path back to engine path because the sandbox folder should not be exposed
|
|
// to the engine and remain transparent.
|
|
LocalFilename = LocalFilename.Mid(SandboxFile.GetSandboxDirectory().Len());
|
|
if (LocalFilename.StartsWith(TEXT("Engine/")))
|
|
{
|
|
LocalFilename = SandboxFile.GetAbsoluteRootDirectory() / LocalFilename;
|
|
}
|
|
else
|
|
{
|
|
LocalFilename = SandboxFile.GetAbsolutePathToGameDirectory() / LocalFilename;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Favourize Sandbox files over normal path files.
|
|
CanVisit = !VisitedSandboxFiles.Contains( SandboxFile.ConvertToSandboxPath(*LocalFilename ) )
|
|
&& SandboxFile.OkForInnerAccess(*LocalFilename, bIsDirectory);
|
|
}
|
|
if( CanVisit )
|
|
{
|
|
bool Result = Visitor.Visit( *LocalFilename, bIsDirectory );
|
|
return Result;
|
|
}
|
|
else
|
|
{
|
|
// Continue iterating.
|
|
return true;
|
|
}
|
|
}
|
|
};
|
|
|
|
virtual bool IterateDirectory(const TCHAR* Directory, IPlatformFile::FDirectoryVisitor& Visitor) override
|
|
{
|
|
FSandboxVisitor SandboxVisitor( Visitor, *this );
|
|
bool Result = false;
|
|
LowerLevel->IterateDirectory( *ConvertToSandboxPath( Directory ), SandboxVisitor );
|
|
Result = LowerLevel->IterateDirectory( Directory, SandboxVisitor );
|
|
return Result;
|
|
}
|
|
|
|
virtual bool IterateDirectoryRecursively(const TCHAR* Directory, IPlatformFile::FDirectoryVisitor& Visitor) override
|
|
{
|
|
FSandboxVisitor SandboxVisitor( Visitor, *this );
|
|
bool Result = false;
|
|
LowerLevel->IterateDirectoryRecursively( *ConvertToSandboxPath( Directory ), SandboxVisitor );
|
|
Result = LowerLevel->IterateDirectoryRecursively( Directory, SandboxVisitor );
|
|
return Result;
|
|
}
|
|
|
|
class FSandboxStatVisitor : public IPlatformFile::FDirectoryStatVisitor
|
|
{
|
|
public:
|
|
FDirectoryStatVisitor& Visitor;
|
|
FSandboxPlatformFile& SandboxFile;
|
|
TSet<FString> VisitedSandboxFiles;
|
|
|
|
FSandboxStatVisitor( FDirectoryStatVisitor& InVisitor, FSandboxPlatformFile& InSandboxFile )
|
|
: Visitor( InVisitor )
|
|
, SandboxFile( InSandboxFile )
|
|
{
|
|
}
|
|
virtual bool Visit( const TCHAR* FilenameOrDirectory, const FFileStatData& StatData ) override
|
|
{
|
|
bool CanVisit = true;
|
|
FString LocalFilename( FilenameOrDirectory );
|
|
|
|
if( FCString::Strnicmp( *LocalFilename, *SandboxFile.GetSandboxDirectory(), SandboxFile.GetSandboxDirectory().Len() ) == 0 )
|
|
{
|
|
// FilenameOrDirectory is already pointing to the sandbox directory so add it to the list of sanbox files.
|
|
// The filename is always stored with the abslute sandbox path.
|
|
VisitedSandboxFiles.Add( *LocalFilename );
|
|
// Now convert the sandbox path back to engine path because the sandbox folder should not be exposed
|
|
// to the engine and remain transparent.
|
|
LocalFilename = LocalFilename.Mid(SandboxFile.GetSandboxDirectory().Len());
|
|
if (LocalFilename.StartsWith(TEXT("Engine/")))
|
|
{
|
|
LocalFilename = SandboxFile.GetAbsoluteRootDirectory() / LocalFilename;
|
|
}
|
|
else
|
|
{
|
|
LocalFilename = SandboxFile.GetAbsolutePathToGameDirectory() / LocalFilename;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Favourize Sandbox files over normal path files.
|
|
CanVisit = !VisitedSandboxFiles.Contains( SandboxFile.ConvertToSandboxPath(*LocalFilename ) )
|
|
&& SandboxFile.OkForInnerAccess(*LocalFilename, StatData.bIsDirectory);
|
|
}
|
|
if( CanVisit )
|
|
{
|
|
bool Result = Visitor.Visit( *LocalFilename, StatData );
|
|
return Result;
|
|
}
|
|
else
|
|
{
|
|
// Continue iterating.
|
|
return true;
|
|
}
|
|
}
|
|
};
|
|
|
|
virtual bool IterateDirectoryStat(const TCHAR* Directory, IPlatformFile::FDirectoryStatVisitor& Visitor) override
|
|
{
|
|
FSandboxStatVisitor SandboxVisitor( Visitor, *this );
|
|
bool Result = false;
|
|
LowerLevel->IterateDirectoryStat( *ConvertToSandboxPath( Directory ), SandboxVisitor );
|
|
Result = LowerLevel->IterateDirectoryStat( Directory, SandboxVisitor );
|
|
return Result;
|
|
}
|
|
|
|
virtual bool IterateDirectoryStatRecursively(const TCHAR* Directory, IPlatformFile::FDirectoryStatVisitor& Visitor) override
|
|
{
|
|
FSandboxStatVisitor SandboxVisitor( Visitor, *this );
|
|
bool Result = false;
|
|
LowerLevel->IterateDirectoryStatRecursively( *ConvertToSandboxPath( Directory ), SandboxVisitor );
|
|
Result = LowerLevel->IterateDirectoryStatRecursively( Directory, SandboxVisitor );
|
|
return Result;
|
|
}
|
|
|
|
virtual bool DeleteDirectoryRecursively(const TCHAR* Directory) override
|
|
{
|
|
// Directories can be deleted only under the sandbox path
|
|
return LowerLevel->DeleteDirectoryRecursively( *ConvertToSandboxPath( Directory ) );
|
|
}
|
|
|
|
virtual bool CreateDirectoryTree(const TCHAR* Directory) override
|
|
{
|
|
// Directories can only be created only under the sandbox path
|
|
return LowerLevel->CreateDirectoryTree( *ConvertToSandboxPath( Directory ) );
|
|
}
|
|
|
|
virtual bool CopyFile(const TCHAR* To, const TCHAR* From) override
|
|
{
|
|
// Files can be copied only to the sandbox directory
|
|
bool Result = false;
|
|
if( LowerLevel->FileExists( *ConvertToSandboxPath( From ) ) )
|
|
{
|
|
Result = LowerLevel->CopyFile( *ConvertToSandboxPath( To ), *ConvertToSandboxPath( From ) );
|
|
}
|
|
else
|
|
{
|
|
Result = LowerLevel->CopyFile( *ConvertToSandboxPath( To ), From );
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
virtual FString ConvertToAbsolutePathForExternalAppForRead( const TCHAR* Filename ) override;
|
|
virtual FString ConvertToAbsolutePathForExternalAppForWrite( const TCHAR* Filename ) override;
|
|
};
|
|
|
|
|