root/maint/gnulib/lib/ftruncate.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SetFileSize
  2. ftruncate
  3. chsize_nothrow
  4. ftruncate

   1 /* ftruncate emulations for native Windows.
   2    Copyright (C) 1992-2021 Free Software Foundation, Inc.
   3 
   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)
   7    any later version.
   8 
   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.
  13 
  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/>.  */
  16 
  17 #include <config.h>
  18 
  19 /* Specification.  */
  20 #include <unistd.h>
  21 
  22 #if HAVE__CHSIZE
  23 /* A native Windows platform.  */
  24 
  25 # include <errno.h>
  26 
  27 # if _GL_WINDOWS_64_BIT_OFF_T
  28 
  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.  */
  31 
  32 /* Ensure that <windows.h> declares GetFileSizeEx.  */
  33 #  if !defined _WIN32_WINNT || (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
  34 #   undef _WIN32_WINNT
  35 #   define _WIN32_WINNT _WIN32_WINNT_WIN2K
  36 #  endif
  37 
  38 /* Get declarations of the native Windows API functions.  */
  39 #  define WIN32_LEAN_AND_MEAN
  40 #  include <windows.h>
  41 
  42 /* Get _get_osfhandle.  */
  43 #  if GNULIB_MSVC_NOTHROW
  44 #   include "msvc-nothrow.h"
  45 #  else
  46 #   include <io.h>
  47 #  endif
  48 
  49 static BOOL
  50 SetFileSize (HANDLE h, LONGLONG size)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52   LARGE_INTEGER old_size;
  53 
  54   if (!GetFileSizeEx (h, &old_size))
  55     return FALSE;
  56 
  57   if (size != old_size.QuadPart)
  58     {
  59       /* Duplicate the handle, so we are free to modify its file position.  */
  60       HANDLE curr_process = GetCurrentProcess ();
  61       HANDLE tmph;
  62 
  63       if (!DuplicateHandle (curr_process,           /* SourceProcessHandle */
  64                             h,                      /* SourceHandle */
  65                             curr_process,           /* TargetProcessHandle */
  66                             (PHANDLE) &tmph,        /* TargetHandle */
  67                             (DWORD) 0,              /* DesiredAccess */
  68                             FALSE,                  /* InheritHandle */
  69                             DUPLICATE_SAME_ACCESS)) /* Options */
  70         return FALSE;
  71 
  72       if (size < old_size.QuadPart)
  73         {
  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)
  79             {
  80               CloseHandle (tmph);
  81               return FALSE;
  82             }
  83           if (!SetEndOfFile (tmph))
  84             {
  85               CloseHandle (tmph);
  86               return FALSE;
  87             }
  88         }
  89       else
  90         {
  91           /* Increase the size by adding zero bytes at the end.  */
  92           static char zero_bytes[1024];
  93           LONG pos_hi = 0;
  94           LONG pos_lo = SetFilePointer (tmph, (LONG) 0, &pos_hi, FILE_END);
  95           LONGLONG pos;
  96           if (pos_lo == INVALID_SET_FILE_POINTER
  97               && GetLastError() != NO_ERROR)
  98             {
  99               CloseHandle (tmph);
 100               return FALSE;
 101             }
 102           pos = ((LONGLONG) pos_hi << 32) | (ULONGLONG) (ULONG) pos_lo;
 103           while (pos < size)
 104             {
 105               DWORD written;
 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)
 110                   || written == 0)
 111                 {
 112                   CloseHandle (tmph);
 113                   return FALSE;
 114                 }
 115               pos += (ULONGLONG) (ULONG) written;
 116             }
 117         }
 118       /* Close the handle.  */
 119       CloseHandle (tmph);
 120     }
 121   return TRUE;
 122 }
 123 
 124 int
 125 ftruncate (int fd, off_t length)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127   HANDLE handle = (HANDLE) _get_osfhandle (fd);
 128 
 129   if (handle == INVALID_HANDLE_VALUE)
 130     {
 131       errno = EBADF;
 132       return -1;
 133     }
 134   if (length < 0)
 135     {
 136       errno = EINVAL;
 137       return -1;
 138     }
 139   if (!SetFileSize (handle, length))
 140     {
 141       switch (GetLastError ())
 142         {
 143         case ERROR_ACCESS_DENIED:
 144           errno = EACCES;
 145           break;
 146         case ERROR_HANDLE_DISK_FULL:
 147         case ERROR_DISK_FULL:
 148         case ERROR_DISK_TOO_FRAGMENTED:
 149           errno = ENOSPC;
 150           break;
 151         default:
 152           errno = EIO;
 153           break;
 154         }
 155       return -1;
 156     }
 157   return 0;
 158 }
 159 
 160 # else
 161 
 162 #  include <io.h>
 163 
 164 #  if HAVE_MSVC_INVALID_PARAMETER_HANDLER
 165 #   include "msvc-inval.h"
 166 static int
 167 chsize_nothrow (int fd, long length)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169   int result;
 170 
 171   TRY_MSVC_INVAL
 172     {
 173       result = _chsize (fd, length);
 174     }
 175   CATCH_MSVC_INVAL
 176     {
 177       result = -1;
 178       errno = EBADF;
 179     }
 180   DONE_MSVC_INVAL;
 181 
 182   return result;
 183 }
 184 #  else
 185 #   define chsize_nothrow _chsize
 186 #  endif
 187 
 188 int
 189 ftruncate (int fd, off_t length)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191   return chsize_nothrow (fd, length);
 192 }
 193 
 194 # endif
 195 #endif

/* [previous][next][first][last][top][bottom][index][help] */