From e7605c8fd6639bb1eb8f042b6bec894e010e040b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Franch?= Date: Sun, 11 Oct 2026 02:54:24 +0200 Subject: [PATCH] feat(libc): implement rewind Co-Authored-By: Claude --- core/libs/prx/libc/src/FileAndHeap.cpp | 6 +++++ core/libs/tests/GuestStandardStreams.cpp | 32 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index f295fdb7f..311c4973c 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -246,6 +246,12 @@ int APS5_VABI fsetpos_nid_postfix(FileStream* stream, const std::int64_t* positi return fseeko_nid_postfix(stream, *position, SEEK_SET); } +void APS5_VABI rewind_nid_postfix(FileStream* stream) { + const int saved = errno; + if (fseeko_nid_postfix(stream, 0, SEEK_SET) == 0) errno = saved; + stream->ClearError(); +} + int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream) { if (!str) throw std::runtime_error("fputs: null string"); const int result = std::fputs(str, GetNativeStream(stream)); diff --git a/core/libs/tests/GuestStandardStreams.cpp b/core/libs/tests/GuestStandardStreams.cpp index 66fda23d6..d30be63a6 100644 --- a/core/libs/tests/GuestStandardStreams.cpp +++ b/core/libs/tests/GuestStandardStreams.cpp @@ -41,8 +41,10 @@ int APS5_VABI __swbuf_nid_postfix(int, FileStream*); int APS5_VABI ungetc_nid_postfix(int, FileStream*); char* APS5_VABI fgets_nid_postfix(char*, int, FileStream*); int APS5_VABI feof_nid_postfix(FileStream*); +int APS5_VABI ferror_nid_postfix(FileStream*); int APS5_VABI fileno_nid_postfix(FileStream*); void APS5_VABI clearerr_nid_postfix(FileStream*); +void APS5_VABI rewind_nid_postfix(FileStream*); int APS5_VABI setvbuf_nid_postfix(FileStream*, char*, int, std::size_t); void APS5_VABI setbuf_nid_postfix(FileStream*, char*); FileStream* APS5_VABI fdopen_nid_postfix(int, const char*); @@ -93,6 +95,35 @@ static bool CheckFileBytes(const std::string& filename, const std::string& expec return false; } +static void CheckRewind() { + FileStream stream(std::tmpfile()); + Require(fwrite_nid_postfix("ab", 1, 2, &stream) == 2); + *__error_nid_postfix() = 7; + rewind_nid_postfix(&stream); + Require(*__error_nid_postfix() == 7 && ftello_nid_postfix(&stream) == 0); + Require(fgetc_nid_postfix(&stream) == 'a' && ungetc_nid_postfix('z', &stream) == 'z'); + rewind_nid_postfix(&stream); + Require(fgetc_nid_postfix(&stream) == 'a' && fgetc_nid_postfix(&stream) == 'b' && fgetc_nid_postfix(&stream) == EOF); + Require(feof_nid_postfix(&stream) != 0); + stream.SetEncodingError(); + Require(ferror_nid_postfix(&stream) != 0); + rewind_nid_postfix(&stream); + Require(feof_nid_postfix(&stream) == 0 && ferror_nid_postfix(&stream) == 0 && fgetc_nid_postfix(&stream) == 'a'); + stream.Close(); +#ifndef _WIN32 + int pipeEnds[2]; + Require(::pipe(pipeEnds) == 0); + Require(::write(pipeEnds[1], "p", 1) == 1); + ::close(pipeEnds[1]); + FileStream pipe(::fdopen(pipeEnds[0], "r")); + Require(fgetc_nid_postfix(&pipe) == 'p' && fgetc_nid_postfix(&pipe) == EOF && feof_nid_postfix(&pipe) != 0); + *__error_nid_postfix() = 0; + rewind_nid_postfix(&pipe); + Require(*__error_nid_postfix() == 29 && feof_nid_postfix(&pipe) == 0 && ferror_nid_postfix(&pipe) == 0); + pipe.Close(); +#endif +} + static bool CheckBinaryModes() { const auto directory = "anyps5-byte-stream-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()); Require(std::filesystem::create_directory(directory)); @@ -333,5 +364,6 @@ int main() { Require(lockedWrite && fseeko_nid_postfix(&locked, 0, SEEK_SET) == 0); Require(fgetc_nid_postfix(&locked) == 'A' && fgetc_nid_postfix(&locked) == 'B'); locked.Close(); + CheckRewind(); return CheckBinaryModes() ? 0 : 1; }