Skip to content

feat(libkernel): support SEEK_DATA and SEEK_HOLE in lseek - #6936

Open
AlexOfTheForest wants to merge 3 commits into
boykopovar:mainfrom
AlexOfTheForest:fix/lseek-data-hole
Open

AlexOfTheForest wants to merge 3 commits into
boykopovar:mainfrom
AlexOfTheForest:fix/lseek-data-hole

Conversation

@AlexOfTheForest

Copy link
Copy Markdown
Contributor

What

FreeBSD 11.4's lseek accepts SEEK_DATA (3) and SEEK_HOLE (4); AnyPS5 rejected them, sceKernelLseek threw on any unknown whence, and lseek returned EINVAL before looking at the descriptor. Three commits:

  • fix(libkernel): an unknown whence fails as in FreeBSD's kern_lseek. The file is fetched first, so a closed descriptor is EBADF and a pipe ESPIPE whatever the whence. vn_seek rejects the unknown whence with EINVAL. sceKernelLseek no longer throws.
  • feat(libkernel): SEEK_DATA/SEEK_HOLE as vn_seek and vn_bmap_seekhole define them:
    • Regular file: an offset at or past the end is ENXIO. Inside the file, SEEK_DATA finds the next data and SEEK_HOLE the next hole, with the end of the file counting as one.
    • Directory: ENOTTY. Pipe: ESPIPE.
    • Hosts: Linux and macOS ask the host for the same regions. Windows reports no holes, so SEEK_HOLE returns the file size.
    • A negative offset, shared memory and devices throw, as the source does not settle them.
  • feat(libkernel): the same on app0.zar descriptors, which have no holes.

The logic lives in File/src/Seek.cpp. The console's filesystems are unknown (one without FIOSEEKDATA would answer ENOTTY), so this is recorded in docs/dev/debt/libkernel.md. GuestPosixScalarIo expected EINVAL for whence 3; it now checks an unknown whence (5) instead.

Tested

Linux x86-64, GCC.

  • New test guest_lseek_whence:
    • unknown whence: EINVAL, EBADF and ESPIPE, through both sceKernelLseek and lseek;
    • SEEK_DATA/SEEK_HOLE inside a file, at its end and past it, and on an empty file, a directory and a pipe;
    • the position is unchanged after an error, and negative offsets throw.
  • guest_kernel_app_archive covers archived files. guest_posix_scalar_io, guest_filesystem and the archive tests pass.
  • Each commit was built and tested on its own.
  • Not tested on Windows or macOS.

Checklist

  • Based on current main; no other open PR implements the same functions
  • 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
  • GPUs tested: n/a
  • AI-assisted: yes

@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 4563 core/libs/prx/libkernel/CMakeLists.txt
PR 4630 docs/dev/debt/libkernel.md
PR 5021 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 6149 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 6740 docs/dev/debt/libkernel.md
PR 7088 docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7121 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 7149 docs/dev/debt/libkernel.md
PR 7156 core/libs/prx/libkernel/CMakeLists.txt
PR 7192 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7447 core/libs/prx/libkernel/File/src/ArchivedFile.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 7464 docs/dev/debt/libkernel.md
PR 7532 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7565 docs/dev/debt/libkernel.md
PR 7645 core/libs/prx/libkernel/CMakeLists.txt
PR 7804 docs/dev/debt/libkernel.md
PR 8041 core/libs/prx/libkernel/CMakeLists.txt
PR 8463 core/libs/prx/libkernel/CMakeLists.txt
PR 8497 docs/dev/debt/libkernel.md
PR 8605 docs/dev/debt/libkernel.md
PR 9019 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9156 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9161 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9199 docs/dev/debt/libkernel.md
PR 9242 docs/dev/debt/libkernel.md
PR 9293 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 9297 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 9302 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 9326 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9383 core/libs/prx/libkernel/CMakeLists.txt
PR 9389 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9557 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9566 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9684 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9843 docs/dev/debt/libkernel.md
PR 9938 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9947 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
docs/dev/debt/libkernel.md
PR 10014 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 10016 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 10025 docs/dev/debt/libkernel.md
PR 10192 docs/dev/debt/libkernel.md
PR 10319 core/libs/prx/libkernel/File/src/Open.cpp
docs/dev/debt/libkernel.md
PR 10442 docs/dev/debt/libkernel.md
PR 10558 docs/dev/debt/libkernel.md
PR 10645 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10749 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10806 core/libs/prx/libkernel/CMakeLists.txt
PR 11002 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 11215 docs/dev/debt/libkernel.md
PR 11219 docs/dev/debt/libkernel.md
PR 11223 docs/dev/debt/libkernel.md
PR 11247 docs/dev/debt/libkernel.md
PR 11446 core/libs/prx/libkernel/CMakeLists.txt
PR 11624 docs/dev/debt/libkernel.md
PR 11625 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/ArchivedFile.cpp
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/tests/GuestKernelAppArchive.cpp
docs/dev/debt/libkernel.md
PR 11628 docs/dev/debt/libkernel.md
PR 11661 docs/dev/debt/libkernel.md
PR 11689 docs/dev/debt/libkernel.md
PR 11698 docs/dev/debt/libkernel.md
PR 11831 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/tests/GuestKernelAppArchive.cpp
PR 11891 core/libs/prx/libkernel/CMakeLists.txt
PR 11894 core/libs/prx/libkernel/CMakeLists.txt
PR 11896 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 11939 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 12104 docs/dev/debt/libkernel.md
PR 12139 core/libs/prx/libkernel/CMakeLists.txt
PR 12149 core/libs/prx/libkernel/CMakeLists.txt
PR 12170 docs/dev/debt/libkernel.md
PR 12544 core/libs/prx/libkernel/CMakeLists.txt
PR 12560 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 12682 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/tests/GuestKernelAppArchive.cpp
docs/dev/debt/libkernel.md
PR 12688 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/tests/GuestKernelAppArchive.cpp
docs/dev/debt/libkernel.md
PR 12700 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/tests/GuestKernelAppArchive.cpp
docs/dev/debt/libkernel.md
PR 12835 core/libs/prx/libkernel/File/src/Open.cpp
PR 12854 docs/dev/debt/libkernel.md
PR 12915 core/libs/prx/libkernel/File/src/Open.cpp
PR 12965 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
core/libs/tests/GuestKernelAppArchive.cpp
docs/dev/debt/libkernel.md
PR 12970 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 13336 docs/dev/debt/libkernel.md
PR 13504 docs/dev/debt/libkernel.md
PR 13506 docs/dev/debt/libkernel.md
PR 13560 docs/dev/debt/libkernel.md
PR 13582 docs/dev/debt/libkernel.md
PR 13587 docs/dev/debt/libkernel.md
PR 13664 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 13695 docs/dev/debt/libkernel.md
PR 13730 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 13950 docs/dev/debt/libkernel.md
PR 13953 docs/dev/debt/libkernel.md
PR 13964 docs/dev/debt/libkernel.md
PR 13995 docs/dev/debt/libkernel.md
PR 14039 docs/dev/debt/libkernel.md
PR 14043 docs/dev/debt/libkernel.md
PR 14085 docs/dev/debt/libkernel.md
PR 14103 docs/dev/debt/libkernel.md
PR 14105 docs/dev/debt/libkernel.md
PR 14108 docs/dev/debt/libkernel.md
PR 14111 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 14128 docs/dev/debt/libkernel.md
PR 14183 docs/dev/debt/libkernel.md
PR 14190 docs/dev/debt/libkernel.md
PR 14206 core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 14212 docs/dev/debt/libkernel.md
PR 14264 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 14272 core/libs/prx/libkernel/CMakeLists.txt
PR 14299 core/libs/prx/libkernel/CMakeLists.txt
PR 14310 docs/dev/debt/libkernel.md
PR 14320 docs/dev/debt/libkernel.md
PR 14324 docs/dev/debt/libkernel.md
PR 14325 docs/dev/debt/libkernel.md
PR 14417 docs/dev/debt/libkernel.md
PR 14493 core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 14497 docs/dev/debt/libkernel.md
PR 14557 core/libs/prx/libkernel/CMakeLists.txt
PR 14566 core/libs/prx/libkernel/CMakeLists.txt
PR 14710 docs/dev/debt/libkernel.md
PR 14756 docs/dev/debt/libkernel.md
PR 14832 docs/dev/debt/libkernel.md
PR 14841 core/libs/prx/libkernel/CMakeLists.txt
PR 14854 docs/dev/debt/libkernel.md
PR 14874 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 14875 docs/dev/debt/libkernel.md
PR 14876 docs/dev/debt/libkernel.md
PR 14885 docs/dev/debt/libkernel.md
PR 14886 docs/dev/debt/libkernel.md
PR 14894 docs/dev/debt/libkernel.md
PR 14970 core/libs/prx/libkernel/CMakeLists.txt
PR 15030 docs/dev/debt/libkernel.md
PR 15035 docs/dev/debt/libkernel.md
PR 15037 core/libs/prx/libkernel/File/src/Stdio.cpp
docs/dev/debt/libkernel.md
PR 15040 docs/dev/debt/libkernel.md
PR 15041 docs/dev/debt/libkernel.md
PR 15046 core/libs/prx/libkernel/CMakeLists.txt
PR 15064 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 15095 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md

@AlexOfTheForest AlexOfTheForest changed the title Fix/lseek data hole feat(libkernel): support SEEK_DATA and SEEK_HOLE in lseek Oct 16, 2026
@cadenasynyster

Copy link
Copy Markdown
Contributor

Windows run, since the PR lists Windows as untested and the Windows CI job is skipped on this head:

Windows 11 10.0.26200.9711 (NTFS), WinLibs GCC 15.2.0 posix UCRT r7, Release, BUILD_TESTING=ON, head 8392e0c merged onto main f3263df (clean merge, no new build errors).

  • guest_lseek_whence: passes 3/3 (ctest --repeat until-fail:3).
  • guest_posix_scalar_io, guest_filesystem, guest_kernel_app_archive_archive / _plain / _mmap: pass.

Not checked: sparse files with real holes on NTFS, or a title.

AI-assisted: yes

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
@adriadam10 adriadam10 self-assigned this Oct 19, 2026
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 19, 2026
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 20, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 20, 2026
…of throwing

sceKernelLseek threw on a whence other than SET, CUR and END, and lseek returned EINVAL before looking at the descriptor. FreeBSD 11.4's kern_lseek fetches the file first and dispatches to its fo_seek: a closed descriptor is EBADF, a pipe ESPIPE whatever the whence, and vn_seek rejects the unknown whence with EINVAL. Both calls now resolve the descriptor before the whence.
FreeBSD 11.4 accepts whence 3 and 4: vn_seek forwards them to FIOSEEKDATA and FIOSEEKHOLE, which UFS answers through vn_bmap_seekhole. An offset at or past the end of a regular file is ENXIO, a directory ENOTTY and a pipe ESPIPE; inside the file SEEK_DATA finds the next data and SEEK_HOLE the next hole, the end of the file counting as one. Linux and macOS ask the host for the same regions; Windows has no holes to report, so SEEK_DATA keeps the offset and SEEK_HOLE moves to the size. A negative offset, shared memory and devices throw, as the source does not settle them.
An archived descriptor fell through to AppArchiveDescriptorSeek, which throws on any whence but SET, CUR and END. An archived file has no holes: SEEK_DATA keeps an offset inside the file, SEEK_HOLE moves to its size and an offset at or past the end is ENXIO, as for a regular file.
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 22, 2026
@fogydes

fogydes commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Review of PR #6936: feat(libkernel): support SEEK_DATA and SEEK_HOLE in lseek

Verdict: stale+rebase

Findings

  1. [verified] Freshness & merge conflicts: Branch head \ 06949da78cf801f47702e27f0dd987f4b80e184\ is 11,022 commits behind \origin/main\ (\�a627802e2210187d417deb64c8f2fed8e33011f). \git merge-tree --write-tree origin/main refs/heads/pull/6936\ fails with exit code 1 due to 2 content conflicts:
    • \core/libs/prx/libkernel/File/src/Open.cpp - \docs/dev/debt/libkernel.md2. [verified] Conventions: \python tools/check_conventions.py --base 7e2ba73\ passes cleanly with 0 errors and 0 warnings against its merge base.
  2. [read-only] Commit history: 3 clean conventional commits (\ ix(libkernel): fail an unknown lseek whence as FreeBSD does instead of throwing, \ eat(libkernel): support SEEK_DATA and SEEK_HOLE in lseek, \ eat(libkernel): answer SEEK_DATA and SEEK_HOLE on app0.zar files).
  3. [read-only] PR template checklist: The checklist omits the required - [ ] Fixes: none\ (or #N) line.
  4. [author-reported] Testing: Author reports unit test additions (\guest_lseek_whence\ in \core/libs/tests/GuestPosixScalarIo.cpp\ and archive coverage in \GuestKernelAppArchive.cpp) passing under Linux x86-64 GCC.

Freshness Envelope

  • Head SHA: \ 06949da78cf801f47702e27f0dd987f4b80e184- Merge base: �e2ba73e4c8c26b5d632b0d2f46166ffc1b8a29d- Commits behind main: 11,022
  • Merge-tree exit code: 1 (conflicts in \Open.cpp, \libkernel.md)

Cross-PR Ledger

@CnRJay CnRJay left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction (2026-11-01): the title-ID/log demand below is not a CONTRIBUTING requirement; Unblocks: none is allowed. The technical points below are unaffected.

The PR names no title that calls lseek with SEEK_DATA or SEEK_HOLE ("Unblocks: none") and shows no log line of a title reaching the change on main. Without that the new Seek.cpp surface (about 250 changed lines) is unreachable from anything that runs, and this kind of PR gets closed. Please add the title ID and the log line.

Two questions on the code:

  1. sceKernelLseek used to throw on an unknown whence and now returns EINVAL for anything outside 0 to 4. The description says this matches kern_lseek; is that checked against a console trace or only against FreeBSD sources? The debt entry says the console's filesystems are unknown, and the same uncertainty applies to which errno the console returns here.
  2. On Windows SEEK_HOLE returns the file size and SEEK_DATA returns the offset, i.e. the whole file is data. That is correct for a filesystem without sparse reporting, but sparse files on NTFS do exist; if a title probes for holes it would see a different layout than on Linux. Is that recorded in docs/dev/debt/libkernel.md, or only the console side?

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

build docs libkernel needs rebase Conflicts with main, rebase needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants