Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/libs/prx/libkernel/File/src/Stdio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1669,7 +1669,7 @@ int APS5_VABI lutimes_nid_postfix(const char* path, const KernelTimeval* times)
path = copy.c_str();
std::filesystem::path native;
if (const int error = ResolvePathError_nid_no_patch(path, native)) return PosixFailure(error);
if (NativeUtimes(native, times, false) != 0) return PosixResult(SceErrorFromErrno(errno));
if (NativeUtimes(native, times, false) != 0) return PosixResult(SceErrorFromErrno(errno == ENOENT ? NotFoundError_nid_no_patch(native) : errno));
return 0;
}

Expand Down
37 changes: 37 additions & 0 deletions core/libs/tests/GuestFileTimestamps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,5 +257,42 @@ int main() {
Require(futimes_nid_postfix(pipe[0], first) == -1 && *__error_nid_postfix() == 22, "pipe timestamp update fails");
#endif
Require(close_nid_postfix(pipe[0]) == 0 && close_nid_postfix(pipe[1]) == 0, "close pipe");
const auto throughFile = (root / "file.txt" / "child").string();
for (const auto update : {utimes_nid_postfix, lutimes_nid_postfix}) {
Require(update(throughFile.c_str(), first) == -1 && *__error_nid_postfix() == 20, "a path through a file reports ENOTDIR");
}
#ifdef _WIN32
const auto fileLink = (root / "file-link.txt").string();
const auto directoryLink = (root / "directory-link").string();
const auto danglingLink = (root / "dangling-link").string();
const auto createLink = [](const std::string& link, const std::string& target, DWORD flags) {
wchar_t full[MAX_PATH];
GetFullPathNameW(std::filesystem::path(target).c_str(), MAX_PATH, full, nullptr);
return CreateSymbolicLinkW(std::filesystem::path(link).c_str(), full, flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) != 0;
};
if (createLink(fileLink, path, 0) && createLink(directoryLink, directory, SYMBOLIC_LINK_FLAG_DIRECTORY) &&
createLink(danglingLink, (root / "missing").string(), 0)) {
const auto modified = [](const char* name, bool link) {
FileStat status{};
Require((link ? lstat_nid_postfix(name, &status) : stat_nid_postfix(name, &status)) == 0, "stat a link fixture");
return status.st_mtim.tv_sec;
};
Require(utimes_nid_postfix(fileLink.c_str(), first) == 0 && modified(path.c_str(), false) == first[1].tv_sec, "utimes follows a file link");
Require(modified(fileLink.c_str(), true) != first[1].tv_sec, "utimes leaves the file link alone");
Require(utimes_nid_postfix(directoryLink.c_str(), second) == 0 && modified(directory.c_str(), false) == second[1].tv_sec,
"utimes follows a directory link");
Require(utimes_nid_postfix(danglingLink.c_str(), first) == -1 && *__error_nid_postfix() == 2, "utimes through a dangling link reports ENOENT");
Require(lutimes_nid_postfix(directoryLink.c_str(), first) == 0 && modified(directoryLink.c_str(), true) == first[1].tv_sec &&
modified(directory.c_str(), false) == second[1].tv_sec, "lutimes changes a directory link and not its target");
Require(lutimes_nid_postfix(danglingLink.c_str(), first) == 0 && modified(danglingLink.c_str(), true) == first[1].tv_sec,
"lutimes changes a dangling link");
const auto throughLink = fileLink + "/child";
for (const auto update : {utimes_nid_postfix, lutimes_nid_postfix}) {
Require(update(throughLink.c_str(), first) == -1 && *__error_nid_postfix() == 20, "a path through a file link reports ENOTDIR");
}
Require(RemoveDirectoryW(std::filesystem::path(directoryLink).c_str()) && DeleteFileW(std::filesystem::path(fileLink).c_str()) &&
DeleteFileW(std::filesystem::path(danglingLink).c_str()), "remove the link fixtures");
}
#endif
std::filesystem::remove_all(root);
}
Loading