mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-04 13:07:32 +00:00
FilePosition checked fgetpos and fsetpos only on a freshly written stream. It now reads three bytes and requires fgetpos to give 3, reads to end of file and requires fsetpos back to 3 to clear the end-of-file indicator (C11 7.21.9.3) so the next fgetc returns the fourth byte, and requires fsetpos to -1 to fail with EINVAL as FreeBSD's fseeko does. A rejected seek on Windows still moves the stream, because the UCRT drops its read buffer before the failing lseek: recorded in libc's technical debt instead of asserted. Co-Authored-By: Claude Opus 5.5 <[email protected]>
78 lines
2.5 KiB
C++
78 lines
2.5 KiB
C++
#include "prx/libc/include/Api.hpp"
|
|
#include "prx/libc/include/FileStream.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cerrno>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#ifdef _WIN32
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#include <windows.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
static void Check(bool value, int line) {
|
|
if (!value) {
|
|
std::fprintf(stderr, "File position check failed at line %d\n", line);
|
|
std::abort();
|
|
}
|
|
}
|
|
#define Require(value) Check((value), __LINE__)
|
|
|
|
int main() {
|
|
FileStream file(std::tmpfile());
|
|
Require(std::fputs("position", file.GetHandle()) >= 0);
|
|
std::int64_t position = -1;
|
|
Require(fgetpos_nid_postfix(&file, &position) == 0);
|
|
Require(position == 8);
|
|
const std::int64_t beginning = 0;
|
|
Require(fsetpos_nid_postfix(&file, &beginning) == 0);
|
|
Require(std::fgetc(file.GetHandle()) == 'p');
|
|
Require(fgetpos_nid_postfix(&file, &position) == 0 && position == 1);
|
|
file.Close();
|
|
|
|
FileStream reread(std::tmpfile());
|
|
Require(std::fputs("position", reread.GetHandle()) >= 0);
|
|
Require(fsetpos_nid_postfix(&reread, &beginning) == 0);
|
|
for (const char expected : {'p', 'o', 's'}) Require(fgetc_nid_postfix(&reread) == expected);
|
|
Require(fgetpos_nid_postfix(&reread, &position) == 0 && position == 3);
|
|
const std::int64_t third = position;
|
|
while (fgetc_nid_postfix(&reread) != EOF) {}
|
|
Require(feof_nid_postfix(&reread) != 0);
|
|
Require(fsetpos_nid_postfix(&reread, &third) == 0);
|
|
Require(feof_nid_postfix(&reread) == 0);
|
|
Require(fgetc_nid_postfix(&reread) == 'i');
|
|
const std::int64_t negative = -1;
|
|
errno = 0;
|
|
Require(fsetpos_nid_postfix(&reread, &negative) != 0);
|
|
Require(errno == EINVAL);
|
|
reread.Close();
|
|
|
|
int descriptors[2];
|
|
#ifdef _WIN32
|
|
Require(_pipe(descriptors, 4096, _O_BINARY) == 0);
|
|
FileStream pipe(_fdopen(descriptors[0], "rb"));
|
|
Require(_close(descriptors[1]) == 0);
|
|
Require(CloseHandle(reinterpret_cast<HANDLE>(_get_osfhandle(descriptors[0]))) != 0);
|
|
#else
|
|
Require(::pipe(descriptors) == 0);
|
|
FileStream pipe(::fdopen(descriptors[0], "rb"));
|
|
Require(::close(descriptors[1]) == 0);
|
|
#endif
|
|
Require(ftello_nid_postfix(&pipe) == -1);
|
|
const int expectedError = errno;
|
|
Require(expectedError != 0);
|
|
position = 123;
|
|
errno = 0;
|
|
Require(fgetpos_nid_postfix(&pipe, &position) != 0);
|
|
Require(errno == expectedError);
|
|
Require(position == 123);
|
|
#ifdef _WIN32
|
|
Require(std::fclose(pipe.GetHandle()) == EOF);
|
|
#else
|
|
pipe.Close();
|
|
#endif
|
|
}
|