Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libfs.sprx enabled #2722

Merged
merged 14 commits into from
Apr 26, 2017
65 changes: 60 additions & 5 deletions Utilities/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static fs::error to_error(DWORD e)
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/statvfs.h>
#include <dirent.h>
#include <fcntl.h>
#include <libgen.h>
Expand Down Expand Up @@ -156,6 +157,16 @@ namespace fs
{
}

stat_t file_base::stat()
{
fmt::throw_exception("fs::file::stat() not supported for %s", typeid(*this).name());
}

void file_base::sync()
{
// Do notning
}

dir_base::~dir_base()
{
}
Expand Down Expand Up @@ -393,6 +404,45 @@ bool fs::is_dir(const std::string& path)
return true;
}

bool fs::statfs(const std::string& path, fs::device_stat& info)
{
if (auto device = get_virtual_device(path))
{
return device->statfs(path, info);
}

#ifdef _WIN32
ULARGE_INTEGER avail_free;
ULARGE_INTEGER total_size;
ULARGE_INTEGER total_free;

if (!GetDiskFreeSpaceExW(to_wchar(path).get(), &avail_free, &total_size, &total_free))
{
g_tls_error = to_error(GetLastError());
return false;
}

info.block_size = 4096; // TODO
info.total_size = total_size.QuadPart;
info.total_free = total_free.QuadPart;
info.avail_free = avail_free.QuadPart;
#else
struct ::statvfs buf;
if (!::statvfs(path.c_str(), &buf) != 0)
{
g_tls_error = to_error(errno);
return false;
}

info.block_size = buf.f_frsize;
info.total_size = info.block_size * buf.f_blocks;
info.total_free = info.block_size * buf.f_bfree;
info.avail_free = info.block_size * buf.f_bavail;
#endif

return true;
}

bool fs::create_dir(const std::string& path)
{
if (auto device = get_virtual_device(path))
Expand Down Expand Up @@ -745,6 +795,11 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return info;
}

void sync() override
{
verify("file::sync" HERE), FlushFileBuffers(m_handle);
}

bool trunc(u64 length) override
{
LARGE_INTEGER old, pos;
Expand Down Expand Up @@ -870,6 +925,11 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return info;
}

void sync() override
{
verify("file::sync" HERE), ::fsync(m_fd) == 0;
}

