Commit Graph
93 Commits
Author SHA1 Message Date
xXPBSXxandClaude Sonnet 5.5 972fb84988 fix(libc): fail chdir, remove, opendir and fopen through a regular file with ENOTDIR on Windows
A path whose directory part is a regular file, such as file/child, failed
with ENOENT in chdir, remove, opendir, fopen and freopen on Windows, where
FreeBSD 11.4 fails it with ENOTDIR (vfs_cache_lookup, sys/kern/vfs_cache.c).
The not-found error of these calls now asks whether the nearest existing
ancestor is not a directory, as open, stat, lstat, access and unlink do.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 07:54:18 +02:00
xXPBSXxandClaude Sonnet 5.5 d6b5e3f6b8 fix(libc): fail fopen and freopen of a directory for writing with EISDIR on Windows
fopen and freopen of a directory in a write mode failed with EACCES on
Windows, the host's answer. FreeBSD 11.4 fopen opens the path with open(2),
which fails a directory opened for writing with EISDIR (kern_openat, vn_open_cred).
A failed write-mode open of a directory now reports EISDIR.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 03:59:03 +02:00
Adrià 3050105f24 Merge pull request #6707 from karimibrahim07/feat/libc-qsort-s
feat(libc): implement qsort_s
2026-10-19 11:47:03 +02:00
Adrià dc54701e49 Merge pull request #6541 from wachi35676/fix/libc-fopen-random-device
fix(libc): read /dev/random and /dev/urandom through fopen
2026-10-19 08:38:06 +02:00
Ondra97 a64d038154 fix(libs): flush pending GPU results before file writes 2026-10-19 00:53:25 +02:00
Adrià 38a848a1b7 Merge pull request #6287 from ahmad3a4/fix/libc-append-streams-windows
fix(libc): append stream writes atomically on Windows
2026-10-19 00:16:59 +02:00
Muhammad Wasif Ali WasifandClaude Opus 5.5 b4e80e8fc7 fix(libc): read /dev/random and /dev/urandom through fopen
fopen resolved the random device paths to a host file that does not
exist and failed with ENOENT, while open and sceKernelOpen already serve
them from host entropy. A read-only fopen of either path now returns a
stream whose fread fills the buffer with host entropy. setvbuf, feof,
ferror, clearerr, the stream locks and fclose work on it, fflush returns
0 as on a FreeBSD stream that is not writing, other stream functions
throw, and opening the paths for writing throws as in libkernel.

ProsperoTV (PPSA99003) reads its phone pairing code this way and showed
"Code expired or unavailable".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 03:01:38 +05:00
babyhuey 2d8d3b9dc1 fix(libc): keep the host standard stream when a guest freopen of it fails 2026-10-18 09:12:17 -04:00
Ahmad 0b24f92a6c fix(libc): append stream writes atomically on Windows
fopen and freopen in an append mode gave the C runtime a descriptor with
_O_APPEND, which seeks to the end of the file and then writes. Streams on
separate descriptors overwrote each other's data. FreeBSD opens these
streams with O_APPEND, so every flush lands at the end of the file.

