Merge pull request #9469 from Gruzzberry/fix/chflags-dangling-link

fix(libkernel): fail chflags through a dangling Windows symbolic link with ENOENT
This commit is contained in:
Adrià authored and GitHub committed 2026-10-26 00:13:50 +01:00
commit efd368fec6
2 files changed
+30

No files matched your search

@@ -662,6 +662,15 @@ int File::DuplicateFrom(int fd, int start) {
}
static int LookupError(const std::filesystem::path& native) {
#ifdef _WIN32
const auto named = native.has_filename() ? native : WithoutTrailingSeparator(native);
const DWORD attributes = GetFileAttributesW(named.c_str());
if (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
FileStat target{};
if (!File::TryFillFileStat(named, &target)) return SceErrorFromErrno(errno) & 0xffff;
return native.has_filename() || (target.st_mode & 0170000) == 0040000 ? 0 : GUEST_ENOTDIR;
}
#endif
std::error_code error;
const auto status = std::filesystem::status(native, error);
if (std::filesystem::exists(status)) return native.has_filename() || std::filesystem::is_directory(status) ? 0 : GUEST_ENOTDIR;
+21
View File
@@ -634,6 +634,27 @@ int main() {
Require(chflags_nid_postfix(file.string().c_str(), 0x200000) == -1 && *__error_nid_postfix() == 1);
Require(ChflagsThrows(file, 0x2, "UF_IMMUTABLE"));
Require(ChflagsThrows(file, 0x1000 | 0x40000, "UF_READONLY|SF_APPEND"));
const auto chflagsDangling = root / "dangling.link";
const auto chflagsPointing = root / "file.link";
#ifdef _WIN32
const bool chflagsLinked = CreateSymbolicLinkW(chflagsDangling.wstring().c_str(), L"missing.bin", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) != 0 &&
CreateSymbolicLinkW(chflagsPointing.wstring().c_str(), L"file.txt", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) != 0;
#else
std::error_code chflagsLinkError;
std::filesystem::create_symlink("missing.bin", chflagsDangling, chflagsLinkError);
if (!chflagsLinkError) std::filesystem::create_symlink("file.txt", chflagsPointing, chflagsLinkError);
const bool chflagsLinked = !chflagsLinkError;
#endif
if (chflagsLinked) {
Require(chflags_nid_postfix(chflagsDangling.string().c_str(), 0) == -1 && *__error_nid_postfix() == 2);
Require(chflags_nid_postfix(chflagsPointing.string().c_str(), 0) == 0);
Require(chflags_nid_postfix((chflagsPointing.string() + "/").c_str(), 0) == -1 && *__error_nid_postfix() == 20);
Require(chflags_nid_postfix(chflagsPointing.string().c_str(), 0x20) == -1 && *__error_nid_postfix() == 45);
Require(unlink_nid_postfix(chflagsDangling.string().c_str()) == 0 && unlink_nid_postfix(chflagsPointing.string().c_str()) == 0);
} else {
unlink_nid_postfix(chflagsDangling.string().c_str());
std::fprintf(stderr, "symbolic links unavailable: the chflags link cases not tested\n");
}
const int flagged = open_nid_postfix(file.string().c_str(), 0, 0);
Require(flagged >= 0 && fchflags_nid_postfix(flagged, 0) == 0);
Require(fchflags_nid_postfix(flagged, 0x20) == -1 && *__error_nid_postfix() == 45);