| #include <assert.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <io.h> |
| #include <stdio.h> |
| |
| #define WIN32_LEAN_AND_MEAN |
| #include <windows.h> |
| |
| /* mingw-w64 headers */ |
| #include "libtest.h" |
| |
| #define assert_winapi_seek(handle, offset, method) do { \ |
| LARGE_INTEGER li = { .QuadPart = (offset) }; \ |
| li.LowPart = SetFilePointer((handle), li.LowPart, &li.HighPart, (method)); \ |
| if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) \ |
| _assert("SetFilePointer(" #handle ", LARGE_INTEGER(" #offset "), " #method ") failed", __FILE__, __LINE__); \ |
| } while (0) |
| |
| #define assert_crt_fseeki64(expected, ...) do { \ |
| __int64 ret = _fseeki64(__VA_ARGS__); \ |
| if (ret == -1 && errno == ENOSPC) { \ |
| /* skip the test for DISK FULL error */ \ |
| printf("DISK FULL\n"); \ |
| return 77; \ |
| } \ |
| if (ret != (expected)) \ |
| _assert(#expected " == _fseeki64(" #__VA_ARGS__ ")", __FILE__, __LINE__); \ |
| } while (0) |
| |
| int main() { |
| FILE *file; |
| HANDLE handle; |
| char buf[5]; |
| DWORD len; |
| |
| mingw_test_init (); |
| |
| /* create temporary file which is automatically deleted when process terminates */ |
| file = tmpfile(); |
| assert(file); |
| |
| /* use text mode which translates \n to \r\n */ |
| assert(_setmode(fileno(file), _O_TEXT) != -1); |
| |
| /* absolute offset which fits into 32-bit signed type */ |
| assert_crt_fseeki64(0, file, 0x10, SEEK_SET); |
| assert(fputs("A\n", file) >= 0); |
| assert(fputs("A", file) >= 0); |
| |
| /* relative offset which fits into 32-bit signed type, but absolute does not */ |
| assert_crt_fseeki64(0, file, 0x7FFFFFFF, SEEK_CUR); |
| assert(fputs("B\n", file) >= 0); |
| assert(fputs("B", file) >= 0); |
| |
| /* absolute offset which fits into 32-bit unsigned type but does not into 32-bit signed type */ |
| assert_crt_fseeki64(0, file, 0x90000000, SEEK_SET); |
| assert(fputs("C\n", file) >= 0); |
| assert(fputs("C", file) >= 0); |
| |
| /* TODO: SEEK_CUR does not work when current position does not fit into 32-bit signed type for pre-msvcrt40 */ |
| #if __MSVCRT_VERSION__ >= 0x400 |
| /* relative offset which fits into 32-bit unsigned type but absolute does not */ |
| assert_crt_fseeki64(0, file, 0xFFFFFFFF, SEEK_CUR); |
| assert(fputs("D\n", file) >= 0); |
| assert(fputs("D", file) >= 0); |
| #else |
| assert_crt_fseeki64(-1, file, 0xFFFFFFFF, SEEK_CUR); |
| assert(errno == EOVERFLOW); |
| #endif |
| |
| /* absolute offset which does not fit into 32-bit unsigned type */ |
| assert_crt_fseeki64(0, file, 0x100000000, SEEK_SET); |
| assert(fputs("E\n", file) >= 0); |
| assert(fputs("E", file) >= 0); |
| |
| /* TODO: SEEK_CUR does not work when current position does not fit into 32-bit signed type for pre-msvcrt40 */ |
| #if __MSVCRT_VERSION__ >= 0x400 |
| /* relative offset which does not fit into 32-bit unsigned type */ |
| assert_crt_fseeki64(0, file, 0x100000000, SEEK_CUR); |
| assert(fputs("F\n", file) >= 0); |
| assert(fputs("F", file) >= 0); |
| #else |
| assert_crt_fseeki64(-1, file, 0x100000000, SEEK_CUR); |
| assert(errno == EOVERFLOW); |
| #endif |
| |
| /* last absolute write, without the nul byte */ |
| assert_crt_fseeki64(0, file, 0x300000000, SEEK_SET); |
| assert(fputs("_\n", file) >= 0); |
| assert(fputs("_", file) >= 0); |
| |
| /* flush all data, so they can be accessed via WinAPI */ |
| if (fflush(file) == EOF && errno == ENOSPC) { |
| /* skip the test for DISK FULL error */ |
| printf("DISK FULL\n"); |
| return 77; |
| } |
| assert(fflush(file) == 0); |
| |
| /* now read all data via WinAPI and check that they were written at correct offsets */ |
| |
| handle = (HANDLE)_get_osfhandle(fileno(file)); |
| assert(handle != INVALID_HANDLE_VALUE); |
| |
| assert_winapi_seek(handle, 0, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == sizeof(buf)); |
| assert(memcmp(buf, "\0\0\0\0", 5) == 0); |
| |
| assert_winapi_seek(handle, 0x10, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == sizeof(buf)); |
| assert(memcmp(buf, "A\r\nA", 5) == 0); |
| |
| assert_winapi_seek(handle, 0x7FFFFFFFLL + 0x10 + 4, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == sizeof(buf)); |
| assert(memcmp(buf, "B\r\nB", 5) == 0); |
| |
| assert_winapi_seek(handle, 0x90000000, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == sizeof(buf)); |
| assert(memcmp(buf, "C\r\nC", 5) == 0); |
| |
| /* TODO: SEEK_CUR does not work when current position does not fit into 32-bit signed type for pre-msvcrt40 */ |
| #if __MSVCRT_VERSION__ >= 0x400 |
| assert_winapi_seek(handle, 0xFFFFFFFFLL + 0x90000000 + 4, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == sizeof(buf)); |
| assert(memcmp(buf, "D\r\nD", 5) == 0); |
| #endif |
| |
| assert_winapi_seek(handle, 0x100000000, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == sizeof(buf)); |
| assert(memcmp(buf, "E\r\nE", 5) == 0); |
| |
| /* TODO: SEEK_CUR does not work when current position does not fit into 32-bit signed type for pre-msvcrt40 */ |
| #if __MSVCRT_VERSION__ >= 0x400 |
| assert_winapi_seek(handle, 0x200000000 + 4, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == sizeof(buf)); |
| assert(memcmp(buf, "F\r\nF", 5) == 0); |
| #endif |
| |
| assert_winapi_seek(handle, 0x300000000, FILE_BEGIN); |
| assert(ReadFile(handle, buf, sizeof(buf), &len, NULL) == TRUE); |
| assert(len == 4); /* sizeof(buf)-1 -> no nul byte */ |
| assert(memcmp(buf, "_\r\n_", 4) == 0); |
| |
| return 0; |
| } |