The temporary file is made read-only before the rename. When the rename
fails, Windows refuses to remove a read-only file, so the temporary copy
stayed in the cache directory. Give the owner write permission back
before removing it. The failure test now clears its cache directory,
including read-only files, before and after it runs, so it can run
again in the same directory.
A guest that reopens `stdin`, `stdout` or `stderr` onto a directory in a read mode threw instead of
returning the stream, while the console answers that a directory opens in a read mode and the
debt entry already recorded the throw as the Windows difference.
The standard stream now goes through the same descriptor move a regular file uses: the directory
descriptor is opened, moved onto the standard descriptor, and libkernel's directory entry follows
it, so `fstat` of the guest descriptor reports a directory and the first read answers `EISDIR` with
the error indicator set, like every other directory stream. A failed open restores the previous
standard target.
`guest_freopen_host_standard` reopens `stdout` onto a directory, asserts `S_IFDIR` on the guest
descriptor, asserts the first read answers `EISDIR`, then reopens the same stream on a file path
and writes through it.
Writing and reading the cached CA_LIST.cer used the throwing filesystem
and stream calls. Tests that share the cache directory raced on the
rename over the cached file, and on Windows the resulting
filesystem_error cannot be delivered through libkernel frames, so the
test process died. Use the error_code overloads, read in chunks that
set the stream error state, treat a lost rename race as success when the
cached file already holds the bundle, and answer an unavailable list
with no file instead of caching the failure.
The new test blocks the cache directory and the cached file in turn and
expects the open to fail with ENOENT, then to succeed once unblocked.
Discovery failures now fall back to the plain end-of-file extension.
Sparse-marking and EOF failures still map to errors.
An IAT-patched regression covers the three truncate paths.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD 11.4 ufs_setattr refuses a change of any SF_* flag to a caller without PRIV_VFS_SYSFLAGS, which prison_priv_check denies a jailed root without allow.chflags. Under the credential model agreed on #11216 every SF_* flag now fails with EPERM, after the EOPNOTSUPP check for unknown bits, instead of throwing.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
On Windows, closing a pipe while another thread waited for it in select
terminated the process. The close releases the host handle before the C
runtime descriptor, so in between:
- the readiness query of the pipe failed on the dead handle and threw
'querying pipe descriptor ... failed';
- after that, DescriptorIsOpen still saw the descriptor mapped, select
looked it up again, found no known kind and threw 'is neither a
socket, a pipe, ...'.
QueryPipe now reports a descriptor whose handle is no longer a pipe as
not a pipe instead of throwing, DescriptorIsOpen on Windows also checks
that the mapped handle is still valid, and select answers EBADF for such
a descriptor before throwing for an unknown kind, as FreeBSD 11.4's
kern_select does for a descriptor closed during the wait.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceKernelUnlink takes its Windows directory-link path only when
std::filesystem::symlink_status reports a directory, but MinGW's
symlink_status follows the link. A directory symbolic link whose target
is missing therefore looked like a file, went to the file delete, and
failed with EACCES, because Windows removes a directory link only
through RemoveDirectoryW. guest_filesystem stops there on any Windows
host that may create symbolic links.
The directory path is now also taken when the link itself carries both
FILE_ATTRIBUTE_DIRECTORY and FILE_ATTRIBUTE_REPARSE_POINT, which
GetFileAttributesW reports without following the link.
Co-Authored-By: Claude Opus 5.5 <[email protected]>