Skip to content

fix(libSceLibcInternal): read statvfs by path on macOS - #6668

Open
DavidSamir wants to merge 3 commits into
boykopovar:mainfrom
DavidSamir:fix/libc-statvfs-path-macos
Open

DavidSamir wants to merge 3 commits into
boykopovar:mainfrom
DavidSamir:fix/libc-statvfs-path-macos

Conversation

@DavidSamir

@DavidSamir DavidSamir commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

What

libSceLibcInternal does not build on macOS: statvfs opens the path with O_PATH to get a descriptor for fstatvfs, and macOS has no O_PATH:

core/libs/prx/libSceLibcInternal/PathStatistics.cpp:103:49: error: use of undeclared identifier 'O_PATH'

No open mode stands in for it. On macOS 26.7.1, O_RDONLY and O_EVTONLY fail with EACCES on a file or directory without read permission, and so does O_SEARCH | O_DIRECTORY on such a directory, while FreeBSD's statvfs only needs search permission on the path. The host statvfs by path behaves as FreeBSD's does there: it succeeds on a file or directory with mode 0, fails with ENOTDIR for file/, EACCES through a directory without search permission and ENOENT for a missing path.

So on macOS statvfs now reads the volume by path with the host statvfs, fills the kernel statfs the way _fstatfs fills it from the host fstatvfs (f_bsize from f_frsize, f_iosize from f_bsize, f_ffree from f_favail, ST_RDONLY and ST_NOSUID), and converts it with the same code as fstatvfs. A path that must name a directory (trailing slash, final .) and does not fails with ENOTDIR, as the O_DIRECTORY open does elsewhere. Linux and Windows are unchanged.

Commits:

  1. Move the guest struct statvfs and the sfs2svfs conversion from FilesystemStatistics.cpp to include/Statvfs.hpp, unchanged, so both functions share them.
  2. The macOS path.
  3. The test's check that statvfs leaves no descriptor open listed /proc/self/fd; on macOS it lists /dev/fd.

No debt entry: the guest sees the same results as on Linux.

Tested

macOS 26.7.1, Apple M2, AppleClang 21.0.0, x86-64 build under Rosetta, Release.

