Repository navigation
fix(libc): remove read-only files on Windows - #2342
Conversation
FreeBSD's unlink ignores the file's own permission bits, so remove() succeeds on a file the guest made read-only with chmod(0400). On Windows the guest chmod sets FILE_ATTRIBUTE_READONLY, and DeleteFileW then fails with ERROR_ACCESS_DENIED, which remove() reported as EACCES. Clear the attribute and retry, restoring it if the retry still fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Full Linux and Windows builds and tests for this head (
Run: https://github.com/AchrafReyani/AnyPS5/actions/runs/37955618179 |
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Done in e8d4c02: I rechecked on Windows:
The Linux and Windows full build for the new head is running and will be posted here. |
|
Full Linux and Windows builds and tests for this head (
Run: https://github.com/AchrafReyani/AnyPS5/actions/runs/37986819849 |
fix(libc): remove read-only files on Windows
FreeBSD's unlink ignores the file's own permission bits, so it succeeds on a file the guest made read-only with chmod(0400). On Windows the guest chmod sets the read-only attribute and _wunlink then failed with EACCES, which sceKernelUnlink and unlink reported. When the path is a regular file without write permission, make it writable before the single _wunlink and restore the read-only attribute if the unlink fails, as remove() does since boykopovar#2342. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit fbf0ec0)
What
On FreeBSD,
unlink(and soremove) ignores the file's own permission bits: what matters is write access to the directory. A guest that doeschmod(path, 0400)and laterremove(path)therefore succeeds on the console.On Windows, the guest
chmod(_wchmod) setsFILE_ATTRIBUTE_READONLYwhen the write bit is cleared.DeleteFileWthen fails withERROR_ACCESS_DENIED, soremovereturned -1 withEACCES, and the file stayed.When the entry carries
FILE_ATTRIBUTE_READONLY(the attributes are already read),removenow clears it before the single delete. If the delete fails (e.g. the file is open without delete sharing), it restores the original attributes and reports the delete's error, so a failedremoveleaves the file as it was. Linux is unchanged.Tested
Windows 11, WinLibs GCC 15.2.0 r7, Release,
-DBUILD_TESTING=ON:guest_filesystem: a file made read-only withsceKernelChmod(0400)is removed byremove, and no longer exists.mainit fails at that line with guest errno 13.removefails (EBUSY), the file stays, andFILE_ATTRIBUTE_READONLYis restored;chmodnever sets the attribute on directories, so directory removal is unaffected.ctest -E "^agc_|video_out": 249/249.tools/check_conventions.pypasses, andtools/pr_overlap.py --branchreports no overlap. It also merges cleanly with the open PRs that touchGuestFilesystem.cppandFilesystem.cpp: feat(libkernel): export the POSIX rename #1192, feat(libkernel): implement fdatasync #1620, feat(libkernel): implement lstat #1624, fix(libkernel): honour open flags when Windows falls back to a directory descriptor #1628, fix(libkernel): give flock BSD semantics on Windows #1755, fix(libkernel): return EWOULDBLOCK from a contended LOCK_NB flock #1764, feat(libkernel): open /dev/random and /dev/urandom for reading #1777, fix(libkernel): report EISDIR for path truncation #2086, fix(libkernel): report Linux file birth times accurately #2115, feat(libkernel): implement sceKernelFdatasync #2129, fix(files): isolate guest descriptors from host resources #2170, fix(libkernel): report POSIX rename errors from sceKernelRename #2260, fix(libkernel): return EPERM when unlinking a directory #2289 and fix(libkernel): report ENOTDIR from stat for a file with a trailing slash #2300.sceKernelUnlink/unlinkin libkernel likely behave the same way on Windows. They are left for a separate PR, because #2289 changes that function.A Linux and Windows full build will be posted here once it has run.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code