summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_disk_file.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-08-07 19:29:14 +0000
committerCorinna Vinschen <corinna@vinschen.de>2006-08-07 19:29:14 +0000
commit7636b58590621af3c341c3eb37a017e0e6598d3f (patch)
tree7105f91a629f9f9d14224b6405442cf841cf875f /winsup/cygwin/fhandler_disk_file.cc
parent76ddec15abf7557374341c96f999b4965bc10d8d (diff)
downloadcygnal-7636b58590621af3c341c3eb37a017e0e6598d3f.tar.gz
cygnal-7636b58590621af3c341c3eb37a017e0e6598d3f.tar.bz2
cygnal-7636b58590621af3c341c3eb37a017e0e6598d3f.zip
* 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.
Diffstat (limited to 'winsup/cygwin/fhandler_disk_file.cc')
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc125
1 files changed, 98 insertions, 27 deletions
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;