Commit Graph
199 Commits
Author SHA1 Message Date
Adrià FranchandClaude Sonnet 5.5 654eadd7f5 merge: sync archive directories with main
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-26 10:50:37 +01:00
Dean 7109f36927 Merge pull request #8696 from cadenasynyster/fix/win-rename-loop
fix(libc): report ELOOP from rename through a Windows symlink loop
2026-10-26 20:36:42 +13:00
qpavyros 9b2dd8dce9 merge: sync archive follow-up with main 2026-10-26 01:53:02 +02:00
Adrià efd368fec6 Merge pull request #9469 from Gruzzberry/fix/chflags-dangling-link
fix(libkernel): fail chflags through a dangling Windows symbolic link with ENOENT
2026-10-26 00:13:50 +01:00
qpavyros 6105be4431 merge: sync archive directories with main 2026-10-26 01:10:12 +02:00
Adrià 065d5dba6a Merge pull request #9502 from GitamarT045T3R/fix/libkernel-fchmod-pipe
fix(libkernel): fail fchmod on a pipe with EINVAL like FreeBSD
2026-10-25 21:03:23 +01:00
Adrià FranchandClaude Sonnet 5.5 a5c72e02c4 fix(libkernel): rename the chflags link test locals that clash in main()
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-25 19:58:17 +01:00
GruzzberryandClaude Opus 5.5 720cf7e296 fix(libkernel): fail chflags through a dangling Windows symbolic link with ENOENT
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]>
2026-10-25 19:58:17 +01:00
Adrià 506991994d Merge pull request #9496 from Gruzzberry/fix/open-excl-symbolic-link
fix(libkernel): fail open with O_CREAT and O_EXCL on a Windows symbolic link
2026-10-25 18:35:57 +01:00
Adrià 2e1c72239b Merge pull request #9487 from Gruzzberry/fix/chmod-symbolic-link
fix(libkernel): follow a Windows symbolic link in chmod
2026-10-25 18:25:24 +01:00
Yunus Shaikh 20ae347f6a Merge main into fix/libkernel-lstat-relinked-prx
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.
2026-10-25 03:56:39 -07:00
boykopovar f38d29fd08 refactor(sdk): add canonical headers for remaining libraries 2026-10-24 23:17:42 +03:00
qpavyros 0a64d23bdf feat(libkernel): enumerate archived app directories
Squashed onto current main, resolving the fchflags/fstatfs conflict with the kqueue guards.
2026-10-24 20:18:05 +02:00
Dean a3cf44c558 Merge pull request #10111 from xXPBSXx/fix/fchflags-kqueue-einval
fix(libkernel): fail fchflags on a kqueue descriptor with EINVAL
2026-10-24 12:54:38 +13:00
cadenasynyster 0a238f9e49 fix(libc): keep a rename source lookup error ahead of a destination loop
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.
2026-10-23 21:26:38 +02:00
GruzzberryandClaude Opus 5.5 3cd6a37bfb fix(libkernel): fail open with O_CREAT and O_EXCL on a Windows symbolic link
FreeBSD 11.4's vn_open_cred does not follow the last component when
O_EXCL is set, so O_CREAT|O_EXCL on a symbolic link fails with EEXIST
whatever it points to. On Windows the host open followed a dangling link
and created its target. A reparse point in the last component now fails
O_CREAT|O_EXCL with EEXIST before the host open.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 14:40:23 +01:00
GruzzberryandClaude Opus 5.5 4e5db13927 fix(libkernel): follow a Windows symbolic link in chmod
_wchmod changes the read-only attribute of the path it is given, so on
Windows chmod through a symbolic link changed the link and left the file
it names unchanged, and a dangling link succeeded. A reparse point is now
opened through its target and the target's path is changed, as FreeBSD
11.4's sys_chmod passes FOLLOW: a missing target fails with ENOENT and a
link loop with ELOOP. The path lookup of a handle moves out of
WindowsDescriptorPath_nid_no_patch so both use it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 14:40:15 +01:00
Dean 65f1d28e7d Merge pull request #9109 from Retr0G28/fix/alias-trailing-slash-windows
fix(libc): fail with ENOTDIR for a file named with a trailing slash on Windows
2026-10-24 02:08:03 +13:00
xXPBSXxandClaude Sonnet 5.5 5b739d2b56 fix(libkernel): fail fchflags on a kqueue descriptor with EINVAL
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]>
2026-10-23 12:28:27 +02:00
Dean a75292c7b3 Merge pull request #8687 from cadenasynyster/fix/win-loop-errors
fix(libkernel): report ELOOP from unlink, mkdir, rmdir, truncate on Windows
2026-10-23 21:08:52 +13:00
Retr0 0f3d4bc9ee fix(libc): fail with ENOTDIR for a file named with a trailing slash on Windows
FreeBSD 11.4's lookup() (sys/kern/vfs_lookup.c) fails with ENOTDIR when
a path with a trailing slash ends at something that is not a directory.
On Windows a mount alias dropped the slash, and the host calls do not
report ENOTDIR for "file\", so unlink, rename and open acted on the file
or failed with EINVAL. Guest path resolution now rejects an existing
non-directory named with a trailing slash with ENOTDIR on every host, and
a mount alias keeps the slash on Windows as it does on Linux and macOS.
2026-10-23 08:21:01 +03:00
Adrià a6fc8a467d Merge pull request #8797 from xXPBSXx/fix/unlink-rmdir-dot-component
fix(libkernel): fail unlink and rmdir of a path that ends in a dot component with EINVAL
2026-10-22 20:40:44 +02:00
Adrià 9b1ed888d1 Merge pull request #9206 from xXPBSXx/fix/lseek-eoverflow
fix(libkernel): fail lseek with EOVERFLOW when the new offset exceeds the 64-bit range
2026-10-22 20:16:30 +02:00
Itamar Medyoni 89f99c2f50 fix(libkernel): fail fchmod on a pipe with EINVAL like FreeBSD
fchmod and sceKernelFchmod on either end of a pipe answered ENOENT on
Windows, where the pipe has no path, and changed the pipe's mode on Linux.
FreeBSD 11's pipe_chmod sends an unnamed pipe to invfo_chmod, which
returns EINVAL, as sockets already get here.
2026-10-22 15:15:13 +03:00
Yunus Shaikh 82bd36d74b Merge main into fix/libkernel-lstat-relinked-prx 2026-10-21 22:26:58 -07:00
Dean ab347d144d Merge pull request #8534 from ycbuzi/pr/windows-reparse-non-link
fix(libkernel): answer Windows reparse points that are not links
2026-10-22 17:22:28 +13:00
Dean 746bdd8041 Merge pull request #8550 from Retr0G28/fix/fopen-directory-read-windows
fix(libc): open a directory with fopen in a read mode on Windows
2026-10-22 17:22:22 +13:00
blu 9897260c6e Merge branch 'boykopovar:main' into pr/windows-reparse-non-link 2026-10-21 19:08:16 -07:00
Yunus Shaikh 6e9768f618 Merge main into fix/libkernel-lstat-relinked-prx 2026-10-21 15:22:31 -07:00
xXPBSXxandClaude Sonnet 5.5 00bb8aa409 fix(libkernel): fail lseek with EOVERFLOW when the new offset exceeds the 64-bit range
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]>
2026-10-21 20:56:02 +02:00
Adrià ee67ebcf2d Merge pull request #8663 from xXPBSXx/fix/transfer-descriptor-first-fb
fix(libkernel): look up the descriptor of read, write, pread and pwrite before their buffer and offset
2026-10-21 20:35:28 +02:00
Retr0 36226741f5 fix(libc): open a directory with fopen in a read mode on Windows
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.
2026-10-21 14:48:37 +03:00
Dean 8425543705 Merge pull request #8655 from cadenasynyster/fix/win-open-loop-inside
fix(libkernel): report ELOOP for a path below a Windows symlink loop
2026-10-21 20:57:12 +13:00
blu 04b1d6e5b5 Merge branch 'boykopovar:main' into pr/windows-reparse-non-link 2026-10-20 23:38:51 -07:00
0de8266c6f test(libc): cover repeated root separators in the trailing separator trim
The two Windows cases, a doubled separator after the drive root and after a
folder name, come from MarcZX10's follow-up d68de63527 to the root review on
this PR.

