2012-11-15 00:39:56 +01:00
# include "stdafx.h"
2013-10-06 14:07:42 +02:00
# include "SC_FileSystem.h"
2012-11-15 00:39:56 +01:00
# include "Emu/SysCalls/SysCalls.h"
2013-06-30 10:46:29 +02:00
extern Module sys_fs ;
2012-11-15 00:39:56 +01:00
2013-09-24 23:11:29 +02:00
int cellFsOpen ( u32 path_addr , int flags , mem32_t fd , mem32_t arg , u64 size )
2012-11-15 00:39:56 +01:00
{
2013-12-24 04:58:32 +01:00
const wxString & path = wxString ( Memory . ReadString ( path_addr ) , wxConvUTF8 ) ;
2013-06-30 10:46:29 +02:00
sys_fs . Log ( " cellFsOpen(path: %s, flags: 0x%x, fd_addr: 0x%x, arg_addr: 0x%x, size: 0x%llx) " ,
2013-11-19 11:30:58 +01:00
path . mb_str ( ) , flags , fd . GetAddr ( ) , arg . GetAddr ( ) , size ) ;
2012-11-15 00:39:56 +01:00
2013-06-30 10:46:29 +02:00
const wxString & ppath = path ;
2012-11-15 00:39:56 +01:00
//ConLog.Warning("path: %s [%s]", ppath, path);
s32 _oflags = flags ;
2013-10-06 14:07:42 +02:00
if ( flags & CELL_O_CREAT )
2012-11-15 00:39:56 +01:00
{
2013-10-06 14:07:42 +02:00
_oflags & = ~ CELL_O_CREAT ;
2013-06-30 10:46:29 +02:00
/*
2012-11-15 00:39:56 +01:00
//create path
for ( uint p = 1 ; p < ppath . Length ( ) ; p + + )
{
for ( ; p < ppath . Length ( ) ; p + + ) if ( ppath [ p ] = = ' / ' ) break ;
if ( p = = ppath . Length ( ) ) break ;
const wxString & dir = ppath ( 0 , p ) ;
if ( ! wxDirExists ( dir ) )
{
ConLog . Write ( " create dir: %s " , dir ) ;
wxMkdir ( dir ) ;
}
}
//create file
if ( ! wxFileExists ( ppath ) )
{
wxFile f ;
f . Create ( ppath ) ;
f . Close ( ) ;
}
2013-06-30 10:46:29 +02:00
*/
Emu . GetVFS ( ) . Create ( ppath ) ;
2012-11-15 00:39:56 +01:00
}
2013-06-30 10:46:29 +02:00
vfsOpenMode o_mode ;
2012-11-15 00:39:56 +01:00
2013-10-06 14:07:42 +02:00
switch ( flags & CELL_O_ACCMODE )
2012-11-15 00:39:56 +01:00
{
2013-10-06 14:07:42 +02:00
case CELL_O_RDONLY :
_oflags & = ~ CELL_O_RDONLY ;
2013-06-30 10:46:29 +02:00
o_mode = vfsRead ;
2012-11-15 00:39:56 +01:00
break ;
2013-10-06 14:07:42 +02:00
case CELL_O_WRONLY :
_oflags & = ~ CELL_O_WRONLY ;
2012-11-15 00:39:56 +01:00
2013-10-06 14:07:42 +02:00
if ( flags & CELL_O_APPEND )
2012-11-15 00:39:56 +01:00
{
2013-10-06 14:07:42 +02:00
_oflags & = ~ CELL_O_APPEND ;
2013-06-30 10:46:29 +02:00
o_mode = vfsWriteAppend ;
2012-11-15 00:39:56 +01:00
}
2013-10-06 14:07:42 +02:00
else if ( flags & CELL_O_EXCL )
2012-11-15 00:39:56 +01:00
{
2013-10-06 14:07:42 +02:00
_oflags & = ~ CELL_O_EXCL ;
2013-06-30 10:46:29 +02:00
o_mode = vfsWriteExcl ;
2012-11-15 00:39:56 +01:00
}
2013-10-06 14:07:42 +02:00
else //if(flags & CELL_O_TRUNC)
2012-11-15 00:39:56 +01:00
{
2013-10-06 14:07:42 +02:00
_oflags & = ~ CELL_O_TRUNC ;
2013-06-30 10:46:29 +02:00
o_mode = vfsWrite ;
2012-11-15 00:39:56 +01:00
}
break ;
2013-10-06 14:07:42 +02:00
case CELL_O_RDWR :
_oflags & = ~ CELL_O_RDWR ;
2013-06-30 10:46:29 +02:00
o_mode = vfsReadWrite ;
2012-11-15 00:39:56 +01:00
break ;
}
if ( _oflags ! = 0 )
{
2013-11-19 11:30:58 +01:00
sys_fs . Error ( " '%s' has unknown flags! flags: 0x%08x " , ppath . mb_str ( ) , flags ) ;
2012-11-15 00:39:56 +01:00
return CELL_EINVAL ;
}
2013-06-30 10:46:29 +02:00
vfsStream * stream = Emu . GetVFS ( ) . Open ( ppath , o_mode ) ;
if ( ! stream | | ! stream - > IsOpened ( ) )
2012-11-15 00:39:56 +01:00
{
2013-11-19 11:30:58 +01:00
sys_fs . Error ( " '%s' not found! flags: 0x%08x " , ppath . mb_str ( ) , flags ) ;
2013-06-30 10:46:29 +02:00
delete stream ;
2012-11-15 00:39:56 +01:00
return CELL_ENOENT ;
}
2013-09-24 23:11:29 +02:00
fd = sys_fs . GetNewId ( stream , flags ) ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-09-24 23:11:29 +02:00
int cellFsRead ( u32 fd , u32 buf_addr , u64 nbytes , mem64_t nread )
2012-11-15 00:39:56 +01:00
{
2013-06-30 10:46:29 +02:00
sys_fs . Log ( " cellFsRead(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nread_addr: 0x%x) " ,
2013-09-24 23:11:29 +02:00
fd , buf_addr , nbytes , nread . GetAddr ( ) ) ;
2013-06-30 10:46:29 +02:00
ID id ;
if ( ! sys_fs . CheckId ( fd , id ) ) return CELL_ESRCH ;
vfsStream & file = * ( vfsStream * ) id . m_data ;
2012-11-15 00:39:56 +01:00
2013-10-06 16:15:04 +02:00
if ( Memory . IsGoodAddr ( buf_addr ) & & ! Memory . IsGoodAddr ( buf_addr , nbytes ) )
{
MemoryBlock & block = Memory . GetMemByAddr ( buf_addr ) ;
nbytes = block . GetSize ( ) - ( buf_addr - block . GetStartAddr ( ) ) ;
}
2013-10-06 14:07:42 +02:00
const u64 res = nbytes ? file . Read ( Memory . GetMemFromAddr ( buf_addr ) , nbytes ) : 0 ;
if ( nread . IsGood ( ) )
nread = res ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-09-24 23:11:29 +02:00
int cellFsWrite ( u32 fd , u32 buf_addr , u64 nbytes , mem64_t nwrite )
2012-11-15 00:39:56 +01:00
{
2013-06-30 10:46:29 +02:00
sys_fs . Log ( " cellFsWrite(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nwrite_addr: 0x%x) " ,
2013-09-24 23:11:29 +02:00
fd , buf_addr , nbytes , nwrite . GetAddr ( ) ) ;
2013-06-30 10:46:29 +02:00
ID id ;
if ( ! sys_fs . CheckId ( fd , id ) ) return CELL_ESRCH ;
vfsStream & file = * ( vfsStream * ) id . m_data ;
2013-07-12 14:42:17 +02:00
if ( Memory . IsGoodAddr ( buf_addr ) & & ! Memory . IsGoodAddr ( buf_addr , nbytes ) )
{
MemoryBlock & block = Memory . GetMemByAddr ( buf_addr ) ;
nbytes = block . GetSize ( ) - ( buf_addr - block . GetStartAddr ( ) ) ;
}
2012-11-15 00:39:56 +01:00
2013-10-06 14:07:42 +02:00
const u64 res = nbytes ? file . Write ( Memory . GetMemFromAddr ( buf_addr ) , nbytes ) : 0 ;
if ( nwrite . IsGood ( ) )
nwrite = res ;
2013-09-24 23:11:29 +02:00
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-06-30 10:46:29 +02:00
int cellFsClose ( u32 fd )
2012-11-15 00:39:56 +01:00
{
2013-06-30 10:46:29 +02:00
sys_fs . Log ( " cellFsClose(fd: %d) " , fd ) ;
ID id ;
if ( ! sys_fs . CheckId ( fd , id ) ) return CELL_ESRCH ;
vfsStream & file = * ( vfsStream * ) id . m_data ;
2012-11-15 00:39:56 +01:00
file . Close ( ) ;
Emu . GetIdManager ( ) . RemoveID ( fd ) ;
return CELL_OK ;
}
2013-09-24 23:11:29 +02:00
int cellFsOpendir ( u32 path_addr , mem32_t fd )
2012-11-15 00:39:56 +01:00
{
const wxString & path = Memory . ReadString ( path_addr ) ;
2013-11-19 11:30:58 +01:00
sys_fs . Error ( " cellFsOpendir(path_addr: 0x%x(%s), fd_addr: 0x%x) " , path_addr , path . mb_str ( ) , fd . GetAddr ( ) ) ;
2013-09-24 23:11:29 +02:00
if ( ! Memory . IsGoodAddr ( path_addr ) | | ! fd . IsGood ( ) ) return CELL_EFAULT ;
2013-06-30 10:46:29 +02:00
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-09-24 23:11:29 +02:00
int cellFsReaddir ( u32 fd , u32 dir_addr , mem64_t nread )
2012-11-15 00:39:56 +01:00
{
2013-09-24 23:11:29 +02:00
sys_fs . Error ( " cellFsReaddir(fd: %d, dir_addr: 0x%x, nread_addr: 0x%x) " , fd , dir_addr , nread . GetAddr ( ) ) ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-06-30 10:46:29 +02:00
int cellFsClosedir ( u32 fd )
2012-11-15 00:39:56 +01:00
{
2013-06-30 10:46:29 +02:00
sys_fs . Error ( " cellFsClosedir(fd: %d) " , fd ) ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-11-19 22:10:23 +01:00
int cellFsStat ( const u32 path_addr , mem_ptr_t < CellFsStat > sb )
2012-11-15 00:39:56 +01:00
{
2013-06-30 10:46:29 +02:00
const wxString & path = Memory . ReadString ( path_addr ) ;
2014-01-05 00:58:03 +01:00
sys_fs . Log ( " cellFsStat(path: %s, sb_addr: 0x%x) " , path . mb_str ( ) , sb . GetAddr ( ) ) ;
2012-11-15 00:39:56 +01:00
2013-10-06 16:15:04 +02:00
sb - > st_mode =
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR |
CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP |
CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH ;
sb - > st_uid = 0 ;
sb - > st_gid = 0 ;
2013-11-19 11:30:58 +01:00
sb - > st_atime_ = 0 ; //TODO
sb - > st_mtime_ = 0 ; //TODO
sb - > st_ctime_ = 0 ; //TODO
2013-10-06 16:15:04 +02:00
sb - > st_blksize = 4096 ;
2013-09-18 23:50:00 +02:00
// Check if path is a mount point. (TODO: Add information in sb_addr)
for ( u32 i = 0 ; i < Emu . GetVFS ( ) . m_devices . GetCount ( ) ; + + i )
{
2013-10-06 16:15:04 +02:00
if ( path . CmpNoCase ( Emu . GetVFS ( ) . m_devices [ i ] . GetPs3Path ( ) . RemoveLast ( 1 ) ) = = 0 )
2013-09-18 23:50:00 +02:00
{
2014-01-05 00:45:44 +01:00
sys_fs . Log ( " cellFsStat: '%s' is a mount point. " , path . mb_str ( ) ) ;
2013-10-06 16:15:04 +02:00
sb - > st_mode | = CELL_FS_S_IFDIR ;
2013-09-18 23:50:00 +02:00
return CELL_OK ;
}
}
2014-01-05 00:45:44 +01:00
// TODO: Temporary solution until vfsDir is implemented
wxString real_path ;
Emu . GetVFS ( ) . GetDevice ( path , real_path ) ;
struct stat s ;
if ( stat ( real_path . c_str ( ) , & s ) = = 0 )
2013-08-26 16:18:59 +02:00
{
2014-01-05 00:45:44 +01:00
if ( s . st_mode & S_IFDIR )
{
sb - > st_mode | = CELL_FS_S_IFDIR ;
}
else if ( s . st_mode & S_IFREG )
{
vfsFile f ( path ) ;
sb - > st_mode | = CELL_FS_S_IFREG ;
sb - > st_size = f . GetSize ( ) ;
}
}
else
2013-08-26 16:18:59 +02:00
{
2014-01-05 00:45:44 +01:00
sys_fs . Warning ( " cellFsStat: '%s' not found. " , path . mb_str ( ) ) ;
2013-08-26 16:18:59 +02:00
return CELL_ENOENT ;
}
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-11-19 22:10:23 +01:00
int cellFsFstat ( u32 fd , mem_ptr_t < CellFsStat > sb )
2012-11-15 00:39:56 +01:00
{
2013-09-24 23:11:29 +02:00
sys_fs . Log ( " cellFsFstat(fd: %d, sb_addr: 0x%x) " , fd , sb . GetAddr ( ) ) ;
2013-06-30 10:46:29 +02:00
ID id ;
if ( ! sys_fs . CheckId ( fd , id ) ) return CELL_ESRCH ;
vfsStream & file = * ( vfsStream * ) id . m_data ;
2012-11-15 00:39:56 +01:00
2013-10-06 14:07:42 +02:00
sb - > st_mode =
2012-11-15 00:39:56 +01:00
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR |
CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP |
CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH ;
2013-10-06 14:07:42 +02:00
sb - > st_mode | = CELL_FS_S_IFREG ; //TODO: dir CELL_FS_S_IFDIR
sb - > st_uid = 0 ;
sb - > st_gid = 0 ;
2013-11-19 11:30:58 +01:00
sb - > st_atime_ = 0 ; //TODO
sb - > st_mtime_ = 0 ; //TODO
sb - > st_ctime_ = 0 ; //TODO
2013-10-06 14:07:42 +02:00
sb - > st_size = file . GetSize ( ) ;
sb - > st_blksize = 4096 ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-06-30 10:46:29 +02:00
int cellFsMkdir ( u32 path_addr , u32 mode )
2012-11-15 00:39:56 +01:00
{
2013-09-18 23:50:00 +02:00
const wxString & ps3_path = Memory . ReadString ( path_addr ) ;
wxString path ;
Emu . GetVFS ( ) . GetDevice ( ps3_path , path ) ;
2013-11-19 11:30:58 +01:00
sys_fs . Log ( " cellFsMkdir(path: %s, mode: 0x%x) " , path . mb_str ( ) , mode ) ;
2012-11-15 00:39:56 +01:00
if ( wxDirExists ( path ) ) return CELL_EEXIST ;
if ( ! wxMkdir ( path ) ) return CELL_EBUSY ;
return CELL_OK ;
}
2013-06-30 10:46:29 +02:00
int cellFsRename ( u32 from_addr , u32 to_addr )
2012-11-15 00:39:56 +01:00
{
2013-09-18 23:50:00 +02:00
const wxString & ps3_from = Memory . ReadString ( from_addr ) ;
const wxString & ps3_to = Memory . ReadString ( to_addr ) ;
wxString from ;
wxString to ;
Emu . GetVFS ( ) . GetDevice ( ps3_from , from ) ;
Emu . GetVFS ( ) . GetDevice ( ps3_to , to ) ;
2013-11-19 11:30:58 +01:00
sys_fs . Log ( " cellFsRename(from: %s, to: %s) " , from . mb_str ( ) , to . mb_str ( ) ) ;
2012-11-15 00:39:56 +01:00
if ( ! wxFileExists ( from ) ) return CELL_ENOENT ;
if ( wxFileExists ( to ) ) return CELL_EEXIST ;
2013-09-18 23:50:00 +02:00
if ( ! wxRenameFile ( from , to ) ) return CELL_EBUSY ; // (TODO: RenameFile(a,b) = CopyFile(a,b) + RemoveFile(a), therefore file "a" will not be removed if it is opened)
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-06-30 10:46:29 +02:00
int cellFsRmdir ( u32 path_addr )
2012-11-15 00:39:56 +01:00
{
2013-09-18 23:50:00 +02:00
const wxString & ps3_path = Memory . ReadString ( path_addr ) ;
wxString path ;
Emu . GetVFS ( ) . GetDevice ( ps3_path , path ) ;
2013-11-19 11:30:58 +01:00
sys_fs . Log ( " cellFsRmdir(path: %s) " , path . mb_str ( ) ) ;
2012-11-15 00:39:56 +01:00
if ( ! wxDirExists ( path ) ) return CELL_ENOENT ;
2013-09-18 23:50:00 +02:00
if ( ! wxRmdir ( path ) ) return CELL_EBUSY ; // (TODO: Under certain conditions it is not able to delete the folder)
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-06-30 10:46:29 +02:00
int cellFsUnlink ( u32 path_addr )
2012-11-15 00:39:56 +01:00
{
2013-09-18 23:50:00 +02:00
const wxString & ps3_path = Memory . ReadString ( path_addr ) ;
wxString path ;
Emu . GetVFS ( ) . GetDevice ( ps3_path , path ) ;
2013-11-19 11:30:58 +01:00
sys_fs . Error ( " cellFsUnlink(path: %s) " , path . mb_str ( ) ) ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2013-09-24 23:11:29 +02:00
int cellFsLseek ( u32 fd , s64 offset , u32 whence , mem64_t pos )
2012-11-15 00:39:56 +01:00
{
2013-06-30 10:46:29 +02:00
vfsSeekMode seek_mode ;
2013-09-24 23:11:29 +02:00
sys_fs . Log ( " cellFsLseek(fd: %d, offset: 0x%llx, whence: %d, pos_addr: 0x%x) " , fd , offset , whence , pos . GetAddr ( ) ) ;
2012-11-15 00:39:56 +01:00
switch ( whence )
{
2013-10-06 14:07:42 +02:00
case CELL_SEEK_SET : seek_mode = vfsSeekSet ; break ;
case CELL_SEEK_CUR : seek_mode = vfsSeekCur ; break ;
case CELL_SEEK_END : seek_mode = vfsSeekEnd ; break ;
2012-11-15 00:39:56 +01:00
default :
2013-06-30 10:46:29 +02:00
sys_fs . Error ( fd , " Unknown seek whence! (%d) " , whence ) ;
2012-11-15 00:39:56 +01:00
return CELL_EINVAL ;
}
2013-06-30 10:46:29 +02:00
ID id ;
if ( ! sys_fs . CheckId ( fd , id ) ) return CELL_ESRCH ;
vfsStream & file = * ( vfsStream * ) id . m_data ;
2013-09-24 23:11:29 +02:00
pos = file . Seek ( offset , seek_mode ) ;
2013-09-18 23:50:00 +02:00
return CELL_OK ;
}
int cellFsFtruncate ( u32 fd , u64 size )
{
sys_fs . Log ( " cellFsFtruncate(fd: %d, size: %lld) " , fd , size ) ;
ID id ;
if ( ! sys_fs . CheckId ( fd , id ) ) return CELL_ESRCH ;
vfsStream & file = * ( vfsStream * ) id . m_data ;
u64 initialSize = file . GetSize ( ) ;
2013-10-06 16:15:04 +02:00
if ( initialSize < size )
2013-09-18 23:50:00 +02:00
{
u64 last_pos = file . Tell ( ) ;
file . Seek ( 0 , vfsSeekEnd ) ;
2013-10-06 16:15:04 +02:00
static const char nullbyte = 0 ;
file . Seek ( size - initialSize - 1 , vfsSeekCur ) ;
file . Write ( & nullbyte , sizeof ( char ) ) ;
2013-09-18 23:50:00 +02:00
file . Seek ( last_pos , vfsSeekSet ) ;
}
if ( initialSize > size )
{
// (TODO)
}
return CELL_OK ;
}
int cellFsTruncate ( u32 path_addr , u64 size )
{
const wxString & path = Memory . ReadString ( path_addr ) ;
2013-11-19 11:30:58 +01:00
sys_fs . Log ( " cellFsTruncate(path: %s, size: %lld) " , path . mb_str ( ) , size ) ;
2013-09-18 23:50:00 +02:00
2013-10-06 16:15:04 +02:00
vfsFile f ( path , vfsReadWrite ) ;
if ( ! f . IsOpened ( ) )
2013-09-18 23:50:00 +02:00
{
2013-11-19 11:30:58 +01:00
sys_fs . Warning ( " cellFsTruncate: '%s' not found. " , path . mb_str ( ) ) ;
2013-09-18 23:50:00 +02:00
return CELL_ENOENT ;
}
2013-10-06 16:15:04 +02:00
u64 initialSize = f . GetSize ( ) ;
2013-09-18 23:50:00 +02:00
2013-10-06 16:15:04 +02:00
if ( initialSize < size )
2013-09-18 23:50:00 +02:00
{
2013-10-06 16:15:04 +02:00
u64 last_pos = f . Tell ( ) ;
f . Seek ( 0 , vfsSeekEnd ) ;
static const char nullbyte = 0 ;
f . Seek ( size - initialSize - 1 , vfsSeekCur ) ;
f . Write ( & nullbyte , sizeof ( char ) ) ;
f . Seek ( last_pos , vfsSeekSet ) ;
2013-09-18 23:50:00 +02:00
}
if ( initialSize > size )
{
// (TODO)
}
return CELL_OK ;
}
2013-09-24 23:11:29 +02:00
int cellFsFGetBlockSize ( u32 fd , mem64_t sector_size , mem64_t block_size )
2013-09-18 23:50:00 +02:00
{
2013-09-24 23:11:29 +02:00
sys_fs . Log ( " cellFsFGetBlockSize(fd: %d, sector_size_addr: 0x%x, block_size_addr: 0x%x) " , fd , sector_size . GetAddr ( ) , block_size . GetAddr ( ) ) ;
2013-09-18 23:50:00 +02:00
2013-09-24 23:11:29 +02:00
sector_size = 4096 ; // ?
block_size = 4096 ; // ?
2013-09-18 23:50:00 +02:00
2012-11-15 00:39:56 +01:00
return CELL_OK ;
2013-11-19 11:30:58 +01:00
}