main does not build libc and libkernel on macOS for other reasons as well (#4627, #4630, #6124 and mugurc's macOS branches address them), so the tests ran in a local tree of main ce991f1 with those merged.

  • main's PathStatistics.cpp: libSceLibcInternal fails to compile with the error above.
  • main's code with O_EVTONLY in place of O_PATH: builds; guest_statvfs aborts at line 36, a statvfs call it expects to succeed returning -1.
  • After the refactor commit: guest_fstatvfs_conversion passes 3 runs of 3.
  • This branch: guest_statvfs passes 5 runs of 5 (directories, a regular file, the same file with mode 0, a FIFO, a bound socket, a symbolic link, the ENOTDIR, ENOENT and EFAULT cases, and no descriptor left open after 32 calls); guest_fstatvfs_conversion passes 3 runs of 3.
  • tools/check_conventions.py --base origin/main and git diff --check pass.

Windows 11 (WinLibs GCC 15.2.0 r7, UCRT, Release) and Ubuntu 24.04 under WSL2 (GCC 13.3.0, Release), head 4dcb2b89e merged onto main 5d9dcc4: guest_statvfs and guest_fstatvfs_conversion pass 3 runs of 3 with the change, and 3 runs of 3 with the code as on main (FilesystemStatistics.cpp and PathStatistics.cpp restored, include/Statvfs.hpp removed) and the tests kept. Both pass either way there, so the conversion moved into the shared header keeps Windows and Linux as before.

Overlap: #6222 opens with O_EVTONLY and, when that is denied, reads the parent directory's volume instead, which is a different volume when the file is a mount point. #6044 moves GuestStatvfs.cpp; whichever lands second rebases.

Checklist

  • Based on current main; no other open PR implements the same functions (see Overlap above)
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none (every title on macOS needs libSceLibcInternal to build)
  • GPUs tested: n/a
  • AI-assisted: yes

…sion

fstatvfs kept the guest struct statvfs and the sfs2svfs conversion from
the kernel's statfs to itself. Both move to include/Statvfs.hpp so that
statvfs can convert a volume the same way without opening the path.
Nothing changes for fstatvfs.
statvfs opened the path with O_PATH, which macOS does not have, so
libSceLibcInternal did not build there. No open mode stands in for it:
on macOS O_RDONLY and O_EVTONLY fail with EACCES on a file or directory
without read permission, and O_SEARCH on such a directory, where
FreeBSD's statvfs only needs search permission on the path.

On macOS statvfs now asks the host statvfs by path, which needs exactly
that, fills the kernel statfs the way _fstatfs fills it from the host
fstatvfs, and converts it with the code fstatvfs uses. A path that must
name a directory and does not fails with ENOTDIR, as the O_DIRECTORY open
does elsewhere. Other hosts are unchanged.
…n macOS

The check that statvfs leaves no descriptor open listed /proc/self/fd,
which macOS does not have. macOS lists the process's descriptors in
/dev/fd; Linux keeps /proc/self/fd.
@simonbbby

Copy link
Copy Markdown
Contributor

Independent native arm64 filesystem check at exact head 4dcb2b89ed21fe5acde91999a6fc4549666904b4, complementing the Rosetta coverage: macOS 27.2, Apple clang 21.0.0, ordinary user UID 501 (the probe refuses root).

Compiled the complete unchanged production PathStatistics.cpp and its actual Statvfs.hpp. An external driver supplies an identity ResolvePath_nid_no_patch for absolute host fixture paths and the final-dot helper; host filesystem calls, errno conversion and guest output conversion are not mocked. This intentionally does not exercise guest mount/path translation or the full runtime.

Three fresh-process runs pass:

  • Seven success cases: mode-0 regular file, mode-0 directory, ordinary file, FIFO, bound Unix-domain socket, symlink to a file, and directory .. The FIFO case is bounded by an alarm and does not block.
  • Eight error/null cases: null/empty path, missing path, file/, file/., traversal through a mode-0 parent, symlink loop and null output. Guest errors are 14/2/20/13/62 as appropriate; non-null failure outputs retain their sentinel bytes.
  • Successful calls preserve the incoming errno and output guard words. Block/fragment sizes, flags and name limit agree with native ::statvfs; guest fsid and available/free-file relationships are checked.
  • 32 additional mode-0-file calls per process leave the /dev/fd descriptor count unchanged.

Controls:

  • The pre-path-fix PathStatistics.cpp fails native compilation at O_PATH, as reported.
  • Adding only an O_EVTONLY open/close gate before the production path query, in a scratch source copy, makes the unchanged probe fail on its first mode-0-file case with guest errno=13. Restoring the untouched PR object passes all three runs. This confirms the permission matrix distinguishes path metadata access from requiring an open mode.

No repository source changed. No Rosetta/x86 execution, full guest_statvfs integration, Linux/Windows run or title claim.

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 core/libs/prx/libSceLibcInternal/FilesystemStatistics.cpp
core/libs/prx/libSceLibcInternal/PathStatistics.cpp
PR 6044 core/libs/tests/GuestStatvfs.cpp
PR 7201 core/libs/prx/libSceLibcInternal/PathStatistics.cpp
core/libs/tests/GuestStatvfs.cpp

@github-actions github-actions Bot added the prx label Oct 16, 2026
@DavidSamir

Copy link
Copy Markdown
Contributor Author

Windows and Linux results for 4dcb2b8, merged onto main 5d9dcc4:

Host Toolchain With the change Code as on main, new tests kept Restored
Windows 11 WinLibs GCC 15.2.0 r7 (UCRT), Release guest_statvfs and guest_fstatvfs_conversion 3/3 3/3 1/1
Ubuntu 24.04 (WSL2) GCC 13.3.0, Release guest_statvfs and guest_fstatvfs_conversion 3/3 3/3 1/1

Reverted for the middle column: FilesystemStatistics.cpp as on main, with the new PathStatistics.cpp and include/Statvfs.hpp removed. Both tests pass either way on both hosts. So the move of the shared statvfs code into Statvfs.hpp and PathStatistics.cpp keeps Windows and Linux behaving as before; the macOS difference only shows on macOS.

AI-assisted: yes

ycarogabriel-lgtm added a commit to ycarogabriel-lgtm/AnyPS5 that referenced this pull request Oct 17, 2026
Replaces this branch's statvfs fix. Opening the path with O_EVTONLY, and its parent when that failed, still needed read permission on a directory, while FreeBSD's statvfs only needs search permission on the path. The PR uses the host statvfs by path, which behaves as FreeBSD's does, and shares the statfs-to-statvfs conversion. The O_EVTONLY descriptor path and the metadata-only checks in _fstatfs that existed only for it are removed, matching mugurc's series.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ycarogabriel-lgtm added a commit to ycarogabriel-lgtm/AnyPS5 that referenced this pull request Oct 18, 2026
Replaces this branch's statvfs fix. Opening the path with O_EVTONLY, and its parent when that failed, still needed read permission on a directory, while FreeBSD's statvfs only needs search permission on the path. The PR uses the host statvfs by path, which behaves as FreeBSD's does, and shares the statfs-to-statvfs conversion. The O_EVTONLY descriptor path and the metadata-only checks in _fstatfs that existed only for it are removed, matching mugurc's series.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants