mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-30 12:25:49 +00:00
fix(libc): resolve the rename source before the destination argument
FreeBSD 11.4 kern_renameat looks up the source first (namei on fromnd), so a missing or dot source fails with ENOENT or EINVAL before the new name is touched. The guest call rejected a NULL, empty or dot destination first, so rename(missing, NULL) returned EFAULT and rename(missing, ".") returned EINVAL where FreeBSD returns ENOENT. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
1 parent
7602dde042
commit
308848e1a6
3 files changed
+25
-4
No files matched your search
@@ -94,13 +94,26 @@ static int RenamePath_nid_no_patch(const std::filesystem::path& source, const st
|
||||
return error ? FilesystemError(error) : 0;
|
||||
}
|
||||
|
||||
static int SourceLookupError_nid_no_patch(const std::filesystem::path& source) {
|
||||
std::error_code status;
|
||||
const auto sourceStatus = std::filesystem::symlink_status(source, status);
|
||||
if (HasNonDirectoryPrefix_nid_no_patch(source)) return 20;
|
||||
if (status && status != std::errc::no_such_file_or_directory) return FilesystemError(status);
|
||||
return sourceStatus.type() == std::filesystem::file_type::not_found ? 2 : 0;
|
||||
}
|
||||
|
||||
extern "C" int RenameGuestPath_nid_no_patch(const char* from, const char* to) {
|
||||
if (!from || !to) { errno = 14; return -1; }
|
||||
if (!*from || !*to) { errno = 2; return -1; }
|
||||
if (!from) { errno = 14; return -1; }
|
||||
if (!*from) { errno = 2; return -1; }
|
||||
if (const int dot = RenameDotError_nid_no_patch(from)) { errno = dot; return -1; }
|
||||
if (const int dot = RenameDotError_nid_no_patch(to)) { errno = dot; return -1; }
|
||||
const int destinationError = !to ? 14 : !*to ? 2 : RenameDotError_nid_no_patch(to);
|
||||
try {
|
||||
const auto source = ResolvePath_nid_no_patch(from);
|
||||
if (destinationError) {
|
||||
const int sourceError = SourceLookupError_nid_no_patch(source);
|
||||
errno = sourceError ? sourceError : destinationError;
|
||||
return -1;
|
||||
}
|
||||
const auto destination = ResolvePath_nid_no_patch(to);
|
||||
int error = RenamePath_nid_no_patch(source, destination);
|
||||
if (error == 2) {
|
||||
|
||||
@@ -1379,7 +1379,7 @@ int64_t APS5_VABI pwritev_nid_postfix(int d, const KernelIovec* iov, int iovcnt,
|
||||
}
|
||||
|
||||
int APS5_VABI sceKernelRename(const char* from, const char* to) {
|
||||
if (!from || !to) return SceErrorFromErrno(GUEST_EFAULT);
|
||||
if (!from) return SceErrorFromErrno(GUEST_EFAULT);
|
||||
const int result = RenameGuestPath_nid_no_patch(from, to);
|
||||
return result == 0 ? 0 : SceKernelError(errno);
|
||||
if (const int dot = RenameDotError_nid_no_patch(from)) return SceKernelError(dot);
|
||||
|
||||
@@ -856,6 +856,14 @@ int main() {
|
||||
Require(sceKernelCheckReachability("") == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelRename("", presentName.c_str()) == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelRename(presentName.c_str(), "") == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelRename(missingName.c_str(), nullptr) == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelRename("", nullptr) == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelRename(".", nullptr) == static_cast<int>(0x80020016u));
|
||||
Require(sceKernelRename(missingName.c_str(), ".") == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelRename(presentName.c_str(), nullptr) == static_cast<int>(0x8002000Eu));
|
||||
Require(sceKernelRename(nullptr, presentName.c_str()) == static_cast<int>(0x8002000Eu));
|
||||
Require(rename_nid_postfix(missingName.c_str(), nullptr) == -1 && *__error_nid_postfix() == 2);
|
||||
Require(rename_nid_postfix(presentName.c_str(), nullptr) == -1 && *__error_nid_postfix() == 14);
|
||||
Require(sceKernelRmdir("") == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelMkdir("", 0700) == static_cast<int>(0x80020002u));
|
||||
const auto cwdPermissions = std::filesystem::status(".").permissions();
|
||||
|
||||
Reference in new issue
Block a user