bool trunc(u64 length) override
{
if (::ftruncate(m_fd, length) != 0)
Expand Down Expand Up @@ -945,11 +1005,6 @@ fs::file::file(const void* ptr, std::size_t size)
{
}

fs::stat_t stat() override
{
fmt::raw_error("fs::file::memory_stream::stat(): not supported");
}

bool trunc(u64 length) override
{
return false;
Expand Down
28 changes: 22 additions & 6 deletions Utilities/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ namespace fs
{
virtual ~file_base();

virtual stat_t stat() = 0;
virtual stat_t stat();
virtual void sync();
virtual bool trunc(u64 length) = 0;
virtual u64 read(void* buffer, u64 size) = 0;
virtual u64 write(const void* buffer, u64 size) = 0;
Expand All @@ -83,12 +84,22 @@ namespace fs
virtual void rewind() = 0;
};

// Device information
struct device_stat
{
u64 block_size;
u64 total_size;
u64 total_free; // Total size of free space
u64 avail_free; // Free space available to unprivileged user
};

// Virtual device
struct device_base
{
virtual ~device_base();

virtual bool stat(const std::string& path, stat_t& info) = 0;
virtual bool statfs(const std::string& path, device_stat& info) = 0;
virtual bool remove_dir(const std::string& path) = 0;
virtual bool create_dir(const std::string& path) = 0;
virtual bool rename(const std::string& from, const std::string& to) = 0;
Expand Down Expand Up @@ -121,6 +132,9 @@ namespace fs
// Check whether the directory exists and is NOT a file
bool is_dir(const std::string& path);

// Get filesystem information
bool statfs(const std::string& path, device_stat& info);

// Delete empty directory
bool remove_dir(const std::string& path);

Expand Down Expand Up @@ -206,6 +220,13 @@ namespace fs
return m_file->stat();
}

// Sync file buffers
void sync() const
{
if (!m_file) xnull();
return m_file->sync();
}

// Read the data from the file and return the amount of data written in buffer
u64 read(void* buffer, u64 count) const
{
Expand Down Expand Up @@ -488,11 +509,6 @@ namespace fs
{
}

stat_t stat() override
{
fmt::raw_error("fs::container_stream<>::stat(): not supported");
}

bool trunc(u64 length) override
{
obj.resize(length);
Expand Down
81 changes: 36 additions & 45 deletions rpcs3/Emu/Cell/Modules/cellFs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,20 @@ s32 cellFsLseek(u32 fd, s64 offset, u32 whence, vm::ptr<u64> pos)
return sys_fs_lseek(fd, offset, whence, pos);
}

s32 cellFsFdatasync(u32 fd)
{
cellFs.trace("cellFsFdatasync(fd=%d)", fd);

// Call the syscall
return sys_fs_fdatasync(fd);
}

s32 cellFsFsync(u32 fd)
{
cellFs.todo("cellFsFsync(fd=0x%x)", fd);
cellFs.trace("cellFsFsync(fd=%d)", fd);

return CELL_OK;
// Call the syscall
return sys_fs_fsync(fd);
}

s32 cellFsFGetBlockSize(u32 fd, vm::ptr<u64> sector_size, vm::ptr<u64> block_size)
Expand All @@ -180,7 +189,7 @@ s32 cellFsFGetBlockSize(u32 fd, vm::ptr<u64> sector_size, vm::ptr<u64> block_siz
}

// call the syscall
return sys_fs_fget_block_size(fd, sector_size, block_size, vm::var<u64>{}, vm::var<u64>{});
return sys_fs_fget_block_size(fd, sector_size, block_size, vm::var<u64>{}, vm::var<s32>{});
}

s32 cellFsFGetBlockSize2()
Expand Down Expand Up @@ -251,58 +260,46 @@ s32 cellFsUtime(vm::cptr<char> path, vm::cptr<CellFsUtimbuf> timep)

s32 cellFsGetFreeSize(vm::cptr<char> path, vm::ptr<u32> block_size, vm::ptr<u64> block_count)
{
cellFs.warning("cellFsGetFreeSize(path=%s, block_size=*0x%x, block_count=*0x%x)", path, block_size, block_count);

// TODO: Get real values. Currently, it always returns 40 GB of free space divided in 4 KB blocks
*block_size = 4096; // ?
*block_count = 10 * 1024 * 1024; // ?
cellFs.todo("cellFsGetFreeSize(path=%s, block_size=*0x%x, block_count=*0x%x)", path, block_size, block_count);

fs::device_stat info;
fs::statfs(vfs::get(path.get_ptr()), info);
*block_size = 4096;
*block_count = info.avail_free / 4096;
return CELL_OK;
}

s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32 entries_size, vm::ptr<u32> data_count)
error_code cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32 entries_size, vm::ptr<u32> data_count)
{
cellFs.warning("cellFsGetDirectoryEntries(fd=%d, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count);
cellFs.trace("cellFsGetDirectoryEntries(fd=%d, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count);

const auto directory = idm::get<lv2_fs_object, lv2_dir>(fd);
if (!data_count || !entries)
{
return CELL_EFAULT;
}

if (!directory)
if (fd - 3 > 252)
{
return CELL_EBADF;
}

u32 count = 0;
vm::var<lv2_file_op_dir> op;

entries_size /= sizeof(CellFsDirectoryEntry);
op->_vtable = vm::cast(0xfae12000); // Intentionally wrong (provide correct vtable if necessary)

for (; count < entries_size; count++)
{
fs::dir_entry info;
op->op = 0xe0000012;
op->arg._code = 0;
op->arg._size = 0;
op->arg.ptr = entries;
op->arg.max = entries_size / sizeof(CellFsDirectoryEntry);

if (directory->dir.read(info))
{
entries[count].attribute.mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666;
entries[count].attribute.uid = 1; // ???
entries[count].attribute.gid = 1; // ???
entries[count].attribute.atime = info.atime;
entries[count].attribute.mtime = info.mtime;
entries[count].attribute.ctime = info.ctime;
entries[count].attribute.size = info.size;
entries[count].attribute.blksize = 4096; // ???

entries[count].entry_name.d_type = info.is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR;
entries[count].entry_name.d_namlen = u8(std::min<size_t>(info.name.size(), CELL_FS_MAX_FS_FILE_NAME_LENGTH));
strcpy_trunc(entries[count].entry_name.d_name, info.name);
}
else
{
break;
}
}
// Call the syscall
const s32 rc = sys_fs_fcntl(fd, 0xe0000012, op.ptr(&lv2_file_op_dir::arg), 0x10);

*data_count = count;
*data_count = op->arg._size;

return CELL_OK;
// Select the result
return not_an_error(rc ? rc : +op->arg._code);
}

error_code cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<u64> nread)
Expand Down Expand Up @@ -890,12 +887,6 @@ s32 cellFsFcntl()
return CELL_OK;
}

s32 cellFsFdatasync()
{
UNIMPLEMENTED_FUNC(cellFs);
return CELL_OK;
}

s32 cellFsLink()
{
UNIMPLEMENTED_FUNC(cellFs);
Expand Down
6 changes: 0 additions & 6 deletions rpcs3/Emu/Cell/Modules/cellFs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@

#include "Emu/Cell/lv2/sys_fs.h"

struct CellFsDirectoryEntry
{
CellFsStat attribute;
CellFsDirent entry_name;
};

// CellFsRingBuffer.copy
enum : s32
{
Expand Down
5 changes: 5 additions & 0 deletions rpcs3/Emu/Cell/PPUModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,11 @@ static void ppu_initialize_modules(const std::shared_ptr<ppu_linkage_info>& link
for (auto& module : registered)
{
LOG_TRACE(LOADER, "Registered static module: %s", module->name);
}

for (auto& pair : ppu_module_manager::get())
{
const auto module = pair.second;
auto& linkage = link->modules[module->name];

for (auto& function : module->functions)
Expand Down Expand Up @@ -1198,6 +1202,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
{ "cellSync2", "libsre.sprx" },
{ "cellVpost", "libvpost.sprx" },
{ "cellVpost", "libsre.sprx" },
{ "sys_fs", "libfs.sprx" },
};

// Expand dependencies
Expand Down
5 changes: 5 additions & 0 deletions rpcs3/Emu/Cell/PPUModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ class ppu_module_manager final
return info;
}

static const auto& get()
{
return access();
}

static const ppu_static_module cellAdec;
static const ppu_static_module cellAtrac;
static const ppu_static_module cellAtracMulti;
Expand Down
Loading