* 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.
This commit is contained in:
Corinna Vinschen
2003-05-26 09:54:01 +00:00
parent 7b3a9e6e00
commit fac297d5f8
4 changed files with 91 additions and 53 deletions

View File

@ -27,6 +27,7 @@ details. */
#include "pinfo.h"
#include <assert.h>
#include <limits.h>
#include <winioctl.h>
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))
/* 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)
{
__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;
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;
}
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, 0, FILE_BEGIN);
return -1;
}
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)
{
}