From b470a0e81fb3e56dfd7886e0099e7b6b7c148101 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 26 Sep 2005 14:55:40 +0000 Subject: * fhandler.h (class fhandler_dev_raw): Add drive information members drive_size, current_position and bytes_per_sector. (fhandler_dev_floppy::get_drive_info): Declare. * fhandler_floppy.cc (fhandler_dev_floppy::is_eom): Define ERROR_SEEK and ERROR_SECTOR_NOT_FOUND as end-of-medium conditions. (fhandler_dev_floppy::get_drive_info): New method to have one function retrieving drive info. (fhandler_dev_floppy::open): Call get_drive_info to get drive information right from the start. (fhandler_dev_floppy::lseek): Use and set drive information members. Especially keep track of current_position. (fhandler_dev_floppy::ioctl): Ditto. * fhandler_raw.cc (fhandler_dev_raw::write_file): Keep track of current_position. (fhandler_dev_raw::read_file): Ditto. (fhandler_dev_raw::raw_read): Never try to read beyond end-of-medium. (fhandler_dev_raw::dup): Handle new drive information members. --- winsup/cygwin/fhandler_floppy.cc | 225 ++++++++++++++------------------------- 1 file changed, 79 insertions(+), 146 deletions(-) (limited to 'winsup/cygwin/fhandler_floppy.cc') diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc index cbf87c330..cafac8c43 100644 --- a/winsup/cygwin/fhandler_floppy.cc +++ b/winsup/cygwin/fhandler_floppy.cc @@ -27,7 +27,9 @@ details. */ int fhandler_dev_floppy::is_eom (int win_error) { - int ret = (win_error == ERROR_INVALID_PARAMETER); + int ret = (win_error == ERROR_INVALID_PARAMETER + || win_error == ERROR_SEEK + || win_error == ERROR_SECTOR_NOT_FOUND); if (ret) debug_printf ("end of medium"); return ret; @@ -48,39 +50,11 @@ fhandler_dev_floppy::fhandler_dev_floppy () } int -fhandler_dev_floppy::open (int flags, mode_t) -{ - /* The correct size of the buffer would be 512 bytes, - * which is the atomic size, supported by WinNT. - * Unfortunately, the performance is worse than - * access to file system on same device! - * Setting buffer size to a relatively big value - * increases performance by means. - * The new ioctl call with 'rdevio.h' header file - * supports changing this value. - * - * Let's be smart: Let's take a multiplier of typical tar - * and cpio buffer sizes by default! - */ - devbufsiz = 61440L; /* 512L; */ - return fhandler_dev_raw::open (flags); -} - -_off64_t -fhandler_dev_floppy::lseek (_off64_t offset, int whence) +fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo) { - char buf[512]; - _off64_t drive_size = 0; - _off64_t lloffset = offset; - _off64_t current_position; - _off64_t sector_aligned_offset; - _off64_t bytes_left; - DWORD low; - LONG high = 0; - DISK_GEOMETRY di; PARTITION_INFORMATION pi; - DWORD bytes_read; + DWORD bytes_read = 0; if (!DeviceIoControl (get_handle (), IOCTL_DISK_GET_DRIVE_GEOMETRY, @@ -96,15 +70,16 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence) di.TracksPerCylinder, di.SectorsPerTrack, di.BytesPerSector); + bytes_per_sector = di.BytesPerSector; if (DeviceIoControl (get_handle (), IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &pi, sizeof (pi), &bytes_read, NULL)) { - debug_printf ("partition info: %ld (%ld)", - pi.StartingOffset.LowPart, - pi.PartitionLength.LowPart); + debug_printf ("partition info: offset %D length %D", + pi.StartingOffset.QuadPart, + pi.PartitionLength.QuadPart); drive_size = pi.PartitionLength.QuadPart; } else @@ -112,7 +87,53 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence) drive_size = di.Cylinders.QuadPart * di.TracksPerCylinder * di.SectorsPerTrack * di.BytesPerSector; } - debug_printf ("drive size: %ld", drive_size); + debug_printf ("drive size: %D", drive_size); + if (geo) + { + geo->heads = di.TracksPerCylinder; + geo->sectors = di.SectorsPerTrack; + geo->cylinders = di.Cylinders.LowPart; + geo->start = pi.StartingOffset.QuadPart >> 9ULL; + } + return 0; +} + +int +fhandler_dev_floppy::open (int flags, mode_t) +{ + /* The correct size of the buffer would be 512 bytes, + * which is the atomic size, supported by WinNT. + * Unfortunately, the performance is worse than + * access to file system on same device! + * Setting buffer size to a relatively big value + * increases performance by means. + * The new ioctl call with 'rdevio.h' header file + * supports changing this value. + * + * Let's be smart: Let's take a multiplier of typical tar + * and cpio buffer sizes by default! + */ + devbufsiz = 61440L; /* 512L; */ + int ret = fhandler_dev_raw::open (flags); + + if (ret && get_drive_info (NULL)) + { + close (); + return 0; + } + + return ret; +} + +_off64_t +fhandler_dev_floppy::lseek (_off64_t offset, int whence) +{ + char buf[512]; + _off64_t lloffset = offset; + _off64_t sector_aligned_offset; + _off64_t bytes_left; + DWORD low; + LONG high = 0; if (whence == SEEK_END && drive_size > 0) { @@ -122,134 +143,59 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence) if (whence == SEEK_CUR) { - low = SetFilePointer (get_handle (), 0, &high, FILE_CURRENT); - if (low == INVALID_SET_FILE_POINTER && GetLastError ()) - { - __seterrno (); - return -1; - } - current_position = low + ((_off64_t) high << 32); - /* devbufend and devbufstart are always 0 when writing. */ - current_position -= devbufend - devbufstart; - - lloffset += current_position; + lloffset += current_position - (devbufend - devbufstart); whence = SEEK_SET; } - if (lloffset < 0 || - drive_size > 0 && lloffset > drive_size) + if (whence != SEEK_SET + || lloffset < 0 + || drive_size > 0 && lloffset >= drive_size) { set_errno (EINVAL); return -1; } - /* FIXME: sector can possibly be not 512 bytes long */ - sector_aligned_offset = (lloffset / 512) * 512; + sector_aligned_offset = (lloffset / bytes_per_sector) * bytes_per_sector; bytes_left = lloffset - sector_aligned_offset; - if (whence == SEEK_SET) - { - /* Invalidate buffer. */ - devbufstart = devbufend = 0; + /* Invalidate buffer. */ + devbufstart = devbufend = 0; - low = sector_aligned_offset & UINT32_MAX; - high = sector_aligned_offset >> 32; - if (SetFilePointer (get_handle (), low, &high, FILE_BEGIN) - == INVALID_SET_FILE_POINTER && GetLastError ()) - { - __seterrno (); - return -1; - } + low = sector_aligned_offset & UINT32_MAX; + high = sector_aligned_offset >> 32; + if (SetFilePointer (get_handle (), low, &high, FILE_BEGIN) + == INVALID_SET_FILE_POINTER && GetLastError ()) + { + __seterrno (); + return -1; + } - eom_detected (false); + eom_detected (false); + current_position = sector_aligned_offset; + if (bytes_left) + { size_t len = bytes_left; raw_read (buf, len); - return sector_aligned_offset + bytes_left; } - - set_errno (EINVAL); - return -1; + return current_position + bytes_left; } int fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf) { DISK_GEOMETRY di; - PARTITION_INFORMATION pi; DWORD bytes_read; - _off64_t drive_size = 0; - _off64_t start = 0; switch (cmd) { case HDIO_GETGEO: { debug_printf ("HDIO_GETGEO"); - if (!DeviceIoControl (get_handle (), - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, 0, - &di, sizeof (di), - &bytes_read, NULL)) - { - __seterrno (); - return -1; - } - debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)", - di.Cylinders.LowPart, - di.TracksPerCylinder, - di.SectorsPerTrack, - di.BytesPerSector); - if (DeviceIoControl (get_handle (), - IOCTL_DISK_GET_PARTITION_INFO, - NULL, 0, - &pi, sizeof (pi), - &bytes_read, NULL)) - { - debug_printf ("partition info: %ld (%ld)", - pi.StartingOffset.LowPart, - pi.PartitionLength.LowPart); - start = pi.StartingOffset.QuadPart >> 9ULL; - } - struct hd_geometry *geo = (struct hd_geometry *) buf; - geo->heads = di.TracksPerCylinder; - geo->sectors = di.SectorsPerTrack; - geo->cylinders = di.Cylinders.LowPart; - geo->start = start; - return 0; + return get_drive_info ((struct hd_geometry *) buf); } case BLKGETSIZE: case BLKGETSIZE64: { debug_printf ("BLKGETSIZE"); - if (!DeviceIoControl (get_handle (), - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, 0, - &di, sizeof (di), - &bytes_read, NULL)) - { - __seterrno (); - return -1; - } - debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)", - di.Cylinders.LowPart, - di.TracksPerCylinder, - di.SectorsPerTrack, - di.BytesPerSector); - if (DeviceIoControl (get_handle (), - IOCTL_DISK_GET_PARTITION_INFO, - NULL, 0, - &pi, sizeof (pi), - &bytes_read, NULL)) - { - debug_printf ("partition info: %ld (%ld)", - pi.StartingOffset.LowPart, - pi.PartitionLength.LowPart); - drive_size = pi.PartitionLength.QuadPart; - } - else - { - drive_size = di.Cylinders.QuadPart * di.TracksPerCylinder * - di.SectorsPerTrack * di.BytesPerSector; - } if (cmd == BLKGETSIZE) *(long *)buf = drive_size >> 9UL; else @@ -268,26 +214,13 @@ fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf) __seterrno (); return -1; } + get_drive_info (NULL); return 0; } case BLKSSZGET: { debug_printf ("BLKSSZGET"); - if (!DeviceIoControl (get_handle (), - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, 0, - &di, sizeof (di), - &bytes_read, NULL)) - { - __seterrno (); - return -1; - } - debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)", - di.Cylinders.LowPart, - di.TracksPerCylinder, - di.SectorsPerTrack, - di.BytesPerSector); - *(int *)buf = di.BytesPerSector; + *(int *)buf = bytes_per_sector; return 0; } default: -- cgit v1.2.3