Open append streams with FILE_APPEND_DATA but without FILE_WRITE_DATA,
so Windows writes each flush at the end of the file. ftruncate and
flock reopen the file to get the access such a handle lacks.
2026-10-18 14:49:55 +03:00
T3cm0andClaude Opus 5.5 8283831a19 feat(libc): implement mergesort
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:42:46 -05:00
Romans Pokrovskis cf84fc44a8 fix(libc): preserve existing Windows path namespaces 2026-10-17 19:13:32 +03:00
Romans Pokrovskis e61af865de fix(libc): open long Windows host paths 2026-10-17 18:53:10 +03:00
Alexej Szpevák 5433b32b7d fix(libc): return the open error from fopen_s instead of ENOENT
fopen_s returned ENOENT for every failed open, including an invalid mode, a directory opened for writing and the loop and long-name cases. C11 K.3.5.2.1 only asks for a nonzero value; Microsoft's CRT, which shares Dinkumware's library, returns errno. fopen_s now returns the errno fopen set.
2026-10-17 11:52:14 +02:00
Alexej Szpevák 8806043613 fix(libc): translate the host errno of a failed freopen
freopen closed the stream and returned the host's errno from the failed reopen as is, with the same Linux numbers for a symlink loop or an over-long name as fopen had. It now passes it through GuestErrnoFromHost_nid_no_patch.
2026-10-17 11:51:32 +02:00
Alexej Szpevák dc324d3d5f fix(libc): translate the host errno of a failed fopen
fopen left the host's errno in place when the host open failed, so on Linux a symlink loop reached the title as 40 and an over-long name as 36, which are EMSGSIZE and EINPROGRESS on FreeBSD. GuestErrnoFromHost_nid_no_patch maps the host value to FreeBSD 11.4's: 1 to 34 are shared except EAGAIN (35), and ELOOP, ENAMETOOLONG, ENOTEMPTY, EDQUOT, EOVERFLOW and EDEADLK get their FreeBSD numbers; anything else is EIO.
2026-10-17 11:51:00 +02:00
Adrià f3263dfbf3 Merge pull request #5949 from Ondra97/codex/fix-fiopen-exclusive-create
fix(libc): create noreplace streams exclusively
2026-10-17 02:30:12 +02:00
Alexej Szpevák b71434d9b7 feat(libc): read app0.zar beside app0 and refuse archive-only paths elsewhere
A ZArchive named app0.zar beside app0/ is a read-only layer under it. libc opens it at the first path resolution, looks paths missing from app0/ up case-insensitively, reads files across compressed blocks and keeps the archived descriptor table with shared positions.

Resolving an archive-only path through a call that does not read the archive throws instead of failing with ENOENT, as do opendir of a directory present in both places, fdopen of an archived descriptor and chdir into the archive. A path through .. in an archive-only directory resolves.
2026-10-16 20:03:26 +02:00
Ondra97 3f95553e80 fix(libc): ignore noreplace for read-only streams 2026-10-16 11:35:14 +02:00
Ondra97 a70531c8fb Merge remote-tracking branch 'origin/main' into codex/fix-fiopen-exclusive-create 2026-10-16 11:22:10 +02:00
Karim Ibrahim edf4efe360 feat(libc): implement qsort_s
The Quake homebrew's libOSMesa.so.8 imports qsort_s, the only strong
import left unresolved once its symbol names resolve through NIDs.

