sys_fs: Implement ENOTDIR
This commit is contained in:
@@ -166,6 +166,7 @@ static fs::error to_error(int e)
|
|||||||
case ENOTEMPTY: return fs::error::notempty;
|
case ENOTEMPTY: return fs::error::notempty;
|
||||||
case EROFS: return fs::error::readonly;
|
case EROFS: return fs::error::readonly;
|
||||||
case EISDIR: return fs::error::isdir;
|
case EISDIR: return fs::error::isdir;
|
||||||
|
case ENOTDIR: return fs::error::notdir;
|
||||||
case ENOSPC: return fs::error::nospace;
|
case ENOSPC: return fs::error::nospace;
|
||||||
case EXDEV: return fs::error::xdev;
|
case EXDEV: return fs::error::xdev;
|
||||||
default: return fs::error::unknown;
|
default: return fs::error::unknown;
|
||||||
@@ -2833,6 +2834,7 @@ void fmt_class_string<fs::error>::format(std::string& out, u64 arg)
|
|||||||
case fs::error::notempty: return "Not empty";
|
case fs::error::notempty: return "Not empty";
|
||||||
case fs::error::readonly: return "Read only";
|
case fs::error::readonly: return "Read only";
|
||||||
case fs::error::isdir: return "Is a directory";
|
case fs::error::isdir: return "Is a directory";
|
||||||
|
case fs::error::notdir: return "Not a directory";
|
||||||
case fs::error::toolong: return "Path too long";
|
case fs::error::toolong: return "Path too long";
|
||||||
case fs::error::nospace: return "Not enough space on the device";
|
case fs::error::nospace: return "Not enough space on the device";
|
||||||
case fs::error::xdev: return "Device mismatch";
|
case fs::error::xdev: return "Device mismatch";
|
||||||
|
|||||||
@@ -683,6 +683,7 @@ namespace fs
|
|||||||
notempty,
|
notempty,
|
||||||
readonly,
|
readonly,
|
||||||
isdir,
|
isdir,
|
||||||
|
notdir,
|
||||||
toolong,
|
toolong,
|
||||||
nospace,
|
nospace,
|
||||||
xdev,
|
xdev,
|
||||||
|
|||||||
+145
-11
@@ -140,6 +140,32 @@ bool verify_mself(const fs::file& mself_file)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: May not be thread-safe (or even, process-safe)
|
||||||
|
bool has_non_directory_components(std::string_view path)
|
||||||
|
{
|
||||||
|
std::string path0{path};
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const std::string sub_path = fs::get_parent_dir(path0);
|
||||||
|
|
||||||
|
if (sub_path.size() >= path0.size())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::stat_t stat{};
|
||||||
|
if (fs::get_stat(sub_path, stat))
|
||||||
|
{
|
||||||
|
return !stat.is_directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
path0 = std::move(sub_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
lv2_fs_mount_info_map::lv2_fs_mount_info_map()
|
lv2_fs_mount_info_map::lv2_fs_mount_info_map()
|
||||||
{
|
{
|
||||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next) // Scan and keep track of pre-mounted devices
|
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next) // Scan and keep track of pre-mounted devices
|
||||||
@@ -899,8 +925,17 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string& local_path, s3
|
|||||||
|
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir: return {CELL_ENOTDIR};
|
||||||
case fs::error::noent: return {CELL_ENOENT};
|
case fs::error::noent: return {CELL_ENOENT};
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return {CELL_ENOTDIR};
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1372,6 +1407,11 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
fmt::throw_exception("unknown error %s", error);
|
fmt::throw_exception("unknown error %s", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1555,6 +1595,10 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat>
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir:
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path};
|
||||||
|
}
|
||||||
case fs::error::noent:
|
case fs::error::noent:
|
||||||
{
|
{
|
||||||
// Try to analyse split file (TODO)
|
// Try to analyse split file (TODO)
|
||||||
@@ -1594,6 +1638,11 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat>
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
fmt::throw_exception("unknown error %s", error);
|
fmt::throw_exception("unknown error %s", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1720,6 +1769,10 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir:
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path};
|
||||||
|
}
|
||||||
case fs::error::noent:
|
case fs::error::noent:
|
||||||
{
|
{
|
||||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||||
@@ -1728,7 +1781,15 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
|||||||
{
|
{
|
||||||
return {sys_fs.warning, CELL_EEXIST, path};
|
return {sys_fs.warning, CELL_EEXIST, path};
|
||||||
}
|
}
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1789,9 +1850,18 @@ error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir: return {CELL_ENOTDIR, from};
|
||||||
case fs::error::noent: return {CELL_ENOENT, from};
|
case fs::error::noent: return {CELL_ENOENT, from};
|
||||||
case fs::error::exist: return {CELL_EEXIST, to};
|
case fs::error::exist: return {CELL_EEXIST, to};
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_from))
|
||||||
|
{
|
||||||
|
return {CELL_ENOTDIR, from};
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1842,9 +1912,18 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir: return {CELL_ENOTDIR, path};
|
||||||
case fs::error::noent: return {CELL_ENOENT, path};
|
case fs::error::noent: return {CELL_ENOENT, path};
|
||||||
case fs::error::notempty: return {CELL_ENOTEMPTY, path};
|
case fs::error::notempty: return {CELL_ENOTEMPTY, path};
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1896,11 +1975,23 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir:
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
case fs::error::noent:
|
case fs::error::noent:
|
||||||
{
|
{
|
||||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||||
}
|
}
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2737,7 +2828,15 @@ error_code sys_fs_get_block_size(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u
|
|||||||
{
|
{
|
||||||
case fs::error::exist: return {CELL_EISDIR, path};
|
case fs::error::exist: return {CELL_EISDIR, path};
|
||||||
case fs::error::noent: return {CELL_ENOENT, path};
|
case fs::error::noent: return {CELL_ENOENT, path};
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2789,11 +2888,23 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir:
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path};
|
||||||
|
}
|
||||||
case fs::error::noent:
|
case fs::error::noent:
|
||||||
{
|
{
|
||||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||||
}
|
}
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2840,7 +2951,10 @@ error_code sys_fs_ftruncate(ppu_thread& ppu, u32 fd, u64 size)
|
|||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
case fs::error::ok:
|
case fs::error::ok:
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2887,6 +3001,10 @@ error_code sys_fs_chmod(ppu_thread&, vm::cptr<char> path, s32 mode)
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir:
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path};
|
||||||
|
}
|
||||||
case fs::error::noent:
|
case fs::error::noent:
|
||||||
{
|
{
|
||||||
// Try to locate split files
|
// Try to locate split files
|
||||||
@@ -2900,8 +3018,12 @@ error_code sys_fs_chmod(ppu_thread&, vm::cptr<char> path, s32 mode)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
sys_fs.error("sys_fs_chmod(): unknown error %s", error);
|
if (has_non_directory_components(local_path))
|
||||||
return {CELL_EIO, path};
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3033,11 +3155,23 @@ error_code sys_fs_utime(ppu_thread& ppu, vm::cptr<char> path, vm::cptr<CellFsUti
|
|||||||
{
|
{
|
||||||
switch (auto error = fs::g_tls_error)
|
switch (auto error = fs::g_tls_error)
|
||||||
{
|
{
|
||||||
|
case fs::error::notdir:
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path};
|
||||||
|
}
|
||||||
case fs::error::noent:
|
case fs::error::noent:
|
||||||
{
|
{
|
||||||
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
return {mp == &g_mp_sys_dev_hdd1 ? sys_fs.warning : sys_fs.error, CELL_ENOENT, path};
|
||||||
}
|
}
|
||||||
default: fmt::throw_exception("unknown error %s", error);
|
default:
|
||||||
|
{
|
||||||
|
if (has_non_directory_components(local_path))
|
||||||
|
{
|
||||||
|
return { CELL_ENOTDIR, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("unknown error %s", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -585,10 +585,8 @@ std::unique_ptr<fs::dir_base> iso_device::open_dir(const std::string& path)
|
|||||||
|
|
||||||
if (!node->metadata.is_directory)
|
if (!node->metadata.is_directory)
|
||||||
{
|
{
|
||||||
// fs::dir::open -> ::readdir should return ENOTDIR when path is
|
// fs::dir::open -> ::readdir should return ENOTDIR when path is pointing to a file instead of a folder.
|
||||||
// pointing to a file instead of a folder, which translates to error::unknown.
|
fs::g_tls_error = fs::error::notdir;
|
||||||
// doing the same here.
|
|
||||||
fs::g_tls_error = fs::error::unknown;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user