CopyNativeStat keeps the host block size for regular files on POSIX, so a
64 KiB host (ZFS, some network mounts) makes the st_blksize != 0x10000
assertion fail with correct production code. Compare against the host's
actual st_blksize (POSIX) or the 512 Windows convention, which still
catches an unconditional directory-size assignment spilling onto files.
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, std::tmpfile() returns NULL with errno 22 when %TEMP%
contains a character outside the ANSI code page, where GetTempPathA
returns '?' in its place. Fifteen tests that capture output through it
aborted. TemporaryFile::Open() opens a unique delete-on-close file under
temp_directory_path() with _wfopen; other hosts keep std::tmpfile().
Part of #13083
Co-Authored-By: Claude Opus 5.5 <[email protected]>
As rooklz suggested in review: a row for a regular file next to the
directory rows, so a change that reports 0x10000 for every stat fails.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A PS4 Pro (firmware 10.71) reports st_blksize 0x10000 from stat and fstat
for /app0, its subdirectories and the system library directory. Titles
size one getdents buffer from it: CUSA18659's CryPak reads st_blksize +
264 bytes once, so the 512 reported here cut its shader directory listing
short. Directories, app0.zar ones included, now report 0x10000; /data
directories (0x8000 on the console) and files are recorded as debt.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows, std::filesystem::symlink_status and is_symlink report a directory symbolic link as a plain directory, so rmdir removed the link instead of failing with ENOTDIR (20) and unlink failed with EPERM (1) instead of removing it, unlike FreeBSD. Detect the symlink reparse tag with FindFirstFileW: rmdir returns ENOTDIR, unlink removes the link with RemoveDirectoryW. Junctions and volume mounts keep their previous behaviour. Enable the directory-link and dangling-link blocks of guest_filesystem on Windows (created with CreateSymbolicLinkW).
AI-assisted: yes
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GtXavMkgCTCdmRpweviHcQ
sceKernelRmdir decided whether the last component was a symbolic link with
std::filesystem::is_symlink, which follows the link with WinLibs libstdc++ on
Windows. A dangling or self-referencing file link then looked missing on
Windows 10 (ENOENT instead of ENOTDIR), and a directory link to an empty
directory looked like that directory, so rmdir removed the link and
returned 0. The last component is now classified with FillLinkStat, the
same lstat path lstat_nid_postfix uses, matching FreeBSD 11 kern_rmdirat,
which returns ENOTDIR for any non-directory vnode found without following
the last link.
Fixes#12079
Co-Authored-By: Claude Opus 5.5 <[email protected]>
rename looked up its source and destination with
std::filesystem::symlink_status, which MinGW's libstdc++ answers by
following the link, so a dangling or looping link counted as missing
and rename failed with ENOENT. FreeBSD renames the link itself. A path
whose own attributes are a reparse point is now treated as a symbolic
link when symlink_status reports it missing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
NativeLseek seeked first and only checked for a pipe when the host seek
succeeded, so a negative offset reached the guest as EINVAL from
_lseeki64. FreeBSD 11.4's kern_lseek returns ESPIPE for any seek on a
descriptor without DFLAG_SEEKABLE, so the pipe check now comes first.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Match the AT_REMOVEDIR and rmdir sites so file reparse points stay on the old unlink path. Cover file symlink unlinkat on Windows and point the debt at the drive-target consumers.
rmdir followed the junction and reported ENOTEMPTY, and unlink treated it as a real directory, so a junction to a non-empty folder could not be removed.
std::filesystem::status does not follow a Windows symbolic link under
MinGW, so the lookup chflags makes saw a link whose target is missing as
an existing file and returned 0. A reparse point in the last component
is now looked up through the target with the guest stat, as FreeBSD 11.4's
namei follows it: a missing target gives ENOENT, and a trailing slash
after a link to a file gives ENOTDIR.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.
On Windows, rename converted ENOENT or ENOTDIR to ELOOP when either parent directory was below a symbolic link loop. A missing source, or a source below a non-directory, paired with a destination through a loop then reported ELOOP. FreeBSD 11.4 kern_renameat returns the failed source lookup before it examines the destination. A loop below the source still gives ELOOP, and a loop below the destination gives ELOOP only when the source lookup succeeded.
guest_filesystem gains the missing-source and non-directory-source-prefix cases paired with a looping destination, for rename and sceKernelRename.
On success the moved link and the replaced link are already gone, so
only the link now named rename-occupied.txt is removed there; the links
and files a skipped run may leave behind are removed in that branch.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The rename change recognises junctions by IO_REPARSE_TAG_MOUNT_POINT but
the test only made directory symbolic links. The same three calls now
also run on two junctions made with mklink /J, which needs no Developer
Mode, so the cases run where symbolic links cannot be created.
Co-Authored-By: Claude Opus 5.5 <[email protected]>