Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2022-02-07 22:29:37 +0300
committerelfmz <fenix1905@tut.by>2022-02-07 22:29:37 +0300
commitb748240f56afbdae94336442d7e7cb05ec50bfc7 (patch)
treea3b91a242ec1d52edf0ae9411beb17b91d850d9a /WinPort
parent0feb97bb3edddae8a91fd67105f40f80d2c0ee85 (diff)
editor: refactor recent changes
Diffstat (limited to 'WinPort')
-rw-r--r--WinPort/WinPort.h4
-rw-r--r--WinPort/src/APIFiles.cpp41
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;
}