From fac297d5f84d06ec41652c42f410f105dd904b67 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 26 May 2003 09:54:01 +0000 Subject: * fhandler.h: Rename FH_W95LSBUG flag to FH_LSEEKED. (fhandler_base::set_did_lseek): Rename from set_check_win95_lseek_bug. (fhandler_base::get_did_lseek): Rename from get_check_win95_lseek_bug. (fhandler_base::set_fs_flags): New method. (fhandler_base::get_fs_flags): Ditto. * fhandler.cc (fhandler_base::write): Make 64 bit clean. Convert file to a "sparse" file when writing after a long lseek (>64K) beyond EOF. (fhandler_base::lseek): Call set_did_lseek() instead of set_check_win95_lseek_bug(). (fhandler_base::fhandler_base): Initialize fs_flags to 0. * fhandler_disk_file.cc (fhandler_disk_file::open): Don't create files as "sparse" unconditionally. Set fs_flags member. --- winsup/cygwin/fhandler.cc | 102 ++++++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 36 deletions(-) (limited to 'winsup/cygwin/fhandler.cc') diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index bdbe2883d..83302dd73 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -27,6 +27,7 @@ details. */ #include "pinfo.h" #include #include +#include static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ @@ -610,47 +611,75 @@ fhandler_base::write (const void *ptr, size_t len) if (get_append_p ()) SetFilePointer (get_handle (), 0, 0, FILE_END); - else if (wincap.has_lseek_bug () && get_check_win95_lseek_bug ()) + else if (get_did_lseek ()) { - /* Note: this bug doesn't happen on NT4, even though the documentation - for WriteFile() says that it *may* happen on any OS. */ - int actual_length, current_position; - set_check_win95_lseek_bug (0); /* don't do it again */ - actual_length = GetFileSize (get_handle (), NULL); - current_position = SetFilePointer (get_handle (), 0, 0, FILE_CURRENT); + _off64_t actual_length, current_position; + DWORD size_high = 0; + LONG pos_high = 0; + + set_did_lseek (0); /* don't do it again */ + + actual_length = GetFileSize (get_handle (), &size_high); + actual_length += ((_off64_t) size_high) << 32; + + current_position = SetFilePointer (get_handle (), 0, &pos_high, + FILE_CURRENT); + current_position += ((_off64_t) pos_high) << 32; + if (current_position > actual_length) { - /* Oops, this is the bug case - Win95 uses whatever is on the disk - instead of some known (safe) value, so we must seek back and - fill in the gap with zeros. - DJ */ - char zeros[512]; - int number_of_zeros_to_write = current_position - actual_length; - memset (zeros, 0, 512); - SetFilePointer (get_handle (), 0, 0, FILE_END); - while (number_of_zeros_to_write > 0) + if ((get_fs_flags (FILE_SUPPORTS_SPARSE_FILES)) + && current_position >= actual_length + (64 * 1024)) { - DWORD zeros_this_time = (number_of_zeros_to_write > 512 - ? 512 : number_of_zeros_to_write); - DWORD written; - if (!WriteFile (get_handle (), zeros, zeros_this_time, &written, - NULL)) - { - __seterrno (); - if (get_errno () == EPIPE) - raise (SIGPIPE); - /* This might fail, but it's the best we can hope for */ - SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN); - return -1; - - } - if (written < zeros_this_time) /* just in case */ + /* If the file systemn supports sparse files and the application + is writing after a long seek beyond EOF, convert the file to + a sparse file. */ + DWORD dw; + HANDLE h = get_handle (); + BOOL r = DeviceIoControl (h, FSCTL_SET_SPARSE, NULL, 0, NULL, + 0, &dw, NULL); + syscall_printf ("%d = DeviceIoControl(0x%x, FSCTL_SET_SPARSE, " + "NULL, 0, NULL, 0, &dw, NULL)", r, h); + } + else if (wincap.has_lseek_bug ()) + { + /* Oops, this is the bug case - Win95 uses whatever is on the + disk instead of some known (safe) value, so we must seek + back and fill in the gap with zeros. - DJ + Note: this bug doesn't happen on NT4, even though the + documentation for WriteFile() says that it *may* happen + on any OS. */ + char zeros[512]; + int number_of_zeros_to_write = current_position - actual_length; + memset (zeros, 0, 512); + SetFilePointer (get_handle (), 0, NULL, FILE_END); + while (number_of_zeros_to_write > 0) { - set_errno (ENOSPC); - /* This might fail, but it's the best we can hope for */ - SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN); - return -1; + DWORD zeros_this_time = (number_of_zeros_to_write > 512 + ? 512 : number_of_zeros_to_write); + DWORD written; + if (!WriteFile (get_handle (), zeros, zeros_this_time, + &written, NULL)) + { + __seterrno (); + if (get_errno () == EPIPE) + raise (SIGPIPE); + /* This might fail, but it's the best we can hope for */ + SetFilePointer (get_handle (), current_position, NULL, + FILE_BEGIN); + return -1; + + } + if (written < zeros_this_time) /* just in case */ + { + set_errno (ENOSPC); + /* This might fail, but it's the best we can hope for */ + SetFilePointer (get_handle (), current_position, NULL, + FILE_BEGIN); + return -1; + } + number_of_zeros_to_write -= written; } - number_of_zeros_to_write -= written; } } } @@ -876,7 +905,7 @@ fhandler_base::lseek (_off64_t offset, int whence) { /* When next we write(), we will check to see if *this* seek went beyond the end of the file, and back-seek and fill with zeros if so - DJ */ - set_check_win95_lseek_bug (); + set_did_lseek (); /* If this was a SEEK_CUR with offset 0, we still might have readahead that we have to take into account when calculating @@ -1165,6 +1194,7 @@ fhandler_base::fhandler_base (DWORD devtype, int unit): unix_path_name (NULL), win32_path_name (NULL), open_status (0), + fs_flags (0), read_state (NULL) { } -- cgit v1.2.3