Co-Authored-By: MarcZX10 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 08:33:28 +02:00
xXPBSXxandClaude Sonnet 5.5 7d87767137 fix(libc): keep the root when trimming the parent of a dot component
Trimming every trailing separator turned the Windows drive root "C:\" into
the drive-relative "C:". Trim only while the parent is longer than its
root_path(), and cover "/", "C:\" and "C:/" in guest_filesystem.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 08:16:59 +02:00
xXPBSXxandClaude Sonnet 5.5 288bd35d0d fix(libc): resolve the parent of a dot component without its trailing separator
RenameDotError_nid_no_patch resolved the parent with the separator kept
("file/"). On Linux std::filesystem::exists("file/") is false for a regular
file, so unlink, rmdir and rename of "file/." answered ENOENT instead of
ENOTDIR. Trim the trailing separators first (a lone "/" stays) and cover
rename of "file/." and "file/.." in guest_filesystem.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 08:01:50 +02:00
xXPBSXxandClaude Sonnet 5.5 a2a77714d5 fix(libkernel): fail unlink and rmdir of a path that ends in a dot component with EINVAL
FreeBSD lookup() refuses "." and ".." as the last component of a DELETE
lookup with EINVAL (sys/kern/vfs_lookup.c:750-754 and 823-826), before the
unlink and rmdir checks run. unlink and sceKernelUnlink answered EPERM,
rmdir and sceKernelRmdir answered ENOTEMPTY for "..", and unlinkat without
AT_REMOVEDIR answered EPERM. Reuse the RenameDot check added for rename, so a
missing or non-directory parent still reports ENOENT or ENOTDIR first.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 08:01:47 +02:00
xXPBSXxandClaude Sonnet 5.5 f7ff48ce9d test(libc): drop the middle-dot case from the final-dot ENOTDIR test
Resolve() checks a "." only as the last component, so "file/./child" was
already ENOTDIR from the host and did not exercise the change.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 05:08:55 +02:00
bluandClaude Fable 5.1 338e2cbe97 test(libkernel): skip the reparse point checks when setting one is refused for rights
Both fixtures required FSCTL_SET_REPARSE_POINT to succeed; a user without the right would have
aborted guest_filesystem and guest_kernel_sys. They now print that the checks are skipped and carry
on, as the symbolic link checks do without Developer Mode. On this PC the control succeeds at
medium integrity, so the checks ran both elevated and unelevated.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-10-20 18:46:51 -07:00
xXPBSXxandClaude Sonnet 5.5 035d82b571 fix(libc): fail a path that ends in a dot component below a regular file with ENOTDIR on Windows
FreeBSD looks the "." up in the directory before it, so "file/." fails with
ENOTDIR and "missing/." with ENOENT (sys/kern/vfs_cache.c vfs_cache_lookup,
`dvp->v_type != VDIR`). Resolve() dropped a trailing "." and handed the
host "file/", which stat, access, open and mkdir answered with ENOENT,
EINVAL or EEXIST. The ".." branch already checks the directory first;
do the same for a path whose last component is ".".

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 03:08:16 +02:00
Dean 46c7538777 Merge pull request #7467 from Dripl1x/codex/windows-path-component-lookup
perf(libc): avoid repeated Windows path component scans
2026-10-21 13:57:05 +13:00
Dean 07c67a0d6d Merge pull request #8640 from Dom3005/fix/windows-open-symlink-loop-eloop
fix(libc): map a Windows symbolic link loop to ELOOP when opening
2026-10-21 13:13:01 +13:00
xXPBSXxandClaude Sonnet 5.5 c2b92498b5 fix(libkernel): look up the descriptor of read, write, pread and pwrite before their buffer and offset
A null buffer, or for pread and pwrite a negative offset, was answered with
EFAULT or EINVAL before the descriptor was looked at, so a descriptor that is not
open (EBADF) or a pipe (ESPIPE) was hidden. FreeBSD 11.4 sys_generic.c looks
the descriptor up first (kern_readv, kern_preadv: fget, then the seekable
check, then the offset) and only reaches the buffer when it copies. The check
runs only when the buffer or offset is invalid, so a normal transfer costs nothing.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 01:29:00 +02:00
Dean eea640a5bf Merge pull request #8386 from xXPBSXx/fix/lseek-descriptor-first-fb
fix(libkernel): look up the descriptor of lseek before the whence value
2026-10-21 12:06:53 +13:00
cadenasynysterandClaude Sonnet 5.5 447a36e942 fix(libc): report ELOOP from rename through a Windows symlink loop
A rename whose source or destination directory is a self-referencing symbolic link returned ENOTDIR or ENOENT on Windows; FreeBSD returns ELOOP.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GtXavMkgCTCdmRpweviHcQ
2026-10-20 23:12:41 +02:00
cadenasynysterandClaude Sonnet 5.5 e3d249fb05 fix(libkernel): report ELOOP from unlink, mkdir, rmdir and truncate on Windows
A path through a self-referencing symbolic link returned ENOTDIR, EIO or EINVAL on Windows; FreeBSD returns ELOOP. The failure paths now use the loop check that sceKernelStat uses.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GtXavMkgCTCdmRpweviHcQ
2026-10-20 23:02:35 +02:00
Dom3005andClaude Opus 5.5 1af777afb1 fix(libc): map a Windows symbolic link loop to ELOOP when opening
CreateFileW fails a symbolic link that resolves to itself with
ERROR_CANT_RESOLVE_FILENAME (1921). WindowsOpenError_nid_no_patch had no
case for it, so sceKernelOpen, open and fopen reported EINVAL where
FreeBSD reports ELOOP.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 22:18:21 +02:00
cadenasynysterandClaude Sonnet 5.5 97a2dcb27f fix(libkernel): report ELOOP when opening below a Windows symbolic link loop
A path below a self-referencing symbolic link returned ENOTDIR on Windows; FreeBSD returns ELOOP. A failed native open now uses the loop check that sceKernelStat uses.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GtXavMkgCTCdmRpweviHcQ
2026-10-20 22:06:36 +02:00
bluandClaude Opus 5.5 0ecef87c4c fix(libkernel): answer Windows reparse points that are not links
lstat and readlink threw NotImplemented for every Windows reparse point
other than a symbolic link or a drive junction. A tag without the name
surrogate bit (cloud files, deduplication) does not stand for another path,
so lstat now answers as stat does and readlink returns EINVAL, as FreeBSD
does for a file that is not a link and as CPython's os.lstat and os.readlink
do (bpo-37834). A name surrogate that is neither a symbolic link nor a
junction (a mounted volume, a WSL link) is reported as the reparse point
itself with the mode of its attributes, and readlink returns EINVAL.

The tests set reparse tags with FSCTL_SET_REPARSE_POINT, one without the
name surrogate bit and one with it. A compact /exe (WOF) file cannot serve
as the fixture: on Windows 11 24H2 the WOF filter hides the reparse point
from GetFileAttributesW and FileAttributeTagInfo alike. Windows refuses
every open of an unhandled tag without FILE_FLAG_OPEN_REPARSE_POINT, so the
test requires lstat to agree with stat rather than to succeed.

mashingaan's boykopovar/AnyPS5#6447 returned EINVAL for other reparse
points without the tag check.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-10-20 08:21:33 -07:00