diff options
author | elfmz <fenix1905@tut.by> | 2022-02-07 22:29:37 +0300 |
---|---|---|
committer | elfmz <fenix1905@tut.by> | 2022-02-07 22:29:37 +0300 |
commit | b748240f56afbdae94336442d7e7cb05ec50bfc7 (patch) | |
tree | a3b91a242ec1d52edf0ae9411beb17b91d850d9a /WinPort | |
parent | 0feb97bb3edddae8a91fd67105f40f80d2c0ee85 (diff) |
editor: refactor recent changes
Diffstat (limited to 'WinPort')
-rw-r--r-- | WinPort/WinPort.h | 4 | ||||
-rw-r--r-- | WinPort/src/APIFiles.cpp | 41 |
2 files changed, 38 insertions, 7 deletions
diff --git a/WinPort/WinPort.h b/WinPort/WinPort.h index 3bc7fa80..369b451e 100644 --- a/WinPort/WinPort.h +++ b/WinPort/WinPort.h @@ -142,8 +142,12 @@ extern "C" { LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)); WINPORT_DECL(SetFilePointerEx, BOOL, ( HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)); + + // hints that file will soon grow up to specified size, doesnt change actual size of file WINPORT_DECL(FileAllocationHint, VOID, (HANDLE hFile, DWORD64 HintFileSize)); + // grows file to specified size if it was smaller, ensuring that disk space is actually allocated WINPORT_DECL(FileAllocationRequire, BOOL, (HANDLE hFile, DWORD64 RequireFileSize)); + WINPORT_DECL(SetFilePointer, DWORD, ( HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)); WINPORT_DECL(GetFileTime, BOOL, ( HANDLE hFile, LPFILETIME lpCreationTime, diff --git a/WinPort/src/APIFiles.cpp b/WinPort/src/APIFiles.cpp index 347bce4b..c29b0951 100644 --- a/WinPort/src/APIFiles.cpp +++ b/WinPort/src/APIFiles.cpp @@ -407,29 +407,56 @@ extern "C" return FALSE; } + struct stat s{}; + if (fstat(wph->fd, &s) == -1) + return FALSE; + #if defined(__linux__) || defined(__FreeBSD__) int ret = posix_fallocate(wph->fd, 0, (off_t)RequireFileSize); - if (ret != 0) { - errno = ret; - return FALSE; - } + if (ret == 0) + return TRUE; #elif defined(F_PREALLOCATE) + if ((off_t)RequireFileSize <= s.st_size) + return TRUE; + fstore_t fst {}; fst.fst_flags = F_ALLOCATECONTIG; fst.fst_posmode = F_PEOFPOSMODE; fst.fst_offset = 0; - fst.fst_length = (off_t)RequireFileSize; + fst.fst_length = (off_t)((off_t)RequireFileSize - s.st_size); fst.fst_bytesalloc = 0; + int ret = fcntl(wph->fd, F_PREALLOCATE, &fst); if (ret == -1) { fst.fst_flags = F_ALLOCATEALL; + fst.fst_bytesalloc = 0; ret = fcntl(wph->fd, F_PREALLOCATE, &fst); - if (ret == -1) { + } + + if (ret != -1 && ftruncate(wph->fd, (off_t)RequireFileSize) == 0) { + return TRUE; + } +#endif + + // posix_fallocate/F_PREALLOCATE unsupported or failed, try to fallback + // to file expansion by writing zero bytes to ensure space allocation + char dummy[0x10000]{}; + for (off_t ofs = s.st_size; ofs < (off_t)RequireFileSize; ) { + const size_t piece = (size_t)std::min((off_t)sizeof(dummy), (off_t)RequireFileSize - ofs); + const ssize_t r = pwrite(wph->fd, dummy, piece, ofs); + if (r == 0 || (r < 0 && errno != EAGAIN && errno != EINTR)) { + int err = errno; + if (ftruncate(wph->fd, s.st_size) == -1) { // revert original size + perror("FileAllocationRequire: ftruncate to original length"); + } + errno = err; return FALSE; } + if (r > 0) { + ofs+= (size_t)r; + } } -#endif return TRUE; } |