2012-11-01 15:19:01 +00:00
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
2012-11-04 22:01:49 +00:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 15:19:01 +00:00
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2013-08-10 21:02:18 +00:00
# include <algorithm>
2013-12-29 22:28:31 +00:00
# include <set>
# include "Common/ChunkFile.h"
2013-05-03 06:22:15 +00:00
# include "Common/StringUtils.h"
2013-05-27 03:23:09 +00:00
# include "Core/FileSystems/MetaFileSystem.h"
# include "Core/HLE/sceKernelThread.h"
# include "Core/Reporting.h"
2012-11-01 15:19:01 +00:00
2012-12-19 10:11:56 +00:00
static bool ApplyPathStringToComponentsVector ( std : : vector < std : : string > & vector , const std : : string & pathString )
2012-12-15 11:38:14 +00:00
{
size_t len = pathString . length ( ) ;
size_t start = 0 ;
while ( start < len )
{
2013-10-20 00:06:29 +00:00
// TODO: This should only be done for ms0:/ etc.
2013-10-20 08:46:23 +00:00
size_t i = pathString . find_first_of ( " / \\ " , start ) ;
2012-12-15 11:38:14 +00:00
if ( i = = std : : string : : npos )
i = len ;
if ( i > start )
{
std : : string component = pathString . substr ( start , i - start ) ;
if ( component ! = " . " )
{
if ( component = = " .. " )
{
if ( vector . size ( ) ! = 0 )
{
vector . pop_back ( ) ;
}
else
{
2012-12-27 13:27:13 +00:00
// The PSP silently ignores attempts to .. to parent of root directory
2013-09-07 20:02:55 +00:00
WARN_LOG ( FILESYS , " RealPath: ignoring .. beyond root - root directory is its own parent: \" %s \" " , pathString . c_str ( ) ) ;
2012-12-15 11:38:14 +00:00
}
}
else
{
vector . push_back ( component ) ;
}
}
}
start = i + 1 ;
}
return true ;
}
/*
* Changes relative paths to absolute , removes " . " , " .. " , and trailing " / "
2012-12-20 13:33:05 +00:00
* " drive:./blah " is absolute ( ignore the dot ) and " /blah " is relative ( because it ' s missing " drive: " )
2012-12-15 11:38:14 +00:00
* babel ( and possibly other games ) use " /directoryThatDoesNotExist/../directoryThatExists/filename "
*/
2012-12-19 10:11:56 +00:00
static bool RealPath ( const std : : string & currentDirectory , const std : : string & inPath , std : : string & outPath )
2012-12-15 11:38:14 +00:00
{
size_t inLen = inPath . length ( ) ;
if ( inLen = = 0 )
{
2013-09-07 20:02:55 +00:00
WARN_LOG ( FILESYS , " RealPath: inPath is empty " ) ;
2013-01-20 23:20:48 +00:00
outPath = currentDirectory ;
return true ;
2012-12-15 11:38:14 +00:00
}
size_t inColon = inPath . find ( ' : ' ) ;
if ( inColon + 1 = = inLen )
{
2013-08-18 00:20:00 +00:00
// There's nothing after the colon, e.g. umd0: - this is perfectly valid.
2012-12-15 11:38:14 +00:00
outPath = inPath ;
return true ;
}
2012-12-20 13:33:05 +00:00
bool relative = ( inColon = = std : : string : : npos ) ;
std : : string prefix , inAfterColon ;
2012-12-15 11:38:14 +00:00
std : : vector < std : : string > cmpnts ; // path components
2012-12-20 13:33:05 +00:00
size_t outPathCapacityGuess = inPath . length ( ) ;
2012-12-15 11:38:14 +00:00
2012-12-20 13:33:05 +00:00
if ( relative )
2012-12-15 11:38:14 +00:00
{
2012-12-20 13:33:05 +00:00
size_t curDirLen = currentDirectory . length ( ) ;
2012-12-15 11:38:14 +00:00
if ( curDirLen = = 0 )
{
2013-09-07 20:02:55 +00:00
ERROR_LOG ( FILESYS , " RealPath: inPath \" %s \" is relative, but current directory is empty " , inPath . c_str ( ) ) ;
2012-12-15 11:38:14 +00:00
return false ;
}
2012-12-20 13:33:05 +00:00
size_t curDirColon = currentDirectory . find ( ' : ' ) ;
if ( curDirColon = = std : : string : : npos )
2012-12-15 11:38:14 +00:00
{
2013-09-07 20:02:55 +00:00
ERROR_LOG ( FILESYS , " RealPath: inPath \" %s \" is relative, but current directory \" %s \" has no prefix " , inPath . c_str ( ) , currentDirectory . c_str ( ) ) ;
2012-12-15 11:38:14 +00:00
return false ;
}
if ( curDirColon + 1 = = curDirLen )
{
2013-09-07 20:02:55 +00:00
ERROR_LOG ( FILESYS , " RealPath: inPath \" %s \" is relative, but current directory \" %s \" is all prefix and no path. Using \" / \" as path for current directory. " , inPath . c_str ( ) , currentDirectory . c_str ( ) ) ;
2012-12-15 11:38:14 +00:00
}
2012-12-15 12:09:37 +00:00
else
2012-12-15 11:38:14 +00:00
{
2012-12-15 12:09:37 +00:00
const std : : string curDirAfter = currentDirectory . substr ( curDirColon + 1 ) ;
2012-12-19 10:11:56 +00:00
if ( ! ApplyPathStringToComponentsVector ( cmpnts , curDirAfter ) )
2012-12-15 12:09:37 +00:00
{
2013-09-07 20:02:55 +00:00
ERROR_LOG ( FILESYS , " RealPath: currentDirectory is not a valid path: \" %s \" " , currentDirectory . c_str ( ) ) ;
2012-12-15 12:09:37 +00:00
return false ;
}
2012-12-20 13:33:05 +00:00
outPathCapacityGuess + = curDirLen ;
2012-12-15 11:38:14 +00:00
}
2012-12-15 11:47:31 +00:00
2012-12-20 13:33:05 +00:00
prefix = currentDirectory . substr ( 0 , curDirColon + 1 ) ;
inAfterColon = inPath ;
}
else
{
prefix = inPath . substr ( 0 , inColon + 1 ) ;
inAfterColon = inPath . substr ( inColon + 1 ) ;
2012-12-15 11:38:14 +00:00
}
2013-05-12 23:01:38 +00:00
// Special case: "disc0:" is different from "disc0:/", so keep track of the single slash.
if ( inAfterColon = = " / " )
{
outPath = prefix + inAfterColon ;
return true ;
}
2012-12-20 13:33:05 +00:00
if ( ! ApplyPathStringToComponentsVector ( cmpnts , inAfterColon ) )
2012-12-15 11:38:14 +00:00
{
2013-09-07 20:02:55 +00:00
WARN_LOG ( FILESYS , " RealPath: inPath is not a valid path: \" %s \" " , inPath . c_str ( ) ) ;
2012-12-15 11:38:14 +00:00
return false ;
}
outPath . clear ( ) ;
2012-12-20 13:33:05 +00:00
outPath . reserve ( outPathCapacityGuess ) ;
2012-12-15 11:38:14 +00:00
2012-12-20 13:33:05 +00:00
outPath . append ( prefix ) ;
2012-12-15 11:38:14 +00:00
size_t numCmpnts = cmpnts . size ( ) ;
for ( size_t i = 0 ; i < numCmpnts ; i + + )
{
outPath . append ( 1 , ' / ' ) ;
outPath . append ( cmpnts [ i ] ) ;
}
return true ;
}
2012-11-01 15:19:01 +00:00
IFileSystem * MetaFileSystem : : GetHandleOwner ( u32 handle )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
for ( size_t i = 0 ; i < fileSystems . size ( ) ; i + + )
{
if ( fileSystems [ i ] . system - > OwnsHandle ( handle ) )
return fileSystems [ i ] . system ; //got it!
}
//none found?
return 0 ;
}
2013-01-11 17:43:10 +00:00
bool MetaFileSystem : : MapFilePath ( const std : : string & _inpath , std : : string & outpath , MountPoint * * system )
2012-11-01 15:19:01 +00:00
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-12-19 10:11:56 +00:00
std : : string realpath ;
2012-12-26 07:24:19 +00:00
2013-10-09 06:55:51 +00:00
std : : string inpath = _inpath ;
// "ms0:/file.txt" is equivalent to " ms0:/file.txt". Yes, really.
if ( inpath . find ( ' : ' ) ! = inpath . npos ) {
size_t offset = 0 ;
while ( inpath [ offset ] = = ' ' ) {
offset + + ;
}
if ( offset > 0 ) {
inpath = inpath . substr ( offset ) ;
}
}
2012-12-26 07:24:19 +00:00
// Special handling: host0:command.txt (as seen in Super Monkey Ball Adventures, for example)
// appears to mean the current directory on the UMD. Let's just assume the current directory.
2013-05-12 23:01:38 +00:00
if ( strncasecmp ( inpath . c_str ( ) , " host0: " , strlen ( " host0: " ) ) = = 0 ) {
2013-09-07 20:02:55 +00:00
INFO_LOG ( FILESYS , " Host0 path detected, stripping: %s " , inpath . c_str ( ) ) ;
2013-05-12 23:01:38 +00:00
inpath = inpath . substr ( strlen ( " host0: " ) ) ;
2012-12-26 07:24:19 +00:00
}
2013-01-10 11:27:10 +00:00
const std : : string * currentDirectory = & startingDirectory ;
int currentThread = __KernelGetCurThread ( ) ;
2013-01-31 07:53:30 +00:00
currentDir_t : : iterator it = currentDir . find ( currentThread ) ;
2013-05-30 20:23:25 +00:00
if ( it = = currentDir . end ( ) )
2013-01-10 11:27:10 +00:00
{
2013-05-30 20:23:25 +00:00
//Attempt to emulate SCE_KERNEL_ERROR_NOCWD / 8002032C: may break things requiring fixes elsewhere
if ( inpath . find ( ' : ' ) = = std : : string : : npos /* means path is relative */ )
{
2013-08-10 16:54:14 +00:00
lastOpenError = SCE_KERNEL_ERROR_NOCWD ;
2013-09-07 20:02:55 +00:00
WARN_LOG ( FILESYS , " Path is relative, but current directory not set for thread %i. returning 8002032C(SCE_KERNEL_ERROR_NOCWD) instead. " , currentThread ) ;
2013-05-30 20:23:25 +00:00
}
2013-01-10 11:27:10 +00:00
}
else
{
2013-01-31 07:53:30 +00:00
currentDirectory = & ( it - > second ) ;
2013-01-10 11:27:10 +00:00
}
if ( RealPath ( * currentDirectory , inpath , realpath ) )
2012-11-01 15:19:01 +00:00
{
2014-02-10 09:41:28 +00:00
std : : string prefix = realpath ;
size_t prefixPos = realpath . find ( ' : ' ) ;
if ( prefixPos ! = realpath . npos )
prefix = NormalizePrefix ( realpath . substr ( 0 , prefixPos + 1 ) ) ;
2012-12-15 11:38:14 +00:00
for ( size_t i = 0 ; i < fileSystems . size ( ) ; i + + )
2012-11-01 15:19:01 +00:00
{
2012-12-15 11:38:14 +00:00
size_t prefLen = fileSystems [ i ] . prefix . size ( ) ;
2014-02-10 09:41:28 +00:00
if ( strncasecmp ( fileSystems [ i ] . prefix . c_str ( ) , prefix . c_str ( ) , prefLen ) = = 0 )
2012-12-15 11:38:14 +00:00
{
2014-02-11 13:26:44 +00:00
outpath = realpath . substr ( prefixPos + 1 ) ;
2013-01-11 16:54:15 +00:00
* system = & ( fileSystems [ i ] ) ;
2012-12-15 11:38:14 +00:00
2013-09-07 20:02:55 +00:00
VERBOSE_LOG ( FILESYS , " MapFilePath: mapped \" %s \" to prefix: \" %s \" , path: \" %s \" " , inpath . c_str ( ) , fileSystems [ i ] . prefix . c_str ( ) , outpath . c_str ( ) ) ;
2012-12-15 11:38:14 +00:00
return true ;
}
2012-11-01 15:19:01 +00:00
}
}
2012-12-15 11:38:14 +00:00
2013-09-07 20:02:55 +00:00
DEBUG_LOG ( FILESYS , " MapFilePath: failed mapping \" %s \" , returning false " , inpath . c_str ( ) ) ;
2012-11-01 15:19:01 +00:00
return false ;
}
2014-02-10 09:41:28 +00:00
std : : string MetaFileSystem : : NormalizePrefix ( std : : string prefix ) const {
// Let's apply some mapping here since it won't break savestates.
if ( prefix = = " memstick: " )
prefix = " ms0: " ;
// Seems like umd00: etc. work just fine...
if ( startsWith ( prefix , " umd " ) )
prefix = " umd0: " ;
// Seems like umd00: etc. work just fine...
if ( startsWith ( prefix , " host " ) )
prefix = " host0: " ;
return prefix ;
}
2012-11-01 15:19:01 +00:00
void MetaFileSystem : : Mount ( std : : string prefix , IFileSystem * system )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2013-01-11 17:43:10 +00:00
MountPoint x ;
2013-08-10 21:02:18 +00:00
x . prefix = prefix ;
x . system = system ;
2012-11-01 15:19:01 +00:00
fileSystems . push_back ( x ) ;
}
2013-08-10 21:02:18 +00:00
void MetaFileSystem : : Unmount ( std : : string prefix , IFileSystem * system )
{
lock_guard guard ( lock ) ;
MountPoint x ;
x . prefix = prefix ;
x . system = system ;
fileSystems . erase ( std : : remove ( fileSystems . begin ( ) , fileSystems . end ( ) , x ) , fileSystems . end ( ) ) ;
}
2013-11-24 10:46:24 +00:00
void MetaFileSystem : : Remount ( IFileSystem * oldSystem , IFileSystem * newSystem ) {
for ( auto it = fileSystems . begin ( ) ; it ! = fileSystems . end ( ) ; + + it ) {
if ( it - > system = = oldSystem ) {
it - > system = newSystem ;
}
}
2013-11-24 08:08:05 +00:00
}
IFileSystem * MetaFileSystem : : GetSystem ( const std : : string & prefix ) {
for ( auto it = fileSystems . begin ( ) ; it ! = fileSystems . end ( ) ; + + it ) {
2014-02-10 09:41:28 +00:00
if ( it - > prefix = = NormalizePrefix ( prefix ) )
2013-11-24 08:08:05 +00:00
return it - > system ;
}
return NULL ;
}
2013-01-10 11:27:10 +00:00
void MetaFileSystem : : Shutdown ( )
2012-11-01 15:19:01 +00:00
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
current = 6 ;
// Ownership is a bit convoluted. Let's just delete everything once.
std : : set < IFileSystem * > toDelete ;
for ( size_t i = 0 ; i < fileSystems . size ( ) ; i + + ) {
toDelete . insert ( fileSystems [ i ] . system ) ;
}
for ( auto iter = toDelete . begin ( ) ; iter ! = toDelete . end ( ) ; + + iter )
{
delete * iter ;
}
fileSystems . clear ( ) ;
2013-01-10 11:27:10 +00:00
currentDir . clear ( ) ;
startingDirectory = " " ;
2012-11-01 15:19:01 +00:00
}
2013-08-10 16:54:14 +00:00
u32 MetaFileSystem : : OpenWithError ( int & error , std : : string filename , FileAccess access , const char * devicename )
{
lock_guard guard ( lock ) ;
u32 h = OpenFile ( filename , access , devicename ) ;
error = lastOpenError ;
return h ;
}
2013-07-08 04:35:07 +00:00
u32 MetaFileSystem : : OpenFile ( std : : string filename , FileAccess access , const char * devicename )
2012-11-01 15:19:01 +00:00
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2013-08-10 16:54:14 +00:00
lastOpenError = 0 ;
2012-11-01 15:19:01 +00:00
std : : string of ;
2013-07-08 04:35:07 +00:00
MountPoint * mount ;
if ( MapFilePath ( filename , of , & mount ) )
2012-11-01 15:19:01 +00:00
{
2013-07-08 04:35:07 +00:00
return mount - > system - > OpenFile ( of , access , mount - > prefix . c_str ( ) ) ;
2012-11-01 15:19:01 +00:00
}
else
{
return 0 ;
}
}
PSPFileInfo MetaFileSystem : : GetFileInfo ( std : : string filename )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
std : : string of ;
2013-01-11 17:43:10 +00:00
IFileSystem * system ;
2012-11-01 15:19:01 +00:00
if ( MapFilePath ( filename , of , & system ) )
{
2013-01-11 17:43:10 +00:00
return system - > GetFileInfo ( of ) ;
2012-11-01 15:19:01 +00:00
}
else
{
PSPFileInfo bogus ; // TODO
return bogus ;
}
}
2013-01-02 20:00:10 +00:00
bool MetaFileSystem : : GetHostPath ( const std : : string & inpath , std : : string & outpath )
2012-11-18 21:07:40 +00:00
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2013-01-02 20:00:10 +00:00
std : : string of ;
2013-01-11 17:43:10 +00:00
IFileSystem * system ;
2013-01-02 20:00:10 +00:00
if ( MapFilePath ( inpath , of , & system ) ) {
2013-01-11 17:43:10 +00:00
return system - > GetHostPath ( of , outpath ) ;
2013-01-02 20:00:10 +00:00
} else {
return false ;
}
2012-11-18 21:07:40 +00:00
}
2012-11-01 15:19:01 +00:00
std : : vector < PSPFileInfo > MetaFileSystem : : GetDirListing ( std : : string path )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
std : : string of ;
2013-01-11 17:43:10 +00:00
IFileSystem * system ;
2012-11-01 15:19:01 +00:00
if ( MapFilePath ( path , of , & system ) )
{
2013-01-11 17:43:10 +00:00
return system - > GetDirListing ( of ) ;
2012-11-01 15:19:01 +00:00
}
else
{
std : : vector < PSPFileInfo > empty ;
return empty ;
}
}
2013-01-10 11:27:10 +00:00
void MetaFileSystem : : ThreadEnded ( int threadID )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2013-01-10 11:27:10 +00:00
currentDir . erase ( threadID ) ;
}
2013-05-12 23:51:08 +00:00
int MetaFileSystem : : ChDir ( const std : : string & dir )
2013-01-10 11:27:10 +00:00
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2013-05-13 00:03:46 +00:00
// Retain the old path and fail if the arg is 1023 bytes or longer.
if ( dir . size ( ) > = 1023 )
return SCE_KERNEL_ERROR_NAMETOOLONG ;
2013-01-10 11:27:10 +00:00
int curThread = __KernelGetCurThread ( ) ;
2013-01-11 00:15:41 +00:00
std : : string of ;
2013-01-11 17:43:10 +00:00
MountPoint * mountPoint ;
if ( MapFilePath ( dir , of , & mountPoint ) )
2013-01-11 00:15:41 +00:00
{
2013-01-11 17:43:10 +00:00
currentDir [ curThread ] = mountPoint - > prefix + of ;
2013-05-12 23:51:08 +00:00
return 0 ;
2013-01-11 00:15:41 +00:00
}
else
{
2013-05-12 23:51:08 +00:00
for ( size_t i = 0 ; i < fileSystems . size ( ) ; i + + )
{
const std : : string & prefix = fileSystems [ i ] . prefix ;
if ( strncasecmp ( prefix . c_str ( ) , dir . c_str ( ) , prefix . size ( ) ) = = 0 )
{
// The PSP is completely happy with invalid current dirs as long as they have a valid device.
2013-09-07 20:02:55 +00:00
WARN_LOG ( FILESYS , " ChDir failed to map path \" %s \" , saving as current directory anyway " , dir . c_str ( ) ) ;
2013-05-12 23:51:08 +00:00
currentDir [ curThread ] = dir ;
return 0 ;
}
}
2013-09-07 20:02:55 +00:00
WARN_LOG_REPORT ( FILESYS , " ChDir failed to map device for \" %s \" , failing " , dir . c_str ( ) ) ;
2013-05-12 23:51:08 +00:00
return SCE_KERNEL_ERROR_NODEV ;
2013-01-11 00:15:41 +00:00
}
2013-01-10 11:27:10 +00:00
}
2012-11-01 15:19:01 +00:00
bool MetaFileSystem : : MkDir ( const std : : string & dirname )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
std : : string of ;
2013-01-11 17:43:10 +00:00
IFileSystem * system ;
2012-11-01 15:19:01 +00:00
if ( MapFilePath ( dirname , of , & system ) )
{
2013-01-11 17:43:10 +00:00
return system - > MkDir ( of ) ;
2012-11-01 15:19:01 +00:00
}
else
{
return false ;
}
}
bool MetaFileSystem : : RmDir ( const std : : string & dirname )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
std : : string of ;
2013-01-11 17:43:10 +00:00
IFileSystem * system ;
2012-11-01 15:19:01 +00:00
if ( MapFilePath ( dirname , of , & system ) )
{
2013-01-11 17:43:10 +00:00
return system - > RmDir ( of ) ;
2012-11-01 15:19:01 +00:00
}
else
{
return false ;
}
}
2013-06-24 03:09:44 +00:00
int MetaFileSystem : : RenameFile ( const std : : string & from , const std : : string & to )
2012-11-27 18:57:30 +00:00
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-27 18:57:30 +00:00
std : : string of ;
std : : string rf ;
2013-06-24 03:09:44 +00:00
IFileSystem * osystem ;
IFileSystem * rsystem = NULL ;
if ( MapFilePath ( from , of , & osystem ) )
2012-11-27 18:57:30 +00:00
{
2013-06-24 03:09:44 +00:00
// If it's a relative path, it seems to always use from's filesystem.
2013-07-05 06:55:09 +00:00
if ( to . find ( " :/ " ) ! = to . npos )
2013-06-24 03:09:44 +00:00
{
if ( ! MapFilePath ( to , rf , & rsystem ) )
return - 1 ;
}
else
{
rf = to ;
rsystem = osystem ;
}
if ( osystem ! = rsystem )
return SCE_KERNEL_ERROR_XDEV ;
return osystem - > RenameFile ( of , rf ) ;
2012-11-27 18:57:30 +00:00
}
else
{
2013-06-24 03:09:44 +00:00
return - 1 ;
2012-11-27 18:57:30 +00:00
}
}
2013-02-08 18:20:52 +00:00
bool MetaFileSystem : : RemoveFile ( const std : : string & filename )
2012-11-01 15:19:01 +00:00
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
std : : string of ;
2013-01-11 17:43:10 +00:00
IFileSystem * system ;
2012-11-01 15:19:01 +00:00
if ( MapFilePath ( filename , of , & system ) )
{
2013-02-08 18:20:52 +00:00
return system - > RemoveFile ( of ) ;
2012-11-01 15:19:01 +00:00
}
else
{
return false ;
}
}
2013-12-26 22:47:17 +00:00
int MetaFileSystem : : Ioctl ( u32 handle , u32 cmd , u32 indataPtr , u32 inlen , u32 outdataPtr , u32 outlen , int & usec )
{
lock_guard guard ( lock ) ;
IFileSystem * sys = GetHandleOwner ( handle ) ;
if ( sys )
return sys - > Ioctl ( handle , cmd , indataPtr , inlen , outdataPtr , outlen , usec ) ;
return SCE_KERNEL_ERROR_ERROR ;
}
2013-12-27 06:07:41 +00:00
int MetaFileSystem : : DevType ( u32 handle )
{
lock_guard guard ( lock ) ;
IFileSystem * sys = GetHandleOwner ( handle ) ;
if ( sys )
return sys - > DevType ( handle ) ;
return SCE_KERNEL_ERROR_ERROR ;
}
2012-11-01 15:19:01 +00:00
void MetaFileSystem : : CloseFile ( u32 handle )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
IFileSystem * sys = GetHandleOwner ( handle ) ;
if ( sys )
sys - > CloseFile ( handle ) ;
}
size_t MetaFileSystem : : ReadFile ( u32 handle , u8 * pointer , s64 size )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
IFileSystem * sys = GetHandleOwner ( handle ) ;
if ( sys )
return sys - > ReadFile ( handle , pointer , size ) ;
else
return 0 ;
}
size_t MetaFileSystem : : WriteFile ( u32 handle , const u8 * pointer , s64 size )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
IFileSystem * sys = GetHandleOwner ( handle ) ;
if ( sys )
return sys - > WriteFile ( handle , pointer , size ) ;
else
return 0 ;
}
size_t MetaFileSystem : : SeekFile ( u32 handle , s32 position , FileMove type )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2012-11-01 15:19:01 +00:00
IFileSystem * sys = GetHandleOwner ( handle ) ;
if ( sys )
return sys - > SeekFile ( handle , position , type ) ;
else
return 0 ;
}
2013-12-09 16:04:33 +00:00
int MetaFileSystem : : ReadEntireFile ( const std : : string & filename , std : : vector < u8 > & data ) {
2013-12-08 19:05:36 +00:00
int error = 0 ;
2013-12-29 23:11:29 +00:00
u32 handle = OpenWithError ( error , filename , FILEACCESS_READ ) ;
2013-12-08 19:05:36 +00:00
if ( handle = = 0 )
return error ;
2013-12-29 23:11:29 +00:00
size_t dataSize = ( size_t ) GetFileInfo ( filename ) . size ;
2013-12-08 19:05:36 +00:00
data . resize ( dataSize ) ;
2013-12-29 23:11:29 +00:00
size_t result = ReadFile ( handle , ( u8 * ) & data [ 0 ] , dataSize ) ;
CloseFile ( handle ) ;
2013-12-08 19:05:36 +00:00
if ( result ! = dataSize )
return SCE_KERNEL_ERROR_ERROR ;
return 0 ;
}
2012-12-28 06:14:31 +00:00
void MetaFileSystem : : DoState ( PointerWrap & p )
{
2013-08-10 16:27:06 +00:00
lock_guard guard ( lock ) ;
2013-12-29 23:11:29 +00:00
2013-09-15 03:23:03 +00:00
auto s = p . Section ( " MetaFileSystem " , 1 ) ;
if ( ! s )
return ;
2012-12-28 06:14:31 +00:00
p . Do ( current ) ;
2013-01-10 11:27:10 +00:00
// Save/load per-thread current directory map
2013-02-04 09:31:02 +00:00
p . Do ( currentDir ) ;
2013-01-10 11:27:10 +00:00
2013-02-04 16:24:32 +00:00
u32 n = ( u32 ) fileSystems . size ( ) ;
2012-12-28 06:14:31 +00:00
p . Do ( n ) ;
2013-10-13 16:34:20 +00:00
bool skipPfat0 = false ;
2013-02-04 16:24:32 +00:00
if ( n ! = ( u32 ) fileSystems . size ( ) )
2012-12-28 06:14:31 +00:00
{
2013-10-13 16:34:20 +00:00
if ( n = = ( u32 ) fileSystems . size ( ) - 1 ) {
skipPfat0 = true ;
} else {
p . SetError ( p . ERROR_FAILURE ) ;
ERROR_LOG ( FILESYS , " Savestate failure: number of filesystems doesn't match. " ) ;
return ;
}
2012-12-28 06:14:31 +00:00
}
2013-10-13 16:34:20 +00:00
for ( u32 i = 0 ; i < n ; + + i ) {
if ( ! skipPfat0 | | fileSystems [ i ] . prefix ! = " pfat0: " ) {
fileSystems [ i ] . system - > DoState ( p ) ;
}
}
2012-12-28 06:14:31 +00:00
}