* fhandler.cc (is_at_eof): Rewrite using NT functions.
(off_current): New static variable. (off_append): Ditto. (fhandler_base::raw_write): Use NtWriteFile. Accommodate O_APPEND here. (fhandler_base::write): Drop O_APPEND hack. Use NT functions. (fhandler_base::lseek): Rewrite using NT functions. * fhandler_disk_file.cc (fhandler_disk_file::fstatvfs): Add space in debug output. (fhandler_disk_file::ftruncate): Ditto. * ntdll.h (STATUS_DISK_FULL): Define. (FILE_USE_FILE_POINTER_POSITION): Define. (FILE_WRITE_TO_END_OF_FILE): Define.
This commit is contained in:
parent
c99e78b85c
commit
6ce2c24121
|
@ -1,4 +1,19 @@
|
|||
2007-10-12 Corinna Vinschen <corinna@vinschen.de>
|
||||
2007-10-14 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler.cc (is_at_eof): Rewrite using NT functions.
|
||||
(off_current): New static variable.
|
||||
(off_append): Ditto.
|
||||
(fhandler_base::raw_write): Use NtWriteFile. Accommodate O_APPEND here.
|
||||
(fhandler_base::write): Drop O_APPEND hack. Use NT functions.
|
||||
(fhandler_base::lseek): Rewrite using NT functions.
|
||||
* fhandler_disk_file.cc (fhandler_disk_file::fstatvfs): Add space in
|
||||
debug output.
|
||||
(fhandler_disk_file::ftruncate): Ditto.
|
||||
* ntdll.h (STATUS_DISK_FULL): Define.
|
||||
(FILE_USE_FILE_POINTER_POSITION): Define.
|
||||
(FILE_WRITE_TO_END_OF_FILE): Define.
|
||||
|
||||
2007-10-13 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* ntdll.h (STATUS_END_OF_FILE): Define.
|
||||
* path.cc (symlink_info::check_shortcut): Use NT function to get file
|
||||
|
|
|
@ -171,17 +171,16 @@ char *fhandler_base::get_proc_fd_name (char *buf)
|
|||
static int __stdcall
|
||||
is_at_eof (HANDLE h, DWORD err)
|
||||
{
|
||||
DWORD size, upper1, curr;
|
||||
|
||||
size = GetFileSize (h, &upper1);
|
||||
if (size != INVALID_FILE_SIZE || GetLastError () == NO_ERROR)
|
||||
{
|
||||
LONG upper2 = 0;
|
||||
curr = SetFilePointer (h, 0, &upper2, FILE_CURRENT);
|
||||
if (curr == size && upper1 == (DWORD) upper2)
|
||||
return 1;
|
||||
}
|
||||
IO_STATUS_BLOCK io;
|
||||
FILE_POSITION_INFORMATION fpi;
|
||||
FILE_STANDARD_INFORMATION fsi;
|
||||
|
||||
if (NT_SUCCESS (NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
|
||||
FileStandardInformation))
|
||||
&& NT_SUCCESS (NtQueryInformationFile (h, &io, &fpi, sizeof fpi,
|
||||
FilePositionInformation))
|
||||
&& fsi.EndOfFile.QuadPart == fpi.CurrentByteOffset.QuadPart)
|
||||
return 1;
|
||||
SetLastError (err);
|
||||
return 0;
|
||||
}
|
||||
|
@ -284,22 +283,30 @@ retry:
|
|||
|
||||
/* Cover function to WriteFile to provide Posix interface and semantics
|
||||
(as much as possible). */
|
||||
static LARGE_INTEGER off_current = { QuadPart:FILE_USE_FILE_POINTER_POSITION };
|
||||
static LARGE_INTEGER off_append = { QuadPart:FILE_WRITE_TO_END_OF_FILE };
|
||||
|
||||
int
|
||||
fhandler_base::raw_write (const void *ptr, size_t len)
|
||||
{
|
||||
DWORD bytes_written;
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
||||
if (!WriteFile (get_output_handle (), ptr, len, &bytes_written, 0))
|
||||
status = NtWriteFile (get_output_handle (), NULL, NULL, NULL, &io,
|
||||
(PVOID) ptr, len,
|
||||
(get_flags () & O_APPEND) ? &off_append : &off_current,
|
||||
NULL);
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
if (GetLastError () == ERROR_DISK_FULL && bytes_written > 0)
|
||||
if (status == STATUS_DISK_FULL && io.Information > 0)
|
||||
goto written;
|
||||
__seterrno ();
|
||||
__seterrno_from_nt_status (status);
|
||||
if (get_errno () == EPIPE)
|
||||
raise (SIGPIPE);
|
||||
return -1;
|
||||
}
|
||||
written:
|
||||
return bytes_written;
|
||||
return io.Information;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -697,45 +704,33 @@ int
|
|||
fhandler_base::write (const void *ptr, size_t len)
|
||||
{
|
||||
int res;
|
||||
IO_STATUS_BLOCK io;
|
||||
FILE_POSITION_INFORMATION fpi;
|
||||
FILE_STANDARD_INFORMATION fsi;
|
||||
|
||||
if (get_flags () & O_APPEND)
|
||||
if (did_lseek ())
|
||||
{
|
||||
LONG off_high = 0;
|
||||
DWORD ret = SetFilePointer (get_output_handle (), 0, &off_high, FILE_END);
|
||||
if (ret == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
|
||||
{
|
||||
debug_printf ("Seeking to EOF in append mode failed");
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (did_lseek ())
|
||||
{
|
||||
_off64_t actual_length, current_position;
|
||||
DWORD size_high = 0;
|
||||
LONG pos_high = 0;
|
||||
|
||||
did_lseek (false); /* don't do it again */
|
||||
|
||||
actual_length = GetFileSize (get_output_handle (), &size_high);
|
||||
actual_length += ((_off64_t) size_high) << 32;
|
||||
|
||||
current_position = SetFilePointer (get_output_handle (), 0, &pos_high,
|
||||
FILE_CURRENT);
|
||||
current_position += ((_off64_t) pos_high) << 32;
|
||||
|
||||
if (current_position >= actual_length + (128 * 1024)
|
||||
if (!(get_flags () & O_APPEND)
|
||||
&& NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
|
||||
&io, &fsi, sizeof fsi,
|
||||
FileStandardInformation))
|
||||
&& NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
|
||||
&io, &fpi, sizeof fpi,
|
||||
FilePositionInformation))
|
||||
&& fpi.CurrentByteOffset.QuadPart
|
||||
>= fsi.EndOfFile.QuadPart + (128 * 1024)
|
||||
&& get_fs_flags (FILE_SUPPORTS_SPARSE_FILES))
|
||||
{
|
||||
/* If the file system 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_output_handle ();
|
||||
BOOL r = DeviceIoControl (h, FSCTL_SET_SPARSE, NULL, 0, NULL,
|
||||
0, &dw, NULL);
|
||||
syscall_printf ("%d = DeviceIoControl(%p, FSCTL_SET_SPARSE)",
|
||||
r, h);
|
||||
NTSTATUS status;
|
||||
status = NtFsControlFile (get_output_handle (), NULL, NULL, NULL,
|
||||
&io, FSCTL_SET_SPARSE, NULL, 0, NULL, 0);
|
||||
syscall_printf ("%p = NtFsControlFile(%S, FSCTL_SET_SPARSE)",
|
||||
status, pc.get_nt_native_path ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -912,7 +907,10 @@ fhandler_base::writev (const struct iovec *const iov, const int iovcnt,
|
|||
_off64_t
|
||||
fhandler_base::lseek (_off64_t offset, int whence)
|
||||
{
|
||||
_off64_t res;
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK io;
|
||||
FILE_POSITION_INFORMATION fpi;
|
||||
FILE_STANDARD_INFORMATION fsi;
|
||||
|
||||
/* Seeks on text files is tough, we rewind and read till we get to the
|
||||
right place. */
|
||||
|
@ -924,35 +922,52 @@ fhandler_base::lseek (_off64_t offset, int whence)
|
|||
set_readahead_valid (0);
|
||||
}
|
||||
|
||||
debug_printf ("lseek (%s, %D, %d)", get_name (), offset, whence);
|
||||
|
||||
DWORD win32_whence = whence == SEEK_SET ? FILE_BEGIN
|
||||
: (whence == SEEK_CUR ? FILE_CURRENT : FILE_END);
|
||||
|
||||
LONG off_low = ((__uint64_t) offset) & UINT32_MAX;
|
||||
LONG off_high = ((__uint64_t) offset) >> 32LL;
|
||||
|
||||
debug_printf ("setting file pointer to %u (high), %u (low)", off_high, off_low);
|
||||
res = SetFilePointer (get_handle (), off_low, &off_high, win32_whence);
|
||||
if (res == INVALID_SET_FILE_POINTER && GetLastError ())
|
||||
switch (whence)
|
||||
{
|
||||
__seterrno ();
|
||||
res = -1;
|
||||
case SEEK_SET:
|
||||
fpi.CurrentByteOffset.QuadPart = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
|
||||
FilePositionInformation);
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
__seterrno_from_nt_status (status);
|
||||
return -1;
|
||||
}
|
||||
fpi.CurrentByteOffset.QuadPart += offset;
|
||||
break;
|
||||
default: /* SEEK_END */
|
||||
status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
|
||||
FileStandardInformation);
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
__seterrno_from_nt_status (status);
|
||||
return -1;
|
||||
}
|
||||
fpi.CurrentByteOffset.QuadPart = fsi.EndOfFile.QuadPart + offset;
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
debug_printf ("setting file pointer to %U", fpi.CurrentByteOffset.QuadPart);
|
||||
status = NtSetInformationFile (get_handle (), &io, &fpi, sizeof fpi,
|
||||
FilePositionInformation);
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
res += (_off64_t) off_high << 32;
|
||||
|
||||
/* When next we write(), we will check to see if *this* seek went beyond
|
||||
the end of the file and if so, potentially sparsify the file. */
|
||||
did_lseek (true);
|
||||
|
||||
/* If this was a SEEK_CUR with offset 0, we still might have
|
||||
readahead that we have to take into account when calculating
|
||||
the actual position for the application. */
|
||||
if (whence == SEEK_CUR)
|
||||
res -= ralen - raixget;
|
||||
__seterrno_from_nt_status (status);
|
||||
return -1;
|
||||
}
|
||||
_off64_t res = fpi.CurrentByteOffset.QuadPart;
|
||||
|
||||
/* When next we write(), we will check to see if *this* seek went beyond
|
||||
the end of the file and if so, potentially sparsify the file. */
|
||||
did_lseek (true);
|
||||
|
||||
/* If this was a SEEK_CUR with offset 0, we still might have
|
||||
readahead that we have to take into account when calculating
|
||||
the actual position for the application. */
|
||||
if (whence == SEEK_CUR)
|
||||
res -= ralen - raixget;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -698,7 +698,7 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
|
|||
FSCTL_GET_NTFS_VOLUME_DATA,
|
||||
NULL, 0, &nvdb, sizeof nvdb);
|
||||
if (!NT_SUCCESS (status))
|
||||
debug_printf ("%p = NtFsControlFile(%S,FSCTL_GET_NTFS_VOLUME_DATA)",
|
||||
debug_printf ("%p = NtFsControlFile(%S, FSCTL_GET_NTFS_VOLUME_DATA)",
|
||||
status, pc.get_nt_native_path ());
|
||||
else
|
||||
sfs->f_blocks = nvdb.TotalClusters.QuadPart;
|
||||
|
@ -1030,7 +1030,7 @@ fhandler_disk_file::ftruncate (_off64_t length, bool allow_truncate)
|
|||
{
|
||||
status = NtFsControlFile (get_handle (), NULL, NULL, NULL, &io,
|
||||
FSCTL_SET_SPARSE, NULL, 0, NULL, 0);
|
||||
syscall_printf ("%p = NtFsControlFile(%S,FSCTL_SET_SPARSE)",
|
||||
syscall_printf ("%p = NtFsControlFile(%S, FSCTL_SET_SPARSE)",
|
||||
status, pc.get_nt_native_path ());
|
||||
}
|
||||
status = NtSetInformationFile (get_handle (), &io,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A)
|
||||
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
|
||||
#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
|
||||
#define STATUS_DISK_FULL ((NTSTATUS) 0xc000007f)
|
||||
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
|
||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xc00000bb)
|
||||
#define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xc0000101)
|
||||
|
@ -53,6 +54,9 @@
|
|||
#define FILE_EXISTS 4
|
||||
#define FILE_DOES_NOT_EXIST 5
|
||||
|
||||
#define FILE_WRITE_TO_END_OF_FILE (-1LL)
|
||||
#define FILE_USE_FILE_POINTER_POSITION (-2LL)
|
||||
|
||||
/* Device Characteristics. */
|
||||
#define FILE_REMOVABLE_MEDIA 0x00000001
|
||||
#define FILE_READ_ONLY_DEVICE 0x00000002
|
||||
|
|
Loading…
Reference in New Issue