diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 282b8c67c..99bcc9370 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +2005-02-02 Corinna Vinschen + + * 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. + 2005-02-02 Corinna Vinschen * pipe.cc (fhandler_pipe::dup): Fix conditionals in case of error. diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 5f60d0eb2..aa996ea56 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1,6 +1,7 @@ /* fhandler.cc. See console.cc for fhandler_console functions. - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005 Red Hat, Inc. This file is part of Cygwin. @@ -814,8 +815,8 @@ fhandler_base::write (const void *ptr, size_t len) HANDLE h = get_output_handle (); BOOL r = DeviceIoControl (h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dw, NULL); - syscall_printf ("%d = DeviceIoControl(%p, FSCTL_SET_SPARSE, " - "NULL, 0, NULL, 0, &dw, NULL)", r, h); + syscall_printf ("%d = DeviceIoControl(%p, FSCTL_SET_SPARSE)", + r, h); } else if (wincap.has_lseek_bug ()) { @@ -1595,3 +1596,10 @@ fhandler_base::facl (int cmd, int nentries, __aclent32_t *aclbufp) } return res; } + +int +fhandler_base::ftruncate (_off64_t length) +{ + set_errno (EINVAL); + return -1; +} diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 4aaafe831..f710356bf 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1,6 +1,7 @@ /* fhandler.h - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005 Red Hat, Inc. This file is part of Cygwin. @@ -250,6 +251,7 @@ class fhandler_base virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); virtual int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); virtual int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); + virtual int __stdcall ftruncate (_off64_t) __attribute__ ((regparm (2))); virtual int ioctl (unsigned int cmd, void *); virtual int fcntl (int cmd, void *); virtual char const *ttyname () { return get_name (); } @@ -590,6 +592,7 @@ class fhandler_disk_file: public fhandler_base int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); + int __stdcall ftruncate (_off64_t) __attribute__ ((regparm (2))); HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, _off64_t off); int munmap (HANDLE h, caddr_t addr, size_t len); 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 #include +#include #define _COMPILING_NEWLIB #include @@ -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 () { diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 8548f5e4a..d4f497246 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1737,37 +1737,12 @@ setmode (int fd, int mode) extern "C" int ftruncate64 (int fd, _off64_t length) { - int res = -1, res_bug = 0; - - if (length < 0) - set_errno (EINVAL); + int res = -1; + cygheap_fdget cfd (fd); + if (cfd >= 0) + res = cfd->ftruncate (length); else - { - cygheap_fdget cfd (fd); - if (cfd >= 0) - { - HANDLE h = cygheap->fdtab[fd]->get_handle (); - - if (cfd->get_handle ()) - { - /* remember curr file pointer location */ - _off64_t prev_loc = cfd->lseek (0, SEEK_CUR); - - cfd->lseek (length, SEEK_SET); - /* Fill the space with 0, if needed */ - if (wincap.has_lseek_bug ()) - res_bug = cfd->write (&res, 0); - if (!SetEndOfFile (h)) - __seterrno (); - else - res = res_bug; - - /* restore original file pointer location */ - cfd->lseek (prev_loc, SEEK_SET); - } - } - } - + set_errno (EBADF); syscall_printf ("%d = ftruncate (%d, %D)", res, fd, length); return res; }