1 /* ftruncate emulations for native Windows.
2 Copyright (C) 1992-2021 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, see <https://www.gnu.org/licenses/>. */
23 /* A native Windows platform. */
27 # if _GL_WINDOWS_64_BIT_OFF_T
29 /* Large File Support: off_t is 64-bit, but _chsize() takes only a 32-bit
30 argument. So, define a 64-bit safe SetFileSize function ourselves. */
32 /* Ensure that <windows.h> declares GetFileSizeEx. */
33 # if !defined _WIN32_WINNT || (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
35 # define _WIN32_WINNT _WIN32_WINNT_WIN2K
38 /* Get declarations of the native Windows API functions. */
39 # define WIN32_LEAN_AND_MEAN
42 /* Get _get_osfhandle. */
43 # if GNULIB_MSVC_NOTHROW
44 # include "msvc-nothrow.h"
50 SetFileSize (HANDLE h, LONGLONG size)
52 LARGE_INTEGER old_size;
54 if (!GetFileSizeEx (h, &old_size))
57 if (size != old_size.QuadPart)
59 /* Duplicate the handle, so we are free to modify its file position. */
60 HANDLE curr_process = GetCurrentProcess ();
63 if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
65 curr_process, /* TargetProcessHandle */
66 (PHANDLE) &tmph, /* TargetHandle */
67 (DWORD) 0, /* DesiredAccess */
68 FALSE, /* InheritHandle */
69 DUPLICATE_SAME_ACCESS)) /* Options */
72 if (size < old_size.QuadPart)
74 /* Reduce the size. */
75 LONG size_hi = (LONG) (size >> 32);
76 if (SetFilePointer (tmph, (LONG) size, &size_hi, FILE_BEGIN)
77 == INVALID_SET_FILE_POINTER
78 && GetLastError() != NO_ERROR)
83 if (!SetEndOfFile (tmph))
91 /* Increase the size by adding zero bytes at the end. */
92 static char zero_bytes[1024];
94 LONG pos_lo = SetFilePointer (tmph, (LONG) 0, &pos_hi, FILE_END);
96 if (pos_lo == INVALID_SET_FILE_POINTER
97 && GetLastError() != NO_ERROR)
102 pos = ((LONGLONG) pos_hi << 32) | (ULONGLONG) (ULONG) pos_lo;
106 LONGLONG count = size - pos;
107 if (count > sizeof (zero_bytes))
108 count = sizeof (zero_bytes);
109 if (!WriteFile (tmph, zero_bytes, (DWORD) count, &written, NULL)
115 pos += (ULONGLONG) (ULONG) written;
118 /* Close the handle. */
125 ftruncate (int fd, off_t length)
127 HANDLE handle = (HANDLE) _get_osfhandle (fd);
129 if (handle == INVALID_HANDLE_VALUE)
139 if (!SetFileSize (handle, length))
141 switch (GetLastError ())
143 case ERROR_ACCESS_DENIED:
146 case ERROR_HANDLE_DISK_FULL:
147 case ERROR_DISK_FULL:
148 case ERROR_DISK_TOO_FRAGMENTED:
164 # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
165 # include "msvc-inval.h"
167 chsize_nothrow (int fd, long length)
173 result = _chsize (fd, length);
185 # define chsize_nothrow _chsize
189 ftruncate (int fd, off_t length)
191 return chsize_nothrow (fd, length);