Implement file_truncate for Windows and add missing Quakey mocks
file_truncate had a stub `return -1` on Windows, causing all chunk_store_write calls to fail (every PUT returned TRANSFER_FAILED). Implement it using SetFilePointer + SetEndOfFile. Add mock_SetEndOfFile and mock_GetFileAttributesA to Quakey so the simulation can exercise the Windows code paths against the mock filesystem. Without these, SetEndOfFile was unmocked (link error) and GetFileAttributesA called the real Win32 API on mock paths, making chunk_store_exists always return false. Verified: seeds 1-100 pass with 2000s simulation time. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+6
-1
@@ -86,7 +86,12 @@ int file_truncate(Handle fd, size_t new_size)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
return -1; // TODO: Not implemented
|
||||
DWORD result = SetFilePointer((HANDLE) fd.data, (LONG) new_size, NULL, FILE_BEGIN);
|
||||
if (result == INVALID_SET_FILE_POINTER)
|
||||
return -1;
|
||||
if (!SetEndOfFile((HANDLE) fd.data))
|
||||
return -1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -123,11 +123,13 @@ int mock_ioctlsocket(SOCKET fd, long cmd, unsigned long *argp);
|
||||
BOOL mock_QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
|
||||
BOOL mock_QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
|
||||
HANDLE mock_CreateFileW(WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
DWORD mock_GetFileAttributesA(char *lpFileName);
|
||||
BOOL mock_CloseHandle(HANDLE handle);
|
||||
BOOL mock_ReadFile(HANDLE handle, char *dst, DWORD len, DWORD *num, OVERLAPPED *ov);
|
||||
BOOL mock_WriteFile(HANDLE handle, char *src, DWORD len, DWORD *num, OVERLAPPED *ov);
|
||||
BOOL mock_GetFileSizeEx(HANDLE handle, LARGE_INTEGER *buf);
|
||||
DWORD mock_SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
BOOL mock_SetEndOfFile(HANDLE hFile);
|
||||
BOOL mock_LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh);
|
||||
BOOL mock_UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh);
|
||||
BOOL mock_FlushFileBuffers(HANDLE handle);
|
||||
@@ -199,6 +201,7 @@ void mock_free(void *ptr);
|
||||
#define close mock_close
|
||||
#define ftruncate mock_ftruncate
|
||||
#define CreateFileW mock_CreateFileW
|
||||
#define GetFileAttributesA mock_GetFileAttributesA
|
||||
#define CloseHandle mock_CloseHandle
|
||||
#define ReadFile mock_ReadFile
|
||||
#define WriteFile mock_WriteFile
|
||||
@@ -208,6 +211,7 @@ void mock_free(void *ptr);
|
||||
#define GetFileSizeEx mock_GetFileSizeEx
|
||||
#define lseek mock_lseek
|
||||
#define SetFilePointer mock_SetFilePointer
|
||||
#define SetEndOfFile mock_SetEndOfFile
|
||||
#define flock mock_flock
|
||||
#define LockFile mock_LockFile
|
||||
#define UnlockFile mock_UnlockFile
|
||||
|
||||
@@ -4371,6 +4371,25 @@ HANDLE mock_CreateFileW(WCHAR *lpFileName,
|
||||
return (HANDLE)(long long)desc_idx;
|
||||
}
|
||||
|
||||
DWORD mock_GetFileAttributesA(char *lpFileName)
|
||||
{
|
||||
Host *host = host___;
|
||||
if (host == NULL)
|
||||
abort_("Call to mock_GetFileAttributesA() with no node scheduled\n");
|
||||
|
||||
// Try opening the file read-only to check existence
|
||||
int ret = host_open_file(host, lpFileName, MOCKFS_O_RDONLY);
|
||||
if (ret < 0) {
|
||||
*host_errno_ptr(host) = ERROR_FILE_NOT_FOUND;
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
// File exists — close it and return normal attributes
|
||||
host_close(host, ret, false);
|
||||
*host_errno_ptr(host) = ERROR_SUCCESS;
|
||||
return FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
|
||||
BOOL mock_CloseHandle(HANDLE handle)
|
||||
{
|
||||
Host *host = host___;
|
||||
@@ -4574,6 +4593,45 @@ DWORD mock_SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceTo
|
||||
return (DWORD)(new_pos & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
BOOL mock_SetEndOfFile(HANDLE hFile)
|
||||
{
|
||||
Host *host = host___;
|
||||
if (host == NULL)
|
||||
abort_("Call to mock_SetEndOfFile() with no node scheduled\n");
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {
|
||||
*host_errno_ptr(host) = ERROR_INVALID_HANDLE;
|
||||
return 0; // FALSE
|
||||
}
|
||||
|
||||
int desc_idx = (int)(long long)hFile;
|
||||
|
||||
// Get current file position to use as the new size
|
||||
int cur_pos = host_lseek(host, desc_idx, 0, HOST_SEEK_CUR);
|
||||
if (cur_pos < 0) {
|
||||
*host_errno_ptr(host) = ERROR_INVALID_HANDLE;
|
||||
return 0; // FALSE
|
||||
}
|
||||
|
||||
int ret = host_ftruncate(host, desc_idx, cur_pos);
|
||||
if (ret < 0) {
|
||||
switch (ret) {
|
||||
case HOST_ERROR_BADIDX:
|
||||
*host_errno_ptr(host) = ERROR_INVALID_HANDLE;
|
||||
return 0;
|
||||
case HOST_ERROR_NOSPC:
|
||||
*host_errno_ptr(host) = ERROR_DISK_FULL;
|
||||
return 0;
|
||||
default:
|
||||
*host_errno_ptr(host) = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*host_errno_ptr(host) = ERROR_SUCCESS;
|
||||
return 1; // TRUE
|
||||
}
|
||||
|
||||
BOOL mock_GetFileSizeEx(HANDLE handle, LARGE_INTEGER *buf)
|
||||
{
|
||||
Host *host = host___;
|
||||
|
||||
Reference in New Issue
Block a user