2022-04-14 22:41:41 +02:00
# include "FSWrapper.h"
# include "FileUtils.h"
# include "utils/StringTools.h"
# include "utils/logger.h"
2022-04-29 13:34:04 +02:00
# include "utils/utils.h"
2022-04-14 22:41:41 +02:00
# include <algorithm>
# include <coreinit/cache.h>
# include <coreinit/debug.h>
2022-08-07 19:22:20 +02:00
# include <coreinit/filesystem_fsa.h>
2022-04-14 22:41:41 +02:00
# include <cstdio>
# include <filesystem>
# include <sys/dirent.h>
# include <sys/fcntl.h>
# include <sys/unistd.h>
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSOpenDirWrapper ( const char * path , FSDirectoryHandle * handle ) {
if ( path = = nullptr ) {
return FS_ERROR_INVALID_PARAM ;
}
2022-04-14 22:41:41 +02:00
if ( ! IsPathToReplace ( path ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( handle = = nullptr ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] handle was nullptr " , getName ( ) . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_INVALID_PARAM ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
2022-04-29 13:34:04 +02:00
auto dirHandle = getNewDirHandle ( ) ;
if ( dirHandle ) {
2022-04-14 22:41:41 +02:00
DIR * dir ;
auto newPath = GetNewPath ( path ) ;
if ( ( dir = opendir ( newPath . c_str ( ) ) ) ) {
dirHandle - > dir = dir ;
2022-04-29 13:34:04 +02:00
dirHandle - > handle = ( ( ( uint32_t ) dirHandle . get ( ) ) & 0x0FFFFFFF ) | 0x30000000 ;
2022-04-14 22:41:41 +02:00
* handle = dirHandle - > handle ;
dirHandle - > path [ 0 ] = ' \0 ' ;
strncat ( dirHandle - > path , newPath . c_str ( ) , sizeof ( dirHandle - > path ) - 1 ) ;
{
std : : lock_guard < std : : mutex > lock ( openDirsMutex ) ;
openDirs . push_back ( dirHandle ) ;
OSMemoryBarrier ( ) ;
}
} else {
2022-08-07 19:22:20 +02:00
auto err = errno ;
if ( err = = ENOENT ) {
DEBUG_FUNCTION_LINE ( " [%s] Open dir %s (%s) failed. FS_ERROR_NOT_FOUND " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) ) ;
return FS_ERROR_NOT_FOUND ;
}
DEBUG_FUNCTION_LINE_ERR ( " [%s] Open dir %s (%s) failed. errno %d " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) , err ) ;
if ( err = = EACCES ) {
return FS_ERROR_PERMISSION_ERROR ;
} else if ( err = = ENOTDIR ) {
return FS_ERROR_NOT_DIR ;
} else if ( err = = ENFILE | | err = = EMFILE ) {
return FS_ERROR_MAX_DIRS ;
}
return FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
}
} else {
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to alloc dir handle " , getName ( ) . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MAX_DIRS ;
2022-04-14 22:41:41 +02:00
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSReadDirWrapper ( FSDirectoryHandle handle , FSDirectoryEntry * entry ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidDirHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto dirHandle = getDirFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
DIR * dir = dirHandle - > dir ;
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_END_OF_DIR ;
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] readdir %08X (handle %08X) " , getName ( ) . c_str ( ) , dir , handle ) ;
do {
2022-08-07 19:22:20 +02:00
errno = 0 ;
2022-04-14 22:41:41 +02:00
struct dirent * entry_ = readdir ( dir ) ;
if ( entry_ ) {
if ( SkipDeletedFilesInReadDir ( ) & & std : : string_view ( entry_ - > d_name ) . starts_with ( deletePrefix ) ) {
DEBUG_FUNCTION_LINE_ERR ( " Skip file file name %s because of the prefix " , entry_ - > d_name ) ;
continue ;
}
entry - > name [ 0 ] = ' \0 ' ;
strncat ( entry - > name , entry_ - > d_name , sizeof ( entry - > name ) - 1 ) ;
entry - > info . mode = ( FSMode ) FS_MODE_READ_OWNER ;
if ( entry_ - > d_type = = DT_DIR ) {
entry - > info . flags = ( FSStatFlags ) ( ( uint32_t ) FS_STAT_DIRECTORY ) ;
entry - > info . size = 0 ;
} else {
entry - > info . flags = ( FSStatFlags ) 0 ;
if ( strcmp ( entry_ - > d_name , " . " ) = = 0 | | strcmp ( entry_ - > d_name , " .. " ) = = 0 ) {
entry - > info . size = 0 ;
} else {
struct stat sb { } ;
2022-08-08 18:03:37 +02:00
auto path = string_format ( " %s/%s " , dirHandle - > path , entry_ - > d_name ) ;
std : : replace ( path . begin ( ) , path . end ( ) , ' \\ ' , ' / ' ) ;
uint32_t length = path . size ( ) ;
//! clear path of double slashes
for ( uint32_t i = 1 ; i < length ; + + i ) {
if ( path [ i - 1 ] = = ' / ' & & path [ i ] = = ' / ' ) {
path . erase ( i , 1 ) ;
i - - ;
length - - ;
}
}
if ( stat ( path . c_str ( ) , & sb ) > = 0 ) {
2022-08-08 10:12:35 +02:00
translate_stat ( & sb , & entry - > info ) ;
} else {
2022-08-08 18:03:37 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to stat file (%s) in read dir %08X (dir handle %08X) " , getName ( ) . c_str ( ) , path . c_str ( ) , dir , handle ) ;
2022-08-08 10:12:35 +02:00
result = FS_ERROR_MEDIA_ERROR ;
break ;
2022-04-14 22:41:41 +02:00
}
}
}
2022-08-07 19:22:20 +02:00
result = FS_ERROR_OK ;
} else {
auto err = errno ;
2024-04-28 15:21:58 +02:00
if ( err ! = 0 & & err ! = 2 ) { // newlib currently has a bug and doesn't clear errno properly when the end of a dir is reached
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to read dir %08X (handle %08X). errno %d (%s) " , getName ( ) . c_str ( ) , dir , handle , err , strerror ( err ) ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
}
2022-04-14 22:41:41 +02:00
}
break ;
} while ( true ) ;
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSCloseDirWrapper ( FSDirectoryHandle handle ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidDirHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto dirHandle = getDirFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
DIR * dir = dirHandle - > dir ;
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] closedir %08X (handle %08X) " , getName ( ) . c_str ( ) , dir , handle ) ;
2022-08-07 19:22:20 +02:00
if ( closedir ( dir ) < 0 ) {
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to close dir %08X (handle %08X) " , getName ( ) . c_str ( ) , dir , handle ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
}
dirHandle - > dir = nullptr ;
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSRewindDirWrapper ( FSDirectoryHandle handle ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidDirHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto dirHandle = getDirFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
DIR * dir = dirHandle - > dir ;
2022-08-07 19:22:20 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] rewinddir %08X (handle %08X) " , getName ( ) . c_str ( ) , dir , handle ) ;
2022-04-14 22:41:41 +02:00
rewinddir ( dir ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSMakeDirWrapper ( const char * path ) {
2022-04-14 22:41:41 +02:00
if ( ! IsPathToReplace ( path ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( ! pIsWriteable ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Tried to create dir %s but layer is not writeable " , getName ( ) . c_str ( ) , path ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_PERMISSION_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-09-05 20:18:20 +02:00
auto newPath = GetNewPath ( path ) ;
auto res = mkdir ( newPath . c_str ( ) , 0000660 ) ;
if ( res < 0 ) {
auto err = errno ;
if ( err = = EACCES ) {
return FS_ERROR_PERMISSION_ERROR ;
} else if ( err = = EEXIST ) {
return FS_ERROR_ALREADY_EXISTS ;
} else if ( err = = ENOTDIR ) {
return FS_ERROR_NOT_DIR ;
} else if ( err = = ENOENT ) {
return FS_ERROR_NOT_FOUND ;
}
2022-09-05 20:20:42 +02:00
return FS_ERROR_MEDIA_ERROR ;
2022-09-05 20:18:20 +02:00
}
return FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSOpenFileWrapper ( const char * path , const char * mode , FSFileHandle * handle ) {
2022-04-14 22:41:41 +02:00
if ( ! IsPathToReplace ( path ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( path = = nullptr ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] path was nullptr " , getName ( ) . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_INVALID_PARAM ;
2022-04-14 22:41:41 +02:00
}
if ( mode = = nullptr | | handle = = nullptr ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] mode or handle was nullptr " , getName ( ) . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_INVALID_PARAM ;
2022-04-14 22:41:41 +02:00
}
auto newPath = GetNewPath ( path ) ;
if ( pCheckIfDeleted & & CheckFileShouldBeIgnored ( newPath ) ) {
2022-08-07 19:22:20 +02:00
return static_cast < FSError > ( ( FS_ERROR_NOT_FOUND & FS_ERROR_REAL_MASK ) | FS_ERROR_FORCE_NO_FALLBACK ) ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
auto result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
int _mode ;
// Map flags to open modes
if ( ! IsFileModeAllowed ( mode ) ) {
OSReport ( " ## WARN ## [%s] Given mode is not allowed %s " , getName ( ) . c_str ( ) , mode ) ;
2022-08-07 19:22:20 +02:00
DEBUG_FUNCTION_LINE ( " [%s] Given mode is not allowed %s " , getName ( ) . c_str ( ) , mode ) ;
return FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
}
if ( strcmp ( mode , " r " ) = = 0 | | strcmp ( mode , " rb " ) = = 0 ) {
2022-08-07 19:22:20 +02:00
_mode = O_RDONLY ;
2022-04-14 22:41:41 +02:00
} else if ( strcmp ( mode , " r+ " ) = = 0 ) {
2022-08-07 19:22:20 +02:00
_mode = O_RDWR ;
2023-08-01 09:52:25 +02:00
} else if ( strcmp ( mode , " w " ) = = 0 | | strcmp ( mode , " wb " ) = = 0 ) {
2022-08-07 19:22:20 +02:00
_mode = O_WRONLY | O_CREAT | O_TRUNC ;
2022-04-14 22:41:41 +02:00
} else if ( strcmp ( mode , " w+ " ) = = 0 ) {
2022-08-07 19:22:20 +02:00
_mode = O_RDWR | O_CREAT | O_TRUNC ;
2022-04-14 22:41:41 +02:00
} else if ( strcmp ( mode , " a " ) = = 0 ) {
2022-08-07 19:22:20 +02:00
_mode = O_WRONLY | O_CREAT | O_APPEND ;
2022-04-14 22:41:41 +02:00
} else if ( strcmp ( mode , " a+ " ) = = 0 ) {
2022-08-07 19:22:20 +02:00
_mode = O_RDWR | O_CREAT | O_APPEND ;
2022-04-14 22:41:41 +02:00
} else {
DEBUG_FUNCTION_LINE_ERR ( " [%s] mode \" %s \" was allowed but is unsupported " , getName ( ) . c_str ( ) , mode ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
}
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Open %s (as %s) mode %s, " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) , mode ) ;
int32_t fd = open ( newPath . c_str ( ) , _mode ) ;
if ( fd > = 0 ) {
2022-04-29 13:34:04 +02:00
auto fileHandle = getNewFileHandle ( ) ;
2022-04-14 22:41:41 +02:00
if ( fileHandle ) {
std : : lock_guard < std : : mutex > lock ( openFilesMutex ) ;
2022-04-29 13:34:04 +02:00
fileHandle - > handle = ( ( ( uint32_t ) fileHandle . get ( ) ) & 0x0FFFFFFF ) | 0x30000000 ;
2022-04-14 22:41:41 +02:00
* handle = fileHandle - > handle ;
fileHandle - > fd = fd ;
2022-08-08 18:03:37 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Opened %s (as %s) mode %s (%08X), fd %d (%08X) " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) , mode , _mode , fd , fileHandle - > handle ) ;
2022-04-14 22:41:41 +02:00
openFiles . push_back ( fileHandle ) ;
OSMemoryBarrier ( ) ;
} else {
close ( fd ) ;
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to alloc new fileHandle " , getName ( ) . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MAX_FILES ;
2022-04-14 22:41:41 +02:00
}
} else {
2022-08-07 19:22:20 +02:00
auto err = errno ;
if ( err = = ENOENT ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] File not found %s (%s) " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) ) ;
result = FS_ERROR_NOT_FOUND ;
} else {
DEBUG_FUNCTION_LINE ( " [%s] Open file %s (%s) failed. errno %d " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) , err ) ;
if ( err = = EACCES ) {
return FS_ERROR_PERMISSION_ERROR ;
} else if ( err = = ENOENT ) {
result = FS_ERROR_NOT_FOUND ;
} else if ( err = = EEXIST ) {
result = FS_ERROR_ALREADY_EXISTS ;
} else if ( err = = EISDIR ) {
result = FS_ERROR_NOT_FILE ;
} else if ( err = = ENOTDIR ) {
result = FS_ERROR_NOT_DIR ;
} else if ( err = = ENFILE | | err = = EMFILE ) {
result = FS_ERROR_MAX_FILES ;
2022-09-05 20:20:26 +02:00
} else {
result = FS_ERROR_MEDIA_ERROR ;
2022-08-07 19:22:20 +02:00
}
}
2022-04-14 22:41:41 +02:00
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSCloseFileWrapper ( FSFileHandle handle ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
int real_fd = fileHandle - > fd ;
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Close %d (handle %08X) " , getName ( ) . c_str ( ) , real_fd , handle ) ;
if ( close ( real_fd ) ! = 0 ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to close %d (handle %08X) " , getName ( ) . c_str ( ) , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
}
fileHandle - > fd = - 1 ;
return result ;
}
bool FSWrapper : : CheckFileShouldBeIgnored ( std : : string & path ) {
auto asPath = std : : filesystem : : path ( path ) ;
if ( std : : string ( asPath . filename ( ) . c_str ( ) ) . starts_with ( deletePrefix ) ) {
2022-09-10 21:24:58 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Ignore %s, filename starts with %s " , getName ( ) . c_str ( ) , path . c_str ( ) , deletePrefix . c_str ( ) ) ;
2022-04-14 22:41:41 +02:00
return true ;
}
auto newDelPath = asPath . replace_filename ( deletePrefix + asPath . filename ( ) . c_str ( ) ) ;
struct stat buf { } ;
if ( stat ( newDelPath . c_str ( ) , & buf ) = = 0 ) {
2022-09-10 21:24:58 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Ignore %s, file %s exists " , getName ( ) . c_str ( ) , path . c_str ( ) , newDelPath . c_str ( ) ) ;
2022-04-14 22:41:41 +02:00
return true ;
}
return false ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSGetStatWrapper ( const char * path , FSStat * stats ) {
2022-04-14 22:41:41 +02:00
if ( path = = nullptr | | stats = = nullptr ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] path was or stats nullptr " , getName ( ) . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_INVALID_PARAM ;
2022-04-14 22:41:41 +02:00
}
if ( ! IsPathToReplace ( path ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
auto newPath = GetNewPath ( path ) ;
struct stat path_stat { } ;
if ( pCheckIfDeleted & & CheckFileShouldBeIgnored ( newPath ) ) {
2022-08-07 19:22:20 +02:00
return static_cast < FSError > ( ( FS_ERROR_NOT_FOUND & FS_ERROR_REAL_MASK ) | FS_ERROR_FORCE_NO_FALLBACK ) ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] stat of %s (%s) " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) ) ;
if ( stat ( newPath . c_str ( ) , & path_stat ) < 0 ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Path %s (%s) not found " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_NOT_FOUND ;
2022-04-14 22:41:41 +02:00
} else {
2022-08-08 10:12:35 +02:00
translate_stat ( & path_stat , stats ) ;
2022-04-14 22:41:41 +02:00
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSGetStatFileWrapper ( FSFileHandle handle , FSStat * stats ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
int real_fd = fileHandle - > fd ;
struct stat path_stat { } ;
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] fstat of fd %d (FSFileHandle %08X) " , getName ( ) . c_str ( ) , real_fd , handle ) ;
if ( fstat ( real_fd , & path_stat ) < 0 ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] fstat of fd %d (FSFileHandle %08X) failed " , getName ( ) . c_str ( ) , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
} else {
2022-08-08 10:12:35 +02:00
translate_stat ( & path_stat , stats ) ;
2022-04-14 22:41:41 +02:00
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSReadFileWrapper ( void * buffer , uint32_t size , uint32_t count , FSFileHandle handle , [[maybe_unused]] uint32_t unk1 ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( size * count = = 0 ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
}
if ( buffer = = nullptr ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] buffer is null but size * count is not 0 (It's: %d) " , getName ( ) . c_str ( ) , size * count ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_INVALID_BUFFER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
int real_fd = fileHandle - > fd ;
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Read %u bytes of fd %08X (FSFileHandle %08X) to buffer %08X " , getName ( ) . c_str ( ) , size * count , real_fd , handle , buffer ) ;
2022-08-07 19:22:20 +02:00
int64_t read = readIntoBuffer ( real_fd , buffer , size , count ) ;
2022-04-14 22:41:41 +02:00
2022-08-07 19:22:20 +02:00
FSError result ;
2022-04-14 22:41:41 +02:00
if ( read < 0 ) {
2022-09-10 21:24:58 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Read %u bytes of fd %d (FSFileHandle %08X) failed " , getName ( ) . c_str ( ) , size * count , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
auto err = errno ;
if ( err = = EBADF | | err = = EROFS ) {
return FS_ERROR_ACCESS_ERROR ;
}
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
} else {
2022-08-07 19:22:20 +02:00
result = static_cast < FSError > ( ( ( uint32_t ) read ) / size ) ;
2022-04-14 22:41:41 +02:00
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSReadFileWithPosWrapper ( void * buffer , uint32_t size , uint32_t count , uint32_t pos , FSFileHandle handle , int32_t unk1 ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Read from with position. " , getName ( ) . c_str ( ) ) ;
2022-08-07 19:22:20 +02:00
FSError result ;
if ( ( result = this - > FSSetPosFileWrapper ( handle , pos ) ) ! = FS_ERROR_OK ) {
2022-04-14 22:41:41 +02:00
return result ;
}
result = this - > FSReadFileWrapper ( buffer , size , count , handle , unk1 ) ;
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSSetPosFileWrapper ( FSFileHandle handle , uint32_t pos ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
int real_fd = fileHandle - > fd ;
2022-09-10 21:24:58 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] lseek fd %d (FSFileHandle %08X) SEEK_SET to position %08X " , getName ( ) . c_str ( ) , real_fd , handle , pos ) ;
2022-08-07 19:22:20 +02:00
off_t newPos ;
if ( ( newPos = lseek ( real_fd , ( off_t ) pos , SEEK_SET ) ) ! = pos ) {
2022-09-10 21:24:58 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] lseek fd %d (FSFileHandle %08X) to position %08X failed " , getName ( ) . c_str ( ) , real_fd , handle , pos ) ;
2022-08-07 19:22:20 +02:00
if ( newPos < 0 ) {
// TODO: read errno
}
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
} else {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] pos set to %u for fd %d (FSFileHandle %08X) " , getName ( ) . c_str ( ) , pos , real_fd , handle ) ;
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSGetPosFileWrapper ( FSFileHandle handle , uint32_t * pos ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
int real_fd = fileHandle - > fd ;
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] lseek fd %08X (FSFileHandle %08X) to get current position for truncation " , getName ( ) . c_str ( ) , real_fd , handle ) ;
off_t currentPos = lseek ( real_fd , ( off_t ) 0 , SEEK_CUR ) ;
if ( currentPos = = - 1 ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to get current position (res: %lld) of fd (handle %08X) to check EoF " , getName ( ) . c_str ( ) , currentPos , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
} else {
* pos = currentPos ;
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSIsEofWrapper ( FSFileHandle handle ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
2022-08-07 19:22:20 +02:00
FSError result ;
2022-04-14 22:41:41 +02:00
int real_fd = fileHandle - > fd ;
2022-08-07 19:22:20 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] lseek fd %08X (FSFileHandle %08X) to get current position for EOF detection " , getName ( ) . c_str ( ) , real_fd , handle ) ;
2022-04-14 22:41:41 +02:00
off_t currentPos = lseek ( real_fd , ( off_t ) 0 , SEEK_CUR ) ;
2022-08-07 19:22:20 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] lseek fd %08X (FSFileHandle %08X) to get end position for EOF detection " , getName ( ) . c_str ( ) , real_fd , handle ) ;
2022-04-14 22:41:41 +02:00
off_t endPos = lseek ( real_fd , ( off_t ) 0 , SEEK_END ) ;
if ( currentPos = = - 1 | | endPos = = - 1 ) {
2022-08-07 19:22:20 +02:00
// TODO: check errno
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to get current position (res: %lld) or endPos (res: %lld) of fd (handle %08X) to check EoF " , getName ( ) . c_str ( ) , currentPos , endPos , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
} else if ( currentPos = = endPos ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] FSIsEof END for %d \n " , getName ( ) . c_str ( ) , real_fd ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_END_OF_FILE ;
2022-04-14 22:41:41 +02:00
} else {
lseek ( real_fd , currentPos , SEEK_CUR ) ;
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] FSIsEof OK for %d \n " , getName ( ) . c_str ( ) , real_fd ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSTruncateFileWrapper ( FSFileHandle handle ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( ! pIsWriteable ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Tried to truncate fd %d (handle %08X) but layer is not writeable " , getName ( ) . c_str ( ) , getFileFromHandle ( handle ) - > fd , handle ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
int real_fd = fileHandle - > fd ;
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] lseek fd %08X (FSFileHandle %08X) to get current position for truncation " , getName ( ) . c_str ( ) , real_fd , handle ) ;
off_t currentPos = lseek ( real_fd , ( off_t ) 0 , SEEK_CUR ) ;
if ( currentPos = = - 1 ) {
2022-08-07 19:22:20 +02:00
// TODO check errno
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Failed to get current position of fd (handle %08X) to truncate file " , getName ( ) . c_str ( ) , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
} else {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Truncate fd %08X (FSFileHandle %08X) to %lld bytes " , getName ( ) . c_str ( ) , real_fd , handle , currentPos ) ;
if ( ftruncate ( real_fd , currentPos ) < 0 ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] ftruncate failed for fd %08X (FSFileHandle %08X) errno %d " , getName ( ) . c_str ( ) , real_fd , handle , errno ) ;
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
}
}
return result ;
}
2022-09-10 21:24:58 +02:00
FSError FSWrapper : : FSWriteFileWrapper ( const uint8_t * buffer , uint32_t size , uint32_t count , FSFileHandle handle , [[maybe_unused]] uint32_t unk1 ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( ! pIsWriteable ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Tried to write to fd %d (handle %08X) but layer is not writeable " , getName ( ) . c_str ( ) , getFileFromHandle ( handle ) - > fd , handle ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
2022-04-14 22:41:41 +02:00
2022-08-07 19:22:20 +02:00
FSError result ;
2022-04-14 22:41:41 +02:00
int real_fd = fileHandle - > fd ;
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Write %u bytes to fd %08X (FSFileHandle %08X) from buffer %08X " , getName ( ) . c_str ( ) , count * size , real_fd , handle , buffer ) ;
auto writeRes = writeFromBuffer ( real_fd , buffer , size , count ) ;
if ( writeRes < 0 ) {
auto err = errno ;
DEBUG_FUNCTION_LINE_ERR ( " [%s] Write failed %u bytes to fd %08X (FSFileHandle %08X) from buffer %08X errno %d " , getName ( ) . c_str ( ) , count * size , real_fd , handle , buffer , err ) ;
if ( err = = EFBIG ) {
2022-08-07 19:22:20 +02:00
result = FS_ERROR_FILE_TOO_BIG ;
2022-04-14 22:41:41 +02:00
} else if ( err = = EACCES ) {
2022-08-07 19:22:20 +02:00
result = FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
} else {
2022-08-07 19:22:20 +02:00
result = FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
}
} else {
2022-08-07 19:22:20 +02:00
result = static_cast < FSError > ( ( ( uint32_t ) writeRes ) / size ) ;
2022-04-14 22:41:41 +02:00
}
return result ;
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSRemoveWrapper ( const char * path ) {
2022-04-14 22:41:41 +02:00
if ( ! IsPathToReplace ( path ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( ! pIsWriteable ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Tried to remove %s but layer is not writeable " , getName ( ) . c_str ( ) , path ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_PERMISSION_ERROR ;
2022-04-14 22:41:41 +02:00
}
auto newPath = GetNewPath ( path ) ;
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Remove %s (%s) " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) ) ;
if ( remove ( newPath . c_str ( ) ) < 0 ) {
auto err = errno ;
2022-09-10 21:24:58 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Rename failed %s (%s) errno %d " , getName ( ) . c_str ( ) , path , newPath . c_str ( ) , err ) ;
2022-04-14 22:41:41 +02:00
if ( err = = ENOTDIR ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_NOT_DIR ;
2022-04-14 22:41:41 +02:00
} else if ( err = = EACCES ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
} else if ( err = = EISDIR ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_NOT_FILE ;
2022-04-14 22:41:41 +02:00
} else if ( err = = EPERM ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_PERMISSION_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
return FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
return FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSRenameWrapper ( const char * oldPath , const char * newPath ) {
2022-04-14 22:41:41 +02:00
if ( ! IsPathToReplace ( oldPath ) | | ! IsPathToReplace ( newPath ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( ! pIsWriteable ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Tried to rename %s to %s but layer is not writeable " , getName ( ) . c_str ( ) , oldPath , newPath ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_PERMISSION_ERROR ;
2022-04-14 22:41:41 +02:00
}
auto oldPathRedirect = GetNewPath ( oldPath ) ;
auto newPathRedirect = GetNewPath ( newPath ) ;
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Rename %s (%s) -> %s (%s) " , getName ( ) . c_str ( ) , oldPath , oldPathRedirect . c_str ( ) , newPath , newPathRedirect . c_str ( ) ) ;
if ( rename ( oldPathRedirect . c_str ( ) , newPathRedirect . c_str ( ) ) < 0 ) {
auto err = errno ;
DEBUG_FUNCTION_LINE_ERR ( " [%s] Rename failed %s (%s) -> %s (%s). errno %d " , getName ( ) . c_str ( ) , oldPath , oldPathRedirect . c_str ( ) , newPath , newPathRedirect . c_str ( ) , err ) ;
if ( err = = ENOTDIR ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_NOT_DIR ;
2022-04-14 22:41:41 +02:00
} else if ( err = = EACCES ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
} else if ( err = = EISDIR ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_NOT_FILE ;
2022-04-14 22:41:41 +02:00
} else if ( err = = EPERM ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_PERMISSION_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
return FS_ERROR_MEDIA_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
return FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
}
2022-08-07 19:22:20 +02:00
FSError FSWrapper : : FSFlushFileWrapper ( FSFileHandle handle ) {
2022-04-14 22:41:41 +02:00
if ( ! isValidFileHandle ( handle ) ) {
2022-08-07 19:22:20 +02:00
return FS_ERROR_FORCE_PARENT_LAYER ;
2022-04-14 22:41:41 +02:00
}
if ( ! pIsWriteable ) {
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Tried to fsync fd %d (handle %08X)) but layer is not writeable " , getName ( ) . c_str ( ) , getFileFromHandle ( handle ) - > fd , handle ) ;
2022-08-07 19:22:20 +02:00
return FS_ERROR_ACCESS_ERROR ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
auto fileHandle = getFileFromHandle ( handle ) ;
int real_fd = fileHandle - > fd ;
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] fsync fd %08X (FSFileHandle %08X) " , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
FSError result = FS_ERROR_OK ;
2022-04-14 22:41:41 +02:00
if ( fsync ( real_fd ) < 0 ) {
DEBUG_FUNCTION_LINE_ERR ( " [%s] fsync failed for fd %08X (FSFileHandle %08X) " , getName ( ) . c_str ( ) , real_fd , handle ) ;
2022-08-07 19:22:20 +02:00
auto err = errno ;
if ( err = = EBADF ) {
result = FS_ERROR_INVALID_FILEHANDLE ;
} else {
result = FS_ERROR_MEDIA_ERROR ;
}
2022-04-14 22:41:41 +02:00
}
return result ;
}
bool FSWrapper : : IsFileModeAllowed ( const char * mode ) {
if ( strcmp ( mode , " r " ) = = 0 | | strcmp ( mode , " rb " ) = = 0 ) {
return true ;
}
if ( pIsWriteable & & ( strcmp ( mode , " r+ " ) = = 0 | |
strcmp ( mode , " w " ) = = 0 | |
2023-08-01 09:52:25 +02:00
strcmp ( mode , " wb " ) = = 0 | |
2022-04-14 22:41:41 +02:00
strcmp ( mode , " w+ " ) = = 0 | |
strcmp ( mode , " a " ) = = 0 | |
strcmp ( mode , " a+ " ) = = 0 ) ) {
return true ;
}
return false ;
}
bool FSWrapper : : IsPathToReplace ( const std : : string_view & path ) {
2024-04-28 12:21:45 +02:00
return path . starts_with ( pPathToReplace ) ;
2022-04-14 22:41:41 +02:00
}
std : : string FSWrapper : : GetNewPath ( const std : : string_view & path ) {
auto subStr = path . substr ( this - > pPathToReplace . length ( ) ) ;
auto res = string_format ( " %s%.*s " , this - > pReplacePathWith . c_str ( ) , int ( subStr . length ( ) ) , subStr . data ( ) ) ;
2022-04-29 13:34:04 +02:00
std : : replace ( res . begin ( ) , res . end ( ) , ' \\ ' , ' / ' ) ;
2022-04-14 22:41:41 +02:00
uint32_t length = res . size ( ) ;
//! clear path of double slashes
for ( uint32_t i = 1 ; i < length ; + + i ) {
if ( res [ i - 1 ] = = ' / ' & & res [ i ] = = ' / ' ) {
res . erase ( i , 1 ) ;
i - - ;
length - - ;
}
}
DEBUG_FUNCTION_LINE_VERBOSE ( " [%s] Redirect %.*s -> %s " , getName ( ) . c_str ( ) , int ( path . length ( ) ) , path . data ( ) , res . c_str ( ) ) ;
return res ;
}
bool FSWrapper : : isValidFileHandle ( FSFileHandle handle ) {
std : : lock_guard < std : : mutex > lock ( openFilesMutex ) ;
2022-04-29 13:34:04 +02:00
return std : : ranges : : any_of ( openFiles , [ handle ] ( auto & cur ) { return cur - > handle = = handle ; } ) ;
2022-04-14 22:41:41 +02:00
}
bool FSWrapper : : isValidDirHandle ( FSDirectoryHandle handle ) {
std : : lock_guard < std : : mutex > lock ( openDirsMutex ) ;
2022-04-29 13:34:04 +02:00
return std : : ranges : : any_of ( openDirs , [ handle ] ( auto & cur ) { return cur - > handle = = handle ; } ) ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
std : : shared_ptr < FileInfo > FSWrapper : : getNewFileHandle ( ) {
return make_shared_nothrow < FileInfo > ( ) ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
std : : shared_ptr < DirInfo > FSWrapper : : getNewDirHandle ( ) {
return make_shared_nothrow < DirInfo > ( ) ;
2022-04-14 22:41:41 +02:00
}
2022-04-29 13:34:04 +02:00
std : : shared_ptr < FileInfo > FSWrapper : : getFileFromHandle ( FSFileHandle handle ) {
2022-04-14 22:41:41 +02:00
std : : lock_guard < std : : mutex > lock ( openFilesMutex ) ;
for ( auto & file : openFiles ) {
if ( file - > handle = = handle ) {
return file ;
}
}
DEBUG_FUNCTION_LINE_ERR ( " [%s] FileInfo for handle %08X was not found. isValidFileHandle check missing? " , getName ( ) . c_str ( ) , handle ) ;
2022-09-10 21:24:58 +02:00
OSFatal ( " ContentRedirectionModule: Failed to find file handle " ) ;
2022-04-14 22:41:41 +02:00
return nullptr ;
}
2022-04-29 13:34:04 +02:00
std : : shared_ptr < DirInfo > FSWrapper : : getDirFromHandle ( FSDirectoryHandle handle ) {
2022-04-14 22:41:41 +02:00
std : : lock_guard < std : : mutex > lock ( openDirsMutex ) ;
for ( auto & dir : openDirs ) {
if ( dir - > handle = = handle ) {
return dir ;
}
}
DEBUG_FUNCTION_LINE_ERR ( " [%s] DirInfo for handle %08X was not found. isValidDirHandle check missing? " , getName ( ) . c_str ( ) , handle ) ;
2022-09-10 21:24:58 +02:00
OSFatal ( " ContentRedirectionModule: Failed to find dir handle " ) ;
2022-04-14 22:41:41 +02:00
return nullptr ;
}
void FSWrapper : : deleteDirHandle ( FSDirectoryHandle handle ) {
2022-04-29 13:34:04 +02:00
if ( ! remove_locked_first_if ( openDirsMutex , openDirs , [ handle ] ( auto & cur ) { return ( FSFileHandle ) cur - > handle = = handle ; } ) ) {
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Delete failed because the handle %08X was not found " , getName ( ) . c_str ( ) , handle ) ;
}
}
void FSWrapper : : deleteFileHandle ( FSFileHandle handle ) {
2022-04-29 13:34:04 +02:00
if ( ! remove_locked_first_if ( openFilesMutex , openFiles , [ handle ] ( auto & cur ) { return ( FSFileHandle ) cur - > handle = = handle ; } ) ) {
2022-04-14 22:41:41 +02:00
DEBUG_FUNCTION_LINE_ERR ( " [%s] Delete failed because the handle %08X was not found " , getName ( ) . c_str ( ) , handle ) ;
}
}
bool FSWrapper : : SkipDeletedFilesInReadDir ( ) {
return true ;
}