|
Packit Service |
4684c1 |
/* ftruncate emulations for native Windows.
|
|
Packit Service |
4684c1 |
Copyright (C) 1992-2020 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
4684c1 |
it under the terms of the GNU General Public License as published by
|
|
Packit Service |
4684c1 |
the Free Software Foundation; either version 3, or (at your option)
|
|
Packit Service |
4684c1 |
any later version.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
This program is distributed in the hope that it will be useful,
|
|
Packit Service |
4684c1 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
4684c1 |
GNU General Public License for more details.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
You should have received a copy of the GNU General Public License along
|
|
Packit Service |
4684c1 |
with this program; if not, see <https://www.gnu.org/licenses/>. */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <config.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Specification. */
|
|
Packit Service |
4684c1 |
#include <unistd.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#if HAVE_CHSIZE
|
|
Packit Service |
4684c1 |
/* A native Windows platform. */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
# include <errno.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
# if _GL_WINDOWS_64_BIT_OFF_T
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Large File Support: off_t is 64-bit, but chsize() takes only a 32-bit
|
|
Packit Service |
4684c1 |
argument. So, define a 64-bit safe SetFileSize function ourselves. */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Ensure that <windows.h> declares GetFileSizeEx. */
|
|
Packit Service |
4684c1 |
# if !defined _WIN32_WINNT || (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
|
|
Packit Service |
4684c1 |
# undef _WIN32_WINNT
|
|
Packit Service |
4684c1 |
# define _WIN32_WINNT _WIN32_WINNT_WIN2K
|
|
Packit Service |
4684c1 |
# endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get declarations of the native Windows API functions. */
|
|
Packit Service |
4684c1 |
# define WIN32_LEAN_AND_MEAN
|
|
Packit Service |
4684c1 |
# include <windows.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get _get_osfhandle. */
|
|
Packit Service |
4684c1 |
# if GNULIB_MSVC_NOTHROW
|
|
Packit Service |
4684c1 |
# include "msvc-nothrow.h"
|
|
Packit Service |
4684c1 |
# else
|
|
Packit Service |
4684c1 |
# include <io.h>
|
|
Packit Service |
4684c1 |
# endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static BOOL
|
|
Packit Service |
4684c1 |
SetFileSize (HANDLE h, LONGLONG size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
LARGE_INTEGER old_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!GetFileSizeEx (h, &old_size))
|
|
Packit Service |
4684c1 |
return FALSE;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (size != old_size.QuadPart)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* Duplicate the handle, so we are free to modify its file position. */
|
|
Packit Service |
4684c1 |
HANDLE curr_process = GetCurrentProcess ();
|
|
Packit Service |
4684c1 |
HANDLE tmph;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
|
|
Packit Service |
4684c1 |
h, /* SourceHandle */
|
|
Packit Service |
4684c1 |
curr_process, /* TargetProcessHandle */
|
|
Packit Service |
4684c1 |
(PHANDLE) &tmph, /* TargetHandle */
|
|
Packit Service |
4684c1 |
(DWORD) 0, /* DesiredAccess */
|
|
Packit Service |
4684c1 |
FALSE, /* InheritHandle */
|
|
Packit Service |
4684c1 |
DUPLICATE_SAME_ACCESS)) /* Options */
|
|
Packit Service |
4684c1 |
return FALSE;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (size < old_size.QuadPart)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* Reduce the size. */
|
|
Packit Service |
4684c1 |
LONG size_hi = (LONG) (size >> 32);
|
|
Packit Service |
4684c1 |
if (SetFilePointer (tmph, (LONG) size, &size_hi, FILE_BEGIN)
|
|
Packit Service |
4684c1 |
== INVALID_SET_FILE_POINTER
|
|
Packit Service |
4684c1 |
&& GetLastError() != NO_ERROR)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
CloseHandle (tmph);
|
|
Packit Service |
4684c1 |
return FALSE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (!SetEndOfFile (tmph))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
CloseHandle (tmph);
|
|
Packit Service |
4684c1 |
return FALSE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* Increase the size by adding zero bytes at the end. */
|
|
Packit Service |
4684c1 |
static char zero_bytes[1024];
|
|
Packit Service |
4684c1 |
LONG pos_hi = 0;
|
|
Packit Service |
4684c1 |
LONG pos_lo = SetFilePointer (tmph, (LONG) 0, &pos_hi, FILE_END);
|
|
Packit Service |
4684c1 |
LONGLONG pos;
|
|
Packit Service |
4684c1 |
if (pos_lo == INVALID_SET_FILE_POINTER
|
|
Packit Service |
4684c1 |
&& GetLastError() != NO_ERROR)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
CloseHandle (tmph);
|
|
Packit Service |
4684c1 |
return FALSE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
pos = ((LONGLONG) pos_hi << 32) | (ULONGLONG) (ULONG) pos_lo;
|
|
Packit Service |
4684c1 |
while (pos < size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
DWORD written;
|
|
Packit Service |
4684c1 |
LONGLONG count = size - pos;
|
|
Packit Service |
4684c1 |
if (count > sizeof (zero_bytes))
|
|
Packit Service |
4684c1 |
count = sizeof (zero_bytes);
|
|
Packit Service |
4684c1 |
if (!WriteFile (tmph, zero_bytes, (DWORD) count, &written, NULL)
|
|
Packit Service |
4684c1 |
|| written == 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
CloseHandle (tmph);
|
|
Packit Service |
4684c1 |
return FALSE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
pos += (ULONGLONG) (ULONG) written;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
/* Close the handle. */
|
|
Packit Service |
4684c1 |
CloseHandle (tmph);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return TRUE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
ftruncate (int fd, off_t length)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
HANDLE handle = (HANDLE) _get_osfhandle (fd);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle == INVALID_HANDLE_VALUE)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
errno = EBADF;
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (length < 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
errno = EINVAL;
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (!SetFileSize (handle, length))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
switch (GetLastError ())
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
case ERROR_ACCESS_DENIED:
|
|
Packit Service |
4684c1 |
errno = EACCES;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
case ERROR_HANDLE_DISK_FULL:
|
|
Packit Service |
4684c1 |
case ERROR_DISK_FULL:
|
|
Packit Service |
4684c1 |
case ERROR_DISK_TOO_FRAGMENTED:
|
|
Packit Service |
4684c1 |
errno = ENOSPC;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
errno = EIO;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
# else
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
# include <io.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
|
|
Packit Service |
4684c1 |
# include "msvc-inval.h"
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
chsize_nothrow (int fd, long length)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
TRY_MSVC_INVAL
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
result = chsize (fd, length);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
CATCH_MSVC_INVAL
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
result = -1;
|
|
Packit Service |
4684c1 |
errno = EBADF;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
DONE_MSVC_INVAL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
# else
|
|
Packit Service |
4684c1 |
# define chsize_nothrow chsize
|
|
Packit Service |
4684c1 |
# endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
ftruncate (int fd, off_t length)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return chsize_nothrow (fd, length);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
# endif
|
|
Packit Service |
4684c1 |
#endif
|