sys_fs: Fix O_CREATE and O_TRUNC for BDVD
This commit is contained in:
@@ -861,7 +861,7 @@ error_code sys_fs_test(ppu_thread&, u32 arg1, u32 arg2, vm::ptr<u32> arg3, u32 a
|
|||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_info& mp)
|
lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s32 flags, bool has_write_access, lv2_file_type type, const lv2_fs_mount_info& mp)
|
||||||
{
|
{
|
||||||
// TODO: other checks for path
|
// TODO: other checks for path
|
||||||
|
|
||||||
@@ -888,7 +888,7 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & CELL_FS_O_CREAT)
|
if (flags & CELL_FS_O_CREAT && !mp.read_only)
|
||||||
{
|
{
|
||||||
open_mode += fs::create;
|
open_mode += fs::create;
|
||||||
|
|
||||||
@@ -898,7 +898,7 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & CELL_FS_O_TRUNC)
|
if (flags & CELL_FS_O_TRUNC && !mp.read_only)
|
||||||
{
|
{
|
||||||
open_mode += fs::trunc;
|
open_mode += fs::trunc;
|
||||||
}
|
}
|
||||||
@@ -906,6 +906,7 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
if (flags & CELL_FS_O_MSELF)
|
if (flags & CELL_FS_O_MSELF)
|
||||||
{
|
{
|
||||||
open_mode = fs::read;
|
open_mode = fs::read;
|
||||||
|
|
||||||
// mself can be mself or mself | rdonly
|
// mself can be mself or mself | rdonly
|
||||||
if (flags & ~(CELL_FS_O_MSELF | CELL_FS_O_RDONLY))
|
if (flags & ~(CELL_FS_O_MSELF | CELL_FS_O_RDONLY))
|
||||||
{
|
{
|
||||||
@@ -918,7 +919,7 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
sys_fs.warning("lv2_file::open() called with CELL_FS_O_UNK flag enabled. FLAGS: %#o", flags);
|
sys_fs.warning("lv2_file::open() called with CELL_FS_O_UNK flag enabled. FLAGS: %#o", flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mp.read_only)
|
if (mp.read_only || !has_write_access)
|
||||||
{
|
{
|
||||||
// Deactivate mutating flags on read-only FS
|
// Deactivate mutating flags on read-only FS
|
||||||
open_mode = fs::read;
|
open_mode = fs::read;
|
||||||
@@ -970,12 +971,12 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
if (mp.read_only)
|
if (mp.read_only || !has_write_access)
|
||||||
{
|
{
|
||||||
// Failed to create file on read-only FS (file doesn't exist)
|
// Failed to create file on read-only FS (file doesn't exist)
|
||||||
if (flags & CELL_FS_O_ACCMODE && flags & CELL_FS_O_CREAT)
|
if (flags & CELL_FS_O_CREAT)
|
||||||
{
|
{
|
||||||
return {CELL_EPERM};
|
return {mp.read_only ? CELL_EPERM : CELL_EACCES};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,6 +989,7 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
{
|
{
|
||||||
case fs::error::notdir: return {CELL_ENOTDIR};
|
case fs::error::notdir: return {CELL_ENOTDIR};
|
||||||
case fs::error::noent: return {CELL_ENOENT};
|
case fs::error::noent: return {CELL_ENOENT};
|
||||||
|
case fs::error::isdir: return {CELL_EISDIR};
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (has_non_directory_components(local_path))
|
if (has_non_directory_components(local_path))
|
||||||
@@ -1000,6 +1002,11 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & CELL_FS_O_TRUNC && (mp.read_only || !has_write_access))
|
||||||
|
{
|
||||||
|
return {mp.read_only ? CELL_EPERM : CELL_EACCES};
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & CELL_FS_O_MSELF && !verify_mself(file))
|
if (flags & CELL_FS_O_MSELF && !verify_mself(file))
|
||||||
{
|
{
|
||||||
return {CELL_ENOTMSELF};
|
return {CELL_ENOTMSELF};
|
||||||
@@ -1113,11 +1120,6 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
|
|||||||
return {CELL_ENOTMOUNTED, path};
|
return {CELL_ENOTMOUNTED, path};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & CELL_FS_O_CREAT && !has_fs_write_rights(vpath) && !fs::is_dir(local_path))
|
|
||||||
{
|
|
||||||
return {CELL_EACCES};
|
|
||||||
}
|
|
||||||
|
|
||||||
lv2_file_type type = lv2_file_type::regular;
|
lv2_file_type type = lv2_file_type::regular;
|
||||||
|
|
||||||
if (size == 8)
|
if (size == 8)
|
||||||
@@ -1132,7 +1134,7 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [error, file] = open_raw(local_path, flags, mode, type, mp);
|
auto [error, file] = open_raw(local_path, flags, has_fs_write_rights(vpath), type, mp);
|
||||||
|
|
||||||
return {.error = error, .ppath = std::move(path), .real_path = std::move(local_path), .file = std::move(file), .type = type};
|
return {.error = error, .ppath = std::move(path), .real_path = std::move(local_path), .file = std::move(file), .type = type};
|
||||||
}
|
}
|
||||||
@@ -1823,13 +1825,13 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
|||||||
return {CELL_EROFS, path};
|
return {CELL_EROFS, path};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard lock(mp->mutex);
|
||||||
|
|
||||||
if (!fs::exists(local_path) && !has_fs_write_rights(path.get_ptr()))
|
if (!fs::exists(local_path) && !has_fs_write_rights(path.get_ptr()))
|
||||||
{
|
{
|
||||||
return {CELL_EACCES, path};
|
return {CELL_EACCES, path};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard lock(mp->mutex);
|
|
||||||
|
|
||||||
if (!fs::create_dir(local_path))
|
if (!fs::create_dir(local_path))
|
||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
@@ -1953,26 +1955,26 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
|||||||
|
|
||||||
if (mp == &g_mp_sys_dev_root)
|
if (mp == &g_mp_sys_dev_root)
|
||||||
{
|
{
|
||||||
return {CELL_EPERM, path};
|
return {CELL_EPERM, vpath};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_path.empty())
|
if (local_path.empty())
|
||||||
{
|
{
|
||||||
return {CELL_ENOTMOUNTED, path};
|
return {CELL_ENOTMOUNTED, vpath};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mp.read_only)
|
if (mp.read_only)
|
||||||
{
|
{
|
||||||
return {CELL_EROFS, path};
|
return {CELL_EROFS, vpath};
|
||||||
}
|
|
||||||
|
|
||||||
if (fs::is_dir(local_path) && !has_fs_write_rights(path.get_ptr()))
|
|
||||||
{
|
|
||||||
return {CELL_EACCES};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard lock(mp->mutex);
|
std::lock_guard lock(mp->mutex);
|
||||||
|
|
||||||
|
if (fs::is_dir(local_path) && !has_fs_write_rights(vpath))
|
||||||
|
{
|
||||||
|
return {CELL_EACCES, vpath};
|
||||||
|
}
|
||||||
|
|
||||||
if (!fs::remove_dir(local_path))
|
if (!fs::remove_dir(local_path))
|
||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
@@ -1984,7 +1986,7 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
|||||||
{
|
{
|
||||||
if (has_non_directory_components(local_path))
|
if (has_non_directory_components(local_path))
|
||||||
{
|
{
|
||||||
return { CELL_ENOTDIR, path };
|
return { CELL_ENOTDIR, vpath };
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::throw_exception("unknown error %s", error);
|
fmt::throw_exception("unknown error %s", error);
|
||||||
@@ -1992,7 +1994,7 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_fs.notice("sys_fs_rmdir(): directory %s removed", path);
|
sys_fs.notice("sys_fs_rmdir(): directory %s removed", vpath);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ struct lv2_file final : lv2_fs_object
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Open a file with wrapped logic of sys_fs_open
|
// Open a file with wrapped logic of sys_fs_open
|
||||||
static open_raw_result_t open_raw(const std::string& path, s32 flags, s32 mode, lv2_file_type type = lv2_file_type::regular, const lv2_fs_mount_info& mp = g_mi_sys_not_found);
|
static open_raw_result_t open_raw(const std::string& path, s32 flags, bool has_write_access, lv2_file_type type = lv2_file_type::regular, const lv2_fs_mount_info& mp = g_mi_sys_not_found);
|
||||||
static open_result_t open(std::string_view vpath, s32 flags, s32 mode, const void* arg = {}, u64 size = 0);
|
static open_result_t open(std::string_view vpath, s32 flags, s32 mode, const void* arg = {}, u64 size = 0);
|
||||||
|
|
||||||
// File reading with intermediate buffer
|
// File reading with intermediate buffer
|
||||||
|
|||||||
+1
-1
@@ -1028,7 +1028,7 @@ bool vfs::host::rename(const std::string& from, const std::string& to, const lv2
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reopen with ignored TRUNC, APPEND, CREATE and EXCL flags
|
// Reopen with ignored TRUNC, APPEND, CREATE and EXCL flags
|
||||||
auto res0 = lv2_file::open_raw(file.real_path, file.flags & CELL_FS_O_ACCMODE, file.mode, file.type, file.mp);
|
auto res0 = lv2_file::open_raw(file.real_path, file.flags & CELL_FS_O_ACCMODE, true, file.type, file.mp);
|
||||||
file.file = std::move(res0.file);
|
file.file = std::move(res0.file);
|
||||||
ensure(file.file.operator bool());
|
ensure(file.file.operator bool());
|
||||||
file.file.seek(file.restore_data.seek_pos);
|
file.file.seek(file.restore_data.seek_pos);
|
||||||
|
|||||||
Reference in New Issue
Block a user