From 7636b58590621af3c341c3eb37a017e0e6598d3f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 7 Aug 2006 19:29:14 +0000 Subject: * autoload.cc (NtSetInformationFile): Define. * cygwin.din: Export posix_fadvise and posix_fallocate. * fhandler.cc (fhandler_base::fadvise): New method. (fhandler_base::ftruncate): Add allow_truncate parameter. * fhandler.h (class fhandler_base): Add fadvise method. Accomodate new parameter to ftruncate. (class fhandler_pipe): Add fadvise and ftruncate methods. (class fhandler_disk_file): Add fadvise method. Accomodate new parameter to ftruncate. * fhandler_disk_file.cc (fhandler_disk_file::fadvise): New method. (fhandler_disk_file::ftruncate): Accomodate new allow_truncate parameter. Set EOF using NtSetInformationFile on NT. * ntdll.h (struct _FILE_END_OF_FILE_INFORMATION): Define. (NtSetInformationFile): Declare. * pipe.cc (fhandler_pipe::fadvise): New method. (fhandler_pipe::ftruncate): Ditto. * syscalls.cc (posix_fadvise): New function. (posix_fallocate): Ditto. (ftruncate64): Accomodate second parameter to fhandler's ftruncate method. * include/fcntl.h: Add POSIX_FADV_* flags. Add declarations of posix_fadvise and posix_fallocate. * include/cygwin/version.h: Bump API minor number. --- winsup/cygwin/ChangeLog | 26 +++++++ winsup/cygwin/autoload.cc | 1 + winsup/cygwin/cygwin.din | 2 + winsup/cygwin/fhandler.cc | 9 ++- winsup/cygwin/fhandler.h | 8 ++- winsup/cygwin/fhandler_disk_file.cc | 125 ++++++++++++++++++++++++++------- winsup/cygwin/include/cygwin/version.h | 3 +- winsup/cygwin/include/fcntl.h | 18 ++++- winsup/cygwin/ntdll.h | 6 ++ winsup/cygwin/pipe.cc | 14 ++++ winsup/cygwin/syscalls.cc | 34 ++++++++- 11 files changed, 213 insertions(+), 33 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f9b288c06..2b97b08f6 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,29 @@ +2006-08-07 Corinna Vinschen + + * autoload.cc (NtSetInformationFile): Define. + * cygwin.din: Export posix_fadvise and posix_fallocate. + * fhandler.cc (fhandler_base::fadvise): New method. + (fhandler_base::ftruncate): Add allow_truncate parameter. + * fhandler.h (class fhandler_base): Add fadvise method. Accomodate + new parameter to ftruncate. + (class fhandler_pipe): Add fadvise and ftruncate methods. + (class fhandler_disk_file): Add fadvise method. Accomodate new + parameter to ftruncate. + * fhandler_disk_file.cc (fhandler_disk_file::fadvise): New method. + (fhandler_disk_file::ftruncate): Accomodate new allow_truncate + parameter. Set EOF using NtSetInformationFile on NT. + * ntdll.h (struct _FILE_END_OF_FILE_INFORMATION): Define. + (NtSetInformationFile): Declare. + * pipe.cc (fhandler_pipe::fadvise): New method. + (fhandler_pipe::ftruncate): Ditto. + * syscalls.cc (posix_fadvise): New function. + (posix_fallocate): Ditto. + (ftruncate64): Accomodate second parameter to fhandler's ftruncate + method. + * include/fcntl.h: Add POSIX_FADV_* flags. Add declarations of + posix_fadvise and posix_fallocate. + * include/cygwin/version.h: Bump API minor number. + 2006-08-02 Christopher Faylor * environ.cc (env_win32_to_posix_path_list): Declare. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index fc73e8bf4..d1d234dee 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -403,6 +403,7 @@ LoadDLLfuncNt (NtQuerySecurityObject, 20, ntdll) LoadDLLfuncNt (NtQueryVirtualMemory, 24, ntdll) LoadDLLfuncNt (NtQueryVolumeInformationFile, 20, ntdll) LoadDLLfuncNt (NtSetEaFile, 16, ntdll) +LoadDLLfuncNt (NtSetInformationFile, 20, ntdll) LoadDLLfuncNt (NtSetSecurityObject, 12, ntdll) LoadDLLfuncNt (NtUnlockVirtualMemory, 16, ntdll) LoadDLLfuncNt (NtUnmapViewOfSection, 8, ntdll) diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index a80ea388f..e8a40ede2 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -976,6 +976,8 @@ poll SIGFE _poll = poll SIGFE popen SIGFE _popen = popen SIGFE +posix_fadvise SIGFE +posix_fallocate SIGFE posix_openpt SIGFE posix_regcomp SIGFE posix_regerror SIGFE diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 06bed1b46..00e987587 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1652,7 +1652,14 @@ fhandler_base::facl (int cmd, int nentries, __aclent32_t *aclbufp) } int -fhandler_base::ftruncate (_off64_t length) +fhandler_base::fadvise (_off64_t offset, _off64_t length, int advice) +{ + set_errno (EINVAL); + return -1; +} + +int +fhandler_base::ftruncate (_off64_t length, bool allow_truncate) { set_errno (EINVAL); return -1; diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index dee16aaea..6103b432c 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -279,7 +279,8 @@ 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 __stdcall fadvise (_off64_t, _off64_t, int) __attribute__ ((regparm (3))); + virtual int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3))); virtual int __stdcall link (const char *) __attribute__ ((regparm (2))); virtual int __stdcall utimes (const struct timeval *) __attribute__ ((regparm (2))); virtual int __stdcall fsync () __attribute__ ((regparm (1))); @@ -536,6 +537,8 @@ public: } int dup (fhandler_base *child); int ioctl (unsigned int cmd, void *); + int __stdcall fadvise (_off64_t, _off64_t, int) __attribute__ ((regparm (3))); + int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3))); void fixup_in_child (); virtual void fixup_after_fork (HANDLE); void fixup_after_exec (); @@ -684,7 +687,8 @@ 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))); + int __stdcall fadvise (_off64_t, _off64_t, int) __attribute__ ((regparm (3))); + int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3))); int __stdcall link (const char *) __attribute__ ((regparm (2))); int __stdcall utimes (const struct timeval *) __attribute__ ((regparm (2))); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 6190e45d2..a8b6dc31f 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -762,11 +762,57 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp) } int -fhandler_disk_file::ftruncate (_off64_t length) +fhandler_disk_file::fadvise (_off64_t offset, _off64_t length, int advice) { - int res = -1, res_bug = 0; + if (advice < POSIX_FADV_NORMAL || advice > POSIX_FADV_NOREUSE) + { + set_errno (EINVAL); + return -1; + } + + if (!wincap.is_winnt ()) + return 0; + + /* Windows only supports advice flags for the whole file. We're using + a simplified test here so that we don't have to ask for the actual + file size. Length == 0 means all bytes starting at offset anyway. + So we only actually follow the advice, if it's given for offset == 0. */ + if (offset != 0) + return 0; + + /* We only support normal and sequential mode for now. Everything which + is not POSIX_FADV_SEQUENTIAL is treated like POSIX_FADV_NORMAL. */ + if (advice != POSIX_FADV_SEQUENTIAL) + advice = POSIX_FADV_NORMAL; + + IO_STATUS_BLOCK io; + FILE_MODE_INFORMATION fmi; + NTSTATUS status = NtQueryInformationFile (get_handle (), &io, + &fmi, sizeof fmi, + FileModeInformation); + if (!NT_SUCCESS (status)) + __seterrno_from_nt_status (status); + else + { + fmi.Mode &= ~FILE_SEQUENTIAL_ONLY; + if (advice == POSIX_FADV_SEQUENTIAL) + fmi.Mode |= FILE_SEQUENTIAL_ONLY; + status = NtSetInformationFile (get_handle (), &io, &fmi, sizeof fmi, + FileModeInformation); + if (NT_SUCCESS (status)) + return 0; + __seterrno_from_nt_status (status); + } + + return -1; +} + +int +fhandler_disk_file::ftruncate (_off64_t length, bool allow_truncate) +{ + int res = -1; - if (length < 0 || !get_output_handle ()) + if (length < 0 || !get_handle ()) set_errno (EINVAL); else if (pc.isdir ()) set_errno (EISDIR); @@ -774,33 +820,58 @@ fhandler_disk_file::ftruncate (_off64_t length) 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_handle (), &size_high); + actual_length += ((_off64_t) size_high) << 32; + + /* If called through posix_fallocate, silently succeed if length + is less than the file's actual length. */ + if (!allow_truncate && length < actual_length) + return 0; + + if (wincap.is_winnt ()) + { + NTSTATUS status; + IO_STATUS_BLOCK io; + FILE_END_OF_FILE_INFORMATION feofi; + + feofi.EndOfFile.QuadPart = length; + /* Create sparse files only when called through ftruncate, not when + called through posix_fallocate. */ + if (allow_truncate + && get_fs_flags (FILE_SUPPORTS_SPARSE_FILES) + && length >= actual_length + (128 * 1024)) { - _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 ()); - } + DWORD dw; + BOOL r = DeviceIoControl (get_handle (), + FSCTL_SET_SPARSE, NULL, 0, NULL, + 0, &dw, NULL); + syscall_printf ("%d = DeviceIoControl(%p, FSCTL_SET_SPARSE)", + r, get_handle ()); } - else if (wincap.has_lseek_bug ()) - res_bug = write (&res, 0); - if (!SetEndOfFile (get_output_handle ())) - __seterrno (); + status = NtSetInformationFile (get_handle (), &io, + &feofi, sizeof feofi, + FileEndOfFileInformation); + if (!NT_SUCCESS (status)) + __seterrno_from_nt_status (status); else - res = res_bug; - /* restore original file pointer location */ - lseek (prev_loc, SEEK_SET); + res = 0; + } + else + { + _off64_t prev_loc = lseek (0, SEEK_CUR); + if (lseek (length, SEEK_SET) >= 0) + { + int res_bug = write (&res, 0); + if (!SetEndOfFile (get_handle ())) + __seterrno (); + else + res = res_bug; + /* restore original file pointer location */ + lseek (prev_loc, SEEK_SET); + } + } } return res; diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index be660c61a..30ae75800 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -294,12 +294,13 @@ details. */ 158: Export bindresvport, bindresvport_sa, iruserok_sa, rcmd_af, rresvport_af. 159: Export posix_openpt. + 160: Export posix_fadvice, posix_fallocate. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 159 +#define CYGWIN_VERSION_API_MINOR 160 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/fcntl.h b/winsup/cygwin/include/fcntl.h index 6e50b3304..3e88f35f4 100644 --- a/winsup/cygwin/include/fcntl.h +++ b/winsup/cygwin/include/fcntl.h @@ -1,6 +1,6 @@ /* fcntl.h - Copyright 1996, 1998, 2001, 2005 Red Hat, Inc. + Copyright 1996, 1998, 2001, 2005, 2006 Red Hat, Inc. This file is part of Cygwin. @@ -23,4 +23,20 @@ details. */ #define O_DSYNC _FSYNC #define O_RSYNC _FSYNC +#define POSIX_FADV_NORMAL 0 +#define POSIX_FADV_SEQUENTIAL 1 +#define POSIX_FADV_RANDOM 2 +#define POSIX_FADV_WILLNEED 3 +#define POSIX_FADV_DONTNEED 4 +#define POSIX_FADV_NOREUSE 5 + +#ifdef __cplusplus +extern "C" { +#endif +extern int posix_fadvise _PARAMS ((int, off_t, off_t, int)); +extern int posix_fallocate _PARAMS ((int, off_t, off_t)); +#ifdef __cplusplus +} +#endif + #endif /* _FCNTL_H */ diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 2a71cd8f6..0855a878e 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -484,6 +484,10 @@ typedef struct _FILE_POSITION_INFORMATION { LARGE_INTEGER CurrentByteOffset; } FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; +typedef struct _FILE_END_OF_FILE_INFORMATION { + LARGE_INTEGER EndOfFile; +} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; + typedef struct _FILE_MODE_INFORMATION { ULONG Mode; } FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; @@ -646,6 +650,8 @@ extern "C" VOID *, ULONG, FS_INFORMATION_CLASS); NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG); + NTSTATUS NTAPI NtSetInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, + FILE_INFORMATION_CLASS); NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR); NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG); diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index a6171f2f9..d56b32aff 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -151,6 +151,20 @@ fhandler_pipe::lseek (_off64_t offset, int whence) return -1; } +int +fhandler_pipe::fadvise (_off64_t offset, _off64_t length, int advice) +{ + set_errno (ESPIPE); + return -1; +} + +int +fhandler_pipe::ftruncate (_off64_t length, bool allow_truncate) +{ + set_errno (allow_truncate ? EINVAL : ESPIPE); + return -1; +} + void fhandler_pipe::set_close_on_exec (bool val) { diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index a8b7aa815..c56cb58f0 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1752,13 +1752,45 @@ cygwin_setmode (int fd, int mode) return res; } +extern "C" int +posix_fadvise (int fd, _off64_t offset, _off64_t len, int advice) +{ + int res = -1; + cygheap_fdget cfd (fd); + if (cfd >= 0) + res = cfd->fadvise (offset, len, advice); + else + set_errno (EBADF); + syscall_printf ("%d = posix_fadvice (%d, %D, %D, %d)", + res, fd, offset, len, advice); + return res; +} + +extern "C" int +posix_fallocate (int fd, _off64_t offset, _off64_t len) +{ + int res = -1; + if (offset < 0 || len == 0) + set_errno (EINVAL); + else + { + cygheap_fdget cfd (fd); + if (cfd >= 0) + res = cfd->ftruncate (offset + len, false); + else + set_errno (EBADF); + } + syscall_printf ("%d = posix_fallocate (%d, %D, %D)", res, fd, offset, len); + return res; +} + extern "C" int ftruncate64 (int fd, _off64_t length) { int res = -1; cygheap_fdget cfd (fd); if (cfd >= 0) - res = cfd->ftruncate (length); + res = cfd->ftruncate (length, true); else set_errno (EBADF); syscall_printf ("%d = ftruncate (%d, %D)", res, fd, length); -- cgit v1.2.3