diff --git a/compat/msvc-posix.h b/compat/msvc-posix.h index c500b8b4aa..7ce39b8d3f 100644 --- a/compat/msvc-posix.h +++ b/compat/msvc-posix.h @@ -16,7 +16,6 @@ #define __attribute__(x) #define strcasecmp _stricmp #define strncasecmp _strnicmp -#define ftruncate _chsize #define strtoull _strtoui64 #define strtoll _strtoi64 @@ -30,4 +29,27 @@ typedef int sigset_t; #include "mingw-posix.h" +/* + * MSVC's `_chsize()` takes a 32-bit `long` and silently truncates files + * to 2 GiB. `_chsize_s()` accepts a 64-bit length but returns 0 on + * success or an errno value on failure, rather than the -1/errno + * convention POSIX `ftruncate()` callers expect. Wrap it so callers + * that test the return value as `< 0` or against `-1` keep working. + * + * Note: this declaration must follow `#include "mingw-posix.h"` so + * `off_t` resolves to `off64_t` and the parameter type matches the + * underlying `_chsize_s()` width. + */ +static inline int msvc_ftruncate(int fd, off_t length) +{ + int err = _chsize_s(fd, length); + + if (err) { + errno = err; + return -1; + } + return 0; +} +#define ftruncate msvc_ftruncate + #endif /* COMPAT_MSVC_POSIX_H */