Win32 FS: Rewrite (fix) vfs::host::rename

This commit is contained in:
Eladash 2020-09-11 14:06:46 +03:00 committed by Ivan
parent 22269ca0d7
commit b8fa6fb4c4
16 changed files with 329 additions and 108 deletions

View file

@ -230,33 +230,13 @@ error_code sys_fs_test(ppu_thread& ppu, u32 arg1, u32 arg2, vm::ptr<u32> arg3, u
return CELL_OK;
}
lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mode, const void* arg, u64 size)
lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s32 flags, s32 mode, lv2_file_type type, const lv2_fs_mount_point* mp)
{
if (vpath.empty())
{
return {CELL_ENOENT};
}
std::string path;
const std::string local_path = vfs::get(vpath, nullptr, &path);
const auto mp = lv2_fs_object::get_mp(path);
if (vpath.find_first_not_of('/') == umax)
{
return {CELL_EISDIR, path};
}
if (local_path.empty())
{
return {CELL_ENOTMOUNTED, path};
}
// TODO: other checks for path
if (fs::is_dir(local_path))
{
return {CELL_EISDIR, path};
return {CELL_EISDIR};
}
bs_t<fs::open_mode> open_mode{};
@ -272,7 +252,7 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
{
if (flags & CELL_FS_O_ACCMODE || flags & (CELL_FS_O_CREAT | CELL_FS_O_TRUNC))
{
return {CELL_EPERM, path};
return {CELL_EPERM};
}
}
@ -326,14 +306,12 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
if (!open_mode)
{
fmt::throw_exception("lv2_file::open(%s): Invalid or unimplemented flags: %#o" HERE, path, flags);
fmt::throw_exception("lv2_file::open_raw(): Invalid or unimplemented flags: %#o" HERE, flags);
}
fs::file file;
{
std::lock_guard lock(mp->mutex);
file.open(local_path, open_mode);
}
std::lock_guard lock(mp->mutex);
fs::file file(local_path, open_mode);
if (!file && open_mode == fs::read && fs::g_tls_error == fs::error::noent)
{
@ -365,7 +343,7 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
// Failed to create file on read-only FS (file doesn't exist)
if (flags & CELL_FS_O_CREAT)
{
return {CELL_EROFS, path};
return {CELL_EROFS};
}
}
@ -376,11 +354,11 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
switch (auto error = fs::g_tls_error)
{
case fs::error::noent: return {CELL_ENOENT, path};
case fs::error::noent: return {CELL_ENOENT};
default: sys_fs.error("lv2_file::open(): unknown error %s", error);
}
return {CELL_EIO, path};
return {CELL_EIO};
}
if (mp->flags & lv2_mp_flag::read_only)
@ -388,27 +366,27 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
// Failed to create file on read-only FS (file exists)
if (flags & CELL_FS_O_CREAT && flags & CELL_FS_O_EXCL)
{
return {CELL_EEXIST, path};
return {CELL_EEXIST};
}
// Failed to truncate file on read-only FS
if (flags & CELL_FS_O_TRUNC)
{
return {CELL_EROFS, path};
return {CELL_EROFS};
}
}
if (flags & CELL_FS_O_MSELF && !verify_mself(file))
{
return {CELL_ENOTMSELF, path};
return {CELL_ENOTMSELF};
}
if (size == 8)
if (type >= lv2_file_type::sdata)
{
// check for sdata
switch (*static_cast<const be_t<u64>*>(arg))
switch (type)
{
case 0x18000000010:
case lv2_file_type::sdata:
{
// check if the file has the NPD header, or else assume its not encrypted
u32 magic;
@ -419,7 +397,7 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
auto sdata_file = std::make_unique<EDATADecrypter>(std::move(file));
if (!sdata_file->ReadHeader())
{
return {CELL_EFSSPECIFIC, path};
return {CELL_EFSSPECIFIC};
}
file.reset(std::move(sdata_file));
@ -428,7 +406,7 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
break;
}
// edata
case 0x2:
case lv2_file_type::edata:
{
// check if the file has the NPD header, or else assume its not encrypted
u32 magic;
@ -440,7 +418,7 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
auto sdata_file = std::make_unique<EDATADecrypter>(std::move(file), edatkeys->devKlic.load(), edatkeys->rifKey.load());
if (!sdata_file->ReadHeader())
{
return {CELL_EFSSPECIFIC, path};
return {CELL_EFSSPECIFIC};
}
file.reset(std::move(sdata_file));
@ -452,7 +430,49 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
}
}
return {.error = {}, .ppath = path, .file = std::move(file)};
return {.error = {}, .file = std::move(file)};
}
lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mode, const void* arg, u64 size)
{
if (vpath.empty())
{
return {CELL_ENOENT};
}
std::string path;
const std::string local_path = vfs::get(vpath, nullptr, &path);
const auto mp = lv2_fs_object::get_mp(path);
if (vpath.find_first_not_of('/') == umax)
{
return {CELL_EISDIR, path};
}
if (local_path.empty())
{
return {CELL_ENOTMOUNTED, path};
}
lv2_file_type type = lv2_file_type::regular;
if (size == 8)
{
// see lv2_file::open_raw
switch (*static_cast<const be_t<u64>*>(arg))
{
case 0x18000000010: type = lv2_file_type::sdata; break;
case 0x2: type = lv2_file_type::edata; break;
default:
break;
}
}
auto [error, file] = open_raw(local_path, flags, mode, type, mp);
return {.error = error, .ppath = std::move(path), .real_path = std::move(local_path), .file = std::move(file), .type = type};
}
error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode, vm::cptr<void> arg, u64 size)
@ -464,7 +484,7 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
if (!path)
return CELL_EFAULT;
auto [error, ppath, file] = lv2_file::open(path.get_ptr(), flags, mode, arg.get_ptr(), size);
auto [error, ppath, real, file, type] = lv2_file::open(path.get_ptr(), flags, mode, arg.get_ptr(), size);
if (error)
{
@ -476,42 +496,25 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
return {error, path};
}
lv2_file_type type = lv2_file_type::regular;
if (size == 8)
if (type >= lv2_file_type::sdata)
{
// see lv2_file::open
switch (vm::read64(arg.addr()))
{
case 0x18000000010:
case 0x2:
{
type = lv2_file_type::npdrm;
sys_fs.warning("sys_fs_open(): NPDRM detected");
break;
}
default:
break;
}
}
sys_fs.warning("sys_fs_open(): NPDRM detected");
if (type == lv2_file_type::npdrm)
{
if (const u32 id = idm::import<lv2_fs_object, lv2_file>([&ppath = ppath, &file = file, mode, flags]() -> std::shared_ptr<lv2_file>
if (const u32 id = idm::import<lv2_fs_object, lv2_file>([&ppath = ppath, &file = file, mode, flags, &real = real, &type = type]() -> std::shared_ptr<lv2_file>
{
if (!g_fxo->get<loaded_npdrm_keys>()->npdrm_fds.try_inc(16))
{
return nullptr;
}
return std::make_shared<lv2_file>(ppath, std::move(file), mode, flags, lv2_file_type::npdrm);
return std::make_shared<lv2_file>(ppath, std::move(file), mode, flags, real, type);
}))
{
*fd = id;
return CELL_OK;
}
}
else if (const u32 id = idm::make<lv2_fs_object, lv2_file>(ppath, std::move(file), mode, flags))
else if (const u32 id = idm::make<lv2_fs_object, lv2_file>(ppath, std::move(file), mode, flags, real))
{
*fd = id;
return CELL_OK;
@ -622,7 +625,7 @@ error_code sys_fs_close(ppu_thread& ppu, u32 fd)
const auto file = idm::withdraw<lv2_fs_object, lv2_file>(fd, [](lv2_file& file)
{
if (file.type == lv2_file_type::npdrm)
if (file.type >= lv2_file_type::sdata)
{
g_fxo->get<loaded_npdrm_keys>()->npdrm_fds--;
}
@ -674,11 +677,9 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
return {CELL_ENOTDIR, path};
}
fs::dir dir;
{
std::lock_guard lock(mp->mutex);
dir.open(local_path);
}
std::lock_guard lock(mp->mutex);
fs::dir dir(local_path);
if (!dir)
{
@ -1029,9 +1030,10 @@ error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to
return CELL_EROFS;
}
std::lock_guard lock(mp->mutex);
// Done in vfs::host::rename
//std::lock_guard lock(mp->mutex);
if (!vfs::host::rename(local_from, local_to, false))
if (!vfs::host::rename(local_from, local_to, mp, false))
{
switch (auto error = fs::g_tls_error)
{
@ -1266,6 +1268,8 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
return CELL_EBADF;
}
std::lock_guard lock(file->mp->mutex);
auto sdata_file = std::make_unique<EDATADecrypter>(lv2_file::make_view(file, arg->offset));
if (!sdata_file->ReadHeader())
@ -1282,7 +1286,7 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
return nullptr;
}
return std::make_shared<lv2_file>(file, std::move(stream), file.mode, file.flags, lv2_file_type::npdrm);
return std::make_shared<lv2_file>(file, std::move(stream), file.mode, file.flags, file.real_path, lv2_file_type::sdata);
}))
{
arg->out_code = CELL_OK;