qsort_s sorts as qsort does, with the context passed as the
comparator's third argument, and returns EINVAL after calling the
constraint handler for the runtime constraint violations of FreeBSD
13's qsort_s. The sort helpers take any comparator so both functions
share the FreeBSD 11 algorithm.
2026-10-16 01:31:40 -04:00
Ondra97 d902afe2d4 fix(libc): create noreplace streams exclusively 2026-10-14 18:47:19 +02:00
babyhuey 292752ff5a fix(libc): fail stream calls on a stream that a failed freopen closed 2026-10-14 02:20:06 -04:00
Dean 7e68acbb29 Merge pull request #4904 from EagleBearerYS/fix/libc-fflush-errors
fix(libc): return flush failures from fflush instead of throwing
2026-10-14 19:15:54 +13:00
Dean 6546a33944 Merge pull request #4728 from Ondra97/codex/fix-fdopen-access-mode
fix(libc): reject incompatible fdopen access modes on Windows
2026-10-14 19:06:55 +13:00
Dean 1c95691fb5 Merge pull request #5290 from veosett/codex/allocator-failure-results
fix(libc): return allocation failures to guest callers
2026-10-14 17:26:13 +13:00
Hussein Kadhim c520fda39b fix(libc): return ENOMEM when the host cannot commit a heap block and from reallocalign
A commit failure inside the guest arena threw and left the reserved range in use. The heap now resets and releases the range, and returns null with ENOMEM when the host is out of memory. reallocalign returns null with EINVAL or ENOMEM like the other allocator entry points.
2026-10-13 22:12:17 +06:00
Hussein Kadhim b0c0e1dadf fix(libc): return null with ENOMEM or EINVAL from malloc, calloc, realloc, memalign and aligned_alloc
A size the default heap rejects or the guest arena cannot place, a calloc product that overflows, and an invalid alignment threw through the guest call, which aborted the process. FreeBSD 11.4 returns null with ENOMEM, or EINVAL for an alignment that is not a power of two. Guest arena exhaustion now throws bad_alloc.
2026-10-13 22:12:17 +06:00
MarcZX100 eefe4db018 fix(libc): return native fopen errors 2026-10-13 07:51:09 +00:00
Ondra97 f2120a6458 fix(libc): reject incompatible fdopen access modes on Windows 2026-10-13 05:30:05 +02:00
Yunus Shaikh 3d550b3de4 fix(libc): return flush failures from fflush instead of throwing
fflush threw when the host flush failed, which ends the title on an
ordinary write error such as a full disk. FreeBSD's __sflush sets the
stream's error flag and returns EOF, as C17 7.21.5.2 asks. fflush now
returns the host result and keeps the guest stream's error flag in sync,
as fwrite, fputs and fclose already do since #4380 and #3926.
2026-10-12 19:58:04 -07:00
milescovielloandClaude Opus 5.5 0dda76b1f9 fix(libc): check for a pipe on every stream seek on Windows
The pipe check cached its first answer in the FileStream, so a stream
first used on a regular file stayed classified as a file after its
descriptor was replaced with a pipe (dup2 onto fileno(stream)), and a
later fseek reached the C runtime again and dropped buffered bytes.
fseeko and ftello now ask GetFileType on each call, as lseek on a pipe
does since #4670, and FileStream no longer keeps the state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:38:02 +00:00
David 7aabb9005c fix(libc): fail fseek and ftell on a pipe with ESPIPE on Windows 2026-10-13 02:38:01 +00:00
David dbbd6d582c fix(libc): append through a descriptor opened by fdopen in an append mode on Windows 2026-10-12 20:09:54 +00:00
Dean 9c99f43440 Merge pull request #4537 from coltken95/claude/sleepy-dirac-e44kw4
fix(libc): sort with FreeBSD 11's qsort so equal elements keep its order
2026-10-13 07:32:15 +13:00
Dean 57f91221c4 Merge pull request #4380 from AzazelSensei/fix/libc-stream-errors
fix(libc): return stream errors from fwrite, fread and fputs instead of throwing
2026-10-13 07:22:52 +13:00
Dean b701bc5d8d Merge pull request #4372 from milescoviello/fix/fflush-read-stream
fix(libc): leave a stream that is reading untouched in fflush on Linux
2026-10-13 07:22:17 +13:00
Dean b538b28d8b Merge pull request #4354 from milescoviello/fix/fopen-append-position
fix(libc): start append-mode streams at the end of the file
2026-10-13 07:18:50 +13:00
Claude ef09cda468 fix(libc): sort with FreeBSD 11's qsort so equal elements keep its order
qsort was a heapsort. It sorted correctly, but elements that compare
equal ended in a different order from FreeBSD's Bentley-McIlroy qsort,
in 18947 of 20000 random arrays with repeated keys, and below 7
elements, where FreeBSD's insertion sort keeps equal elements in
place, a heapsort does not. qsort now follows FreeBSD 11 qsort.c,
including its comparator call sequence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-12 15:01:35 +00:00
Dean 57dc136026 Merge pull request #3936 from MarcZX100/codex/carry-fopen-s-output-null
fix(libc): clear fopen_s output on invalid arguments
2026-10-13 02:32:30 +13:00
Abdullah 7e2832475f fix(libc): return stream errors from fwrite, fread and fputs instead of throwing 2026-10-12 16:14:25 +03:00
Dean d58ba1010e Merge pull request #4232 from MarcZX100/codex/carry-fdopen-modes-4022
fix(libc): accept FreeBSD fdopen modes
2026-10-13 01:30:04 +13:00
Dean 029c1bc17d Merge pull request #3926 from MarcZX100/codex/carry-fclose-error
fix(libc): return fclose failures to callers
2026-10-13 01:24:43 +13:00
milescovielloandClaude Opus 5.5 1337bd7e45 fix(libc): leave a stream that is reading untouched in fflush on Linux
fflush() passed every stream to glibc's fflush(). For a stream that is
reading, glibc seeks the descriptor back and drops the read buffer, and
with a pushed-back character it gets the position wrong: after fgetc()
returned 'a' from "abcdef\n" and ungetc('Z'), fflush() returned 0 and
the next fread() returned "bcdef\n\n". The pushed-back 'Z' was lost and
the last byte came back twice.

FreeBSD's fflush() writes out only a stream that is writing and leaves
every other stream as it is, lib/libc/stdio/fflush.c:

	if ((fp->_flags & (__SWR | __SRW)) == 0)
		retval = 0;
	else
		retval = __sflush(fp);

and __sflush():

	t = fp->_flags;
	if ((t & __SWR) == 0)
		return (0);

fflush() on Linux now returns 0 without calling the host for a stream
whose last operation was not a write (__fwriting() is 0). fflush(NULL)
and streams that are writing are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 08:00:21 +00:00
milescovielloandClaude Opus 5.5 6a19442f12 fix(libc): start append-mode streams at the end of the file
fopen and freopen leave an "a+" stream where the host CRT puts it, at
the start of the file. On main, after fopen(file, "a+") on a 7-byte
file, ftell returns 0 and the first fgetc returns the first byte of the
file. FreeBSD seeks every append-mode stream to the end when it opens
it, so ftell returns 7 and a read before any fseek returns EOF. Code
that opens a log or save file with "a+" and tests ftell(f) == 0 to see
whether the file is new treats every existing file as empty.

FreeBSD 11.4 lib/libc/stdio/fopen.c (fopen), and the same lines in
lib/libc/stdio/freopen.c (freopen):

	if (oflags & O_APPEND) {
		fp->_flags2 |= __S2OAP;
		(void)_sseek(fp, (fpos_t)0, SEEK_END);
	}

lib/libc/stdio/flags.c sets O_APPEND for every mode that starts with 'a':

	case 'a':	/* open for appending */
		ret = __SWR;
		m = O_WRONLY;
		o = O_CREAT | O_APPEND;

fopen and freopen now seek a stream opened with an 'a' mode to the end
of the file, ignoring a failed seek as FreeBSD does. Writes still go to
the end through O_APPEND.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:50:07 +00:00
milescovielloandClaude Opus 5.5 589de27c17 fix(libc): accept the fdopen modes FreeBSD accepts
fdopen only took a fixed list of 15 mode strings and failed with EINVAL
for any other, so "rt", "r+t", "re", "rbe" or "rw" gave NULL. FreeBSD's
fdopen parses the mode with __sflags (lib/libc/stdio/flags.c): after
r, w or a it takes b, +, x, e and v and stops at the first other
character ("default: known = 0;"), and only a bad first character or x
on a read-only mode fail with EINVAL. fopen and freopen already parse
modes this way through ParseFileMode (#2033).

fdopen now uses ParseFileMode as well and passes the host its normalised
mode without x, which FreeBSD's fdopen ignores.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 01:50:11 +00:00
Yunus Shaikh 0245ba7d88 fix(libc): open fopen streams with delete sharing on Windows
fopen opened its stream with _wfopen, which shares read and write
access but not delete access. While the guest held a stream open,
rename of its file failed with EIO and remove with EBUSY. POSIX rename
and remove work on open files, as on Linux and FreeBSD, and since
#3677 the descriptors sceKernelOpen returns share delete access.

fopen now creates the handle with CreateFileW sharing read, write and
delete, with the access and creation disposition of the mode, and
wraps it with _open_osfhandle and _wfdopen, keeping append mode. A
failed CreateFileW sets errno through the error mapping #3677 added to
libkernel's NativeOpen, which moves to libc as
WindowsOpenError_nid_no_patch so that both use it. freopen still
reopens through _wfreopen; TechnicalDebt records it.
2026-10-11 15:56:20 -07:00
Dean fabbeb393b Merge pull request #3522 from pushkarreddyy/feat/libc-reallocf
feat(libc): implement reallocf
2026-10-12 11:21:30 +13:00
Santhosh Kumar 17827dd9ab fix(filesystem): reject invalid parent traversal on Windows 2026-10-12 01:25:02 +05:30
MarcZX100 cc7343daf5 fix(libc): clear fopen_s output on invalid arguments
(cherry picked from commit 387279ee94)
2026-10-11 19:16:51 +00:00
MarcZX100 fdf288f3fc fix(libc): return fclose failures to callers
(cherry picked from commit 610d6cdda0)
2026-10-11 19:12:46 +00:00