Main's #9618 has lstat fill a local FileStat and copy it out to the guest.
The merge keeps that and this branch's module lookup in the same call, so an
original .prx name still resolves to its relinked .guest.prx.
fcntl(fd, F_DUPFD, min) with min at or above RLIMIT_NOFILE duplicated the
descriptor repeatedly until the CRT table was full and then failed with
EMFILE, after opening thousands of descriptors. FreeBSD checks the minimum
first: kern_dup returns EINVAL for FDDUP_FCNTL when new < 0 or
new >= maxfd (sys/kern/kern_descrip.c:836-840). Linux already answers
EINVAL through the host fcntl. Check the minimum against the guest
RLIMIT_NOFILE before the Windows loop.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
fstat, _fstat, sceKernelFstat, stat, lstat, sceKernelStat and _fstatfs
filled the caller's struct in place, or copied into it after a check that
only tests for null, so a pointer into unmapped memory crashed the host.
Fill a local struct and copy it out with a checked write that fails with
EFAULT. FreeBSD 11.4 does the same after the lookup has succeeded:
copyout(&ub, uap->sb) in sys_fstat (sys/kern/kern_descrip.c:1328),
copyout(&sb, uap->ub) in sys_stat (sys/kern/vfs_syscalls.c:2066) and
copyout(sfp, uap->buf) in sys_fstatfs (sys/kern/vfs_syscalls.c:337).
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
fcntl(F_SETFL) threw when it changed O_APPEND on a Windows file. The
guest flag already chooses WriteAtEnd, but a descriptor opened with
O_APPEND also carries the CRT's append flag, so _write kept appending
after the guest cleared it. F_SETFL now replaces the CRT descriptor of
every descriptor sharing the open file's status with a duplicate handle
opened with or without _O_APPEND, as libc fdopen does for append mode.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD resolves the descriptor with getvnode in sys_fchflags
(vfs_syscalls.c:2403), which fails with EINVAL for a descriptor that has no
vnode. fchflags threw for a kqueue descriptor instead.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
FreeBSD keeps every character device on devfs, whose devfs_statfs reports
512-byte blocks, 2 blocks and nothing free. Windows threw for any console,
NUL or the guest random device, and Linux described the host's /dev mount.
A kqueue now returns EINVAL, as getvnode does.
Co-Authored-By: Claude Opus 5.5 <[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 vn_seek fails SEEK_CUR and SEEK_END with EOVERFLOW when the base offset plus a positive offset does not fit in an off_t, and with EINVAL only when the result is negative. The host lseek reports EINVAL for the overflow, so the guest saw EINVAL. When the host call fails with EINVAL for a positive offset on SEEK_CUR or SEEK_END, the base position is read back and the call fails with EOVERFLOW if the sum would overflow; the file position is left unchanged.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
On Linux sceKernelGetdirentries copied the host d_type, so a directory under app0 that is a host symlink was listed as a link, and a title that only descends into directory entries skipped it. Inside the app0 tree, report a symlink (or an entry of unknown type) as the type of its target; links elsewhere, and dangling links, stay links.
The PS5 libkernel exports _accept, _bind, _connect, _getdirentries,
_getpeername, _getsockname, _getsockopt, _listen, _recvfrom, _recvmsg,
_sendmsg, _sendto, _setsockopt, _sigaction and _sigsuspend (PS5 3.20
export list, DNNDHH/PS5-3.20_Libs b2a77c0 libkernel.c), and main
exports none of them, so a title importing one fails at startup. Each
now forwards to the export without the underscore, as _close, _ioctl
and _nanosleep already do.
In FreeBSD 11.4 (8c639945a4) these are libc's plain system call
entries: lib/libc/amd64/SYS.h makes bind, getdirentries, getpeername,
getsockname, getsockopt, listen and setsockopt one stub under both
names, and lib/libc/sys/Makefile.inc gives accept, connect, recvfrom,
recvmsg, sendmsg, sendto, sigaction and sigsuspend a separate public
name that goes through libthr's interposing table, which adds the
cancellation points and the sigaction wrapper. The exports without the
underscore have no libthr layer here, so forwarding gives the system
call. docs/dev/debt/libkernel.md records what stays unverified: the
console is not measured, _sigaction shares the handler table of
sigaction, and a null set throws in _sigsuspend as in sigsuspend,
where FreeBSD's system call returns EFAULT.
guest_underscore_entries calls every new export: a loopback TCP
connection, UDP datagrams with scatter, truncation and sender
addresses, a directory listing compared with getdirentries, a SIGTERM
handler set by _sigaction, and a pending SIGUSR1 that _sigsuspend
delivers before returning EINTR with the mask restored. It checks the
errors they pass on (EBADF, EINVAL, EFAULT, ENOPROTOOPT, EOPNOTSUPP)
and that outputs stay untouched on failure.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A wait polling a regular-file event holds the equeue mutex and calls
sceKernelLseek, which takes the descriptor's position lock on Windows.
sceKernelClose and close took that lock first and then the equeue mutex
in EqueueDescriptorClosed, so a close racing such a wait deadlocked. Both
now remove the descriptor's events before taking the position lock, as
dup2 already does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD 11 fopen opens the path with _open, and vn_open_vnode refuses a
directory only for FWRITE or O_TRUNC, so fopen of a directory in a read
mode succeeds; Linux hosts already open it. On Windows CreateFileW
without FILE_FLAG_BACKUP_SEMANTICS refused it with EACCES.
fopen now opens such a path as a libkernel directory descriptor, which
libkernel registers in libc when it loads, and fclose and freopen remove
it from libkernel's table. Reads on the stream fail with EISDIR and set
the error indicator, as on a Linux host and FreeBSD's tmpfs: the Windows
CRT fails them already but reports EINVAL. Writes fail with EBADF, and
fseek, ftell and ungetc work, as on any read-only stream.
FreeBSD 11.4's sys_flock only requires a vnode descriptor, so flock on a directory descriptor succeeds. On Windows the call reached LockFileEx, which rejects a directory handle with ERROR_INVALID_PARAMETER, and flock_nid_postfix turned that into a runtime_error that aborted the process. A directory descriptor now returns 0 without taking a lock; the new guest_file_lock_directory case covers it and the debt entry records that no lock is held.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>