summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_disk_file.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-02-02 22:42:06 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-02-02 22:42:06 +0000
commit3fd68a6a044e674d434353d5631aba2743e0bf89 (patch)
tree9f507acf3ea9c2c357cf233519a2d178dbf3b929 /winsup/cygwin/fhandler_disk_file.cc
parent7823d9bb14798143e9791303186c7129336356dd (diff)
downloadcygnal-3fd68a6a044e674d434353d5631aba2743e0bf89.tar.gz
cygnal-3fd68a6a044e674d434353d5631aba2743e0bf89.tar.bz2
cygnal-3fd68a6a044e674d434353d5631aba2743e0bf89.zip
* fhandler.h (fhandler_base::ftruncate): Define new virtual method.
(fhandler_disk_file::ftruncate): Ditto. * fhandler.cc (fhandler_base::ftruncate): New method. * fhandler_disk_file.cc (fhandler_disk_file::ftruncate): Ditto. * syscalls.cc (ftruncate64): Move functionality into fhandlers. Call fhandler method from here.
Diffstat (limited to 'winsup/cygwin/fhandler_disk_file.cc')
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc48
1 files changed, 48 insertions, 0 deletions
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index d8e0c16f7..96d3c0ecf 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -29,6 +29,7 @@ details. */
#include "ntdll.h"
#include <assert.h>
#include <ctype.h>
+#include <winioctl.h>
#define _COMPILING_NEWLIB
#include <dirent.h>
@@ -589,6 +590,53 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
return res;
}
+int
+fhandler_disk_file::ftruncate (_off64_t length)
+{
+ int res = -1, res_bug = 0;
+
+ if (length < 0 || !get_output_handle ())
+ set_errno (EINVAL);
+ else if (pc.isdir ())
+ set_errno (EISDIR);
+ else if (!(get_access () & GENERIC_WRITE))
+ set_errno (EBADF);
+ else
+ {
+ _off64_t prev_loc = lseek (0, SEEK_CUR);
+ if (lseek (length, SEEK_SET) > 0)
+ {
+ if (get_fs_flags (FILE_SUPPORTS_SPARSE_FILES))
+ {
+ _off64_t actual_length;
+ DWORD size_high = 0;
+ actual_length = GetFileSize (get_output_handle (), &size_high);
+ actual_length += ((_off64_t) size_high) << 32;
+ if (length >= actual_length + (128 * 1024))
+ {
+ DWORD dw;
+ BOOL r = DeviceIoControl (get_output_handle (),
+ FSCTL_SET_SPARSE, NULL, 0, NULL,
+ 0, &dw, NULL);
+ syscall_printf ("%d = DeviceIoControl(%p, FSCTL_SET_SPARSE)",
+ r, get_output_handle ());
+ }
+ }
+ else if (wincap.has_lseek_bug ())
+ res_bug = write (&res, 0);
+ if (!SetEndOfFile (get_output_handle ()))
+ __seterrno ();
+ else
+ res = res_bug;
+ /* restore original file pointer location */
+ lseek (prev_loc, SEEK_SET);
+ if (!res)
+ touch_ctime ();
+ }
+ }
+ return res;
+}
+
fhandler_disk_file::fhandler_disk_file () :
fhandler_base ()
{