diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2005-09-26 14:55:40 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2005-09-26 14:55:40 +0000 |
commit | b470a0e81fb3e56dfd7886e0099e7b6b7c148101 (patch) | |
tree | 75fc2d28a97ca8e2b1af8ab3431177d199343ebb /winsup | |
parent | d5f4ee62b706f7cfe22a92fd796dc36382690950 (diff) | |
download | newlib-b470a0e81fb3e56dfd7886e0099e7b6b7c148101.zip newlib-b470a0e81fb3e56dfd7886e0099e7b6b7c148101.tar.gz newlib-b470a0e81fb3e56dfd7886e0099e7b6b7c148101.tar.bz2 |
* 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.
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 20 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 6 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_floppy.cc | 225 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_raw.cc | 21 |
4 files changed, 124 insertions, 148 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 368b984..94356e3 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,23 @@ +2005-09-26 Corinna Vinschen <corinna@vinschen.de> + + * 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. + 2005-09-26 Christopher Faylor <cgf@timesys.com> * exceptions.cc (handle_exceptions): Just si_code to SI_KERNEL first diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index bdc73bf..ac1e4e9 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -551,6 +551,9 @@ public: class fhandler_dev_raw: public fhandler_base { protected: + _off64_t drive_size; + _off64_t current_position; + unsigned long bytes_per_sector; char *devbuf; size_t devbufsiz; size_t devbufstart; @@ -600,6 +603,9 @@ class fhandler_dev_raw: public fhandler_base class fhandler_dev_floppy: public fhandler_dev_raw { + private: + int fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo); + protected: virtual int is_eom (int win_error); virtual int is_eof (int win_error); diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc index cbf87c3..cafac8c 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: diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index 24525ef..fe27bbd 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -51,6 +51,8 @@ fhandler_dev_raw::write_file (const void *buf, DWORD to_write, *err = 0; if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0))) *err = GetLastError (); + else + current_position += *written; syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", ret, *err, get_handle (), buf, to_write, *written); return ret; @@ -64,6 +66,8 @@ fhandler_dev_raw::read_file (void *buf, DWORD to_read, DWORD *read, int *err) *err = 0; if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0))) *err = GetLastError (); + else + current_position += *read; syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", ret, *err, get_handle (), buf, to_read, *read); return ret; @@ -188,7 +192,9 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) { if (len >= devbufsiz) { - bytes_to_read = (len / 512) * 512; + bytes_to_read = (len / bytes_per_sector) * bytes_per_sector; + if (current_position + bytes_to_read >= drive_size) + bytes_to_read = drive_size - current_position; tgt = p; debug_printf ("read %d bytes direct from file",bytes_to_read); } @@ -196,9 +202,17 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) { tgt = devbuf; bytes_to_read = devbufsiz; + if (current_position + bytes_to_read >= drive_size) + bytes_to_read = drive_size - current_position; debug_printf ("read %d bytes from file into buffer", bytes_to_read); } + if (!bytes_to_read) + { + eom_detected (true); + break; + } + if (!read_file (tgt, bytes_to_read, &read2, &ret)) { if (!is_eof (ret) && !is_eom (ret)) @@ -315,6 +329,9 @@ fhandler_dev_raw::dup (fhandler_base *child) { fhandler_dev_raw *fhc = (fhandler_dev_raw *) child; + fhc->drive_size = drive_size; + fhc->current_position = current_position; + fhc->bytes_per_sector = bytes_per_sector; fhc->devbufsiz = devbufsiz; if (devbufsiz > 1L) fhc->devbuf = new char [devbufsiz]; @@ -368,7 +385,7 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf) mop.mt_count = op->rd_parm; ret = ioctl (MTIOCTOP, &mop); } - else if (op->rd_parm % 512) + else if (op->rd_parm % bytes_per_sector) ret = ERROR_INVALID_PARAMETER; else if (devbuf && op->rd_parm < devbufend - devbufstart) ret = ERROR_INVALID_PARAMETER; |