On Windows, mkdirat with a directory descriptor and a relative path that goes through a symbolic link pointing to itself reported EIO. CreateDirectoryW fails with ERROR_CANT_RESOLVE_FILENAME for such a path, and the error mapping had no case for it, so it fell through to GuestEio. FreeBSD fails the lookup with ELOOP. The path form of mkdir and openat with the same descriptor already return ELOOP. ERROR_CANT_RESOLVE_FILENAME now gives ELOOP.
guest_kernel_sys gains a Windows check with a file-type and a directory-type self-loop: mkdirat through the loop returns ELOOP and mkdirat of the link itself still returns EEXIST. The check is skipped when the host denies symbolic link creation.
kern_fpathconf answers _PC_ASYNC_IO with _POSIX_ASYNCHRONOUS_IO (200112) after the descriptor lookup, and a pipe or socket (no vnode) with PIPE_BUF for _PC_PIPE_BUF and EINVAL for every other name. Drop the unused File.hpp include and the duplicate KernelErrors.hpp include.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
DescriptorIsOpen_nid_no_patch is not extern "C", so the patched libkernel.prx
does not export it and libkernel_sys.prx fails to load (patched_libraries:
LoadLibraryEx error 127). Check the descriptor like fchown does: GuestFstat on
Windows, fstat elsewhere, EBADF on failure.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
sceKernelGetSystemExVersion, sysKernelGetLowerLimitSysexVersion,
sysKernelGetLowerLimitUpdVersion and sceKernelGetTraceMemoryStats were
NotImplemented stubs in libkernel_sys. libkernel, libkernel_sys and
libkernel_web of firmware 13.42 answer them without asking the kernel:
empty strings, a zero version and zero statistics, with the null checks
and return codes the firmware uses, including the plain 22 of
sceKernelGetSystemExVersion.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
link took the source's std::filesystem::status first, and MinGW-w64's
libstdc++ reports a Windows symbolic link loop as not found (ENOENT), so
it returned ENOENT before FollowLinkPath, which maps the loop's
ERROR_CANT_RESOLVE_FILENAME to ELOOP, was reached. guest_kernel_sys's
loop case failed at that check wherever symbolic links can be created
(Windows 11 22H2: "check failed at line 835 (guest errno 2)").
When the status reports the source missing, ask FollowLinkPath first:
a loop now returns ELOOP and a dangling link still ENOENT; a missing
path is unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Read the clock of a libkernel condition attribute, returning
SCE_KERNEL_ERROR_EINVAL for a null or destroyed attribute as
scePthreadCondattrSetclock does, after FreeBSD 11.4 libthr's
_pthread_condattr_getclock. A null clock pointer throws.
All four exports threw. The ownership calls follow fchown: owner and
group 0 and the unchanged value are accepted and any other value
throws. The path is looked up first with stat, lstat or fstatat, as
FreeBSD 11's kern_fchownat does, so a lookup error is returned before
the owner is checked. fchownat rejects flags other than
AT_SYMLINK_NOFOLLOW with EINVAL. linkat passes AT_FDCWD and absolute
paths to link and rejects flags other than AT_SYMLINK_FOLLOW with
EINVAL; a relative path with a directory descriptor and a symbolic
link source without AT_SYMLINK_FOLLOW throw. On Windows a symbolic
link source is detected with the file attributes, since libstdc++
there reports it as a regular file.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The EINVAL for a descriptor without a vnode now applies only to a pipe or socket. A character device is a vnode on FreeBSD, so getvnode succeeds and change_dir fails with ENOTDIR; File::IsCharacterDevice keeps that answer for the host character devices (a tty, NUL or /dev/null) and the guest random device. guest_kernel_sys pins it with /dev/random.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
FreeBSD 11.4's sys_fchdir resolves the descriptor with getvnode, which fails with EINVAL for a descriptor that has no vnode; only a vnode that is not a directory gives ENOTDIR from change_dir. fchdir returned ENOTDIR for a pipe or socket. A descriptor that is neither a vnode nor a random device now gets EINVAL; the debt entry records the order of the three errors.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>