Skip to content

libc rename reports wrong errno values on Windows and fails to replace an empty directory #2403

Closed

Description

@reyani-dev

On Windows, the guest rename (rename_nid_postfix in core/libs/prx/libc/src/Filesystem.cpp) passes everything to std::filesystem::rename and maps the resulting std::error_code. MinGW's libstdc++ reports several cases differently from FreeBSD, so the guest sees wrong errno values, and one valid rename fails.

Probe calling rename_nid_postfix directly. Windows 11, WinLibs GCC 15.2.0 r7, current main:

case Windows result FreeBSD
file → existing file 0 0
dir → new name 0 0
dir → existing empty dir -1, errno 13 (EACCES) 0 (replaces it)
dir → non-empty dir -1, errno 13 -1, ENOTEMPTY (66)
file → existing dir -1, errno 21 -1, EISDIR (21)
dir → existing file -1, errno 20 -1, ENOTDIR (20)
missing source -1, errno 5 (EIO) -1, ENOENT (2)
dir into its own subdirectory -1, errno 5 -1, EINVAL (22)
destination parent missing -1, errno 5 -1, ENOENT (2)

On Linux, std::filesystem::rename is rename(2), so these already match.

The libkernel side (sceKernelRename) has the same problem; #2260 fixes it there. It checks source and destination with symlink_status, maps not-found and not-a-directory before calling rename, and removes an empty target directory first on Windows. The same approach would work here.

I haven't opened a PR, because #1192 moves rename_nid_postfix into a new Rename.cpp, and a fix in Filesystem.cpp would conflict with it. This is the data for whoever lands after it. I'm happy to do the follow-up once #1192 is merged or closed.

AI-assisted: yes (the probe was written and run with Claude Code).

Activity

  1. MarcZX10 commented on Oct 9, 2026

    @MarcZX10
    Contributor

    Validation update on current upstream main

    I rebased the prepared two-file candidate onto cf8b129e2771d26eaffc300248c46145063f1794. The merge since the previous update (#2670) does not touch either changed file.

    Check Result
    Build guest_filesystem_tests (Linux x86_64, Release) Passed on cf8b129e
    CTest guest_filesystem (--repeat until-fail:3) Passed 3/3 on cf8b129e
    Conventions against current main Passed
    git diff --cached --check Passed

    The Windows evidence from Achraf is a native Windows 11 probe on the original implementation branch (480dd351, based on 6cc33583): all nine reported rename behaviors matched FreeBSD, including replacing an empty directory. I confirmed Rename.cpp is unchanged between that branch and this candidate. The newly expanded guest_filesystem test binary has not been rerun on Windows at cf8b129e; its added assertions have been run on Linux as shown above.

    The candidate remains local and staged. I have not opened a replacement PR while intake requires 20 merged PRs and my count is 15. AI-assisted change.

  2. reyani-dev commented on Oct 10, 2026

    @reyani-dev
    ContributorAuthor

    Confirmed on Windows, @MarcZX100: your branch (480dd35) merged onto current main 6cc3358, Windows 11, WinLibs GCC 15.2.0 r7, Release.

    The probe from this report (rename_nid_postfix called directly) now matches FreeBSD in all nine cases, including the five that differed:

    case before with the branch
    dir → existing empty dir -1, 13 0 (replaced)
    dir → non-empty dir -1, 13 -1, 66
    missing source -1, 5 -1, 2
    dir into its own subdirectory -1, 5 -1, 22
    destination parent missing -1, 5 -1, 2

    The other four (file → existing file, dir → new name, file → existing dir 21, dir → existing file 20) are unchanged and correct.

    guest_filesystem with your regression passes 3/3 (--repeat until-fail:3), and ctest -E "^agc_|video_out" passes 372/372.

  3. MarcZX10 commented on Oct 10, 2026

    @MarcZX10
    Contributor

    Follow-up on current main

    The ready change is now refreshed onto upstream main ba2a0a31f15e9df224b2df904341fe00c0c26858 in codex/fix-libc-rename-win-errors-2403-latest, commit 7a41ca5e. It applies cleanly after #1192 moved the function to Rename.cpp.

    Current Linux x86_64 / GCC 12.2 / Release validation:

    • guest_filesystem_tests built.
    • CTest guest_filesystem passed (1/1).
    • Conventions against current main and git diff --check passed.

    The test covers the reported errno cases and replacement of an empty destination directory. The native Windows table remains Achraf's independent run on the same implementation at 480dd351 (based on earlier main); I have not run Windows on this refreshed commit. The repo still automatically closes PRs below 20 merged PRs; my live count is 15. The branch is pushed for a collaborator with intake access to carry, not an open PR. AI-assisted: yes.

  4. reyani-dev commented on Oct 10, 2026

    @reyani-dev
    ContributorAuthor

    Windows rerun on the refreshed commit, @MarcZX100: 7a41ca5e merged onto main ba2a0a3, Windows 11, WinLibs GCC 15.2.0 r7, Release.

    • The probe from this report still matches FreeBSD in all nine cases, including the five that differed on main: empty-dir replace gives 0, non-empty dir 66, missing source 2, move into own subdirectory 22, missing destination parent 2.
    • guest_filesystem passes 3/3 (--repeat until-fail:3).
    • ctest -E "^agc_|video_out" passes 380/380.
  5. oneandonlydean commented on Oct 10, 2026

    @oneandonlydean
    Collaborator

    @MarcZX100 the intake check needs 10 merged PRs now, so 7a41ca5 can go up as a PR.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions