4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-28 12:05:47 +08:00

* 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.
This commit is contained in:
Corinna Vinschen 2005-09-26 14:55:40 +00:00
parent d5f4ee62b7
commit b470a0e81f
4 changed files with 126 additions and 150 deletions

View File

@ -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> 2005-09-26 Christopher Faylor <cgf@timesys.com>
* exceptions.cc (handle_exceptions): Just si_code to SI_KERNEL first * exceptions.cc (handle_exceptions): Just si_code to SI_KERNEL first

View File

@ -551,6 +551,9 @@ public:
class fhandler_dev_raw: public fhandler_base class fhandler_dev_raw: public fhandler_base
{ {
protected: protected:
_off64_t drive_size;
_off64_t current_position;
unsigned long bytes_per_sector;
char *devbuf; char *devbuf;
size_t devbufsiz; size_t devbufsiz;
size_t devbufstart; size_t devbufstart;
@ -600,6 +603,9 @@ class fhandler_dev_raw: public fhandler_base
class fhandler_dev_floppy: public fhandler_dev_raw class fhandler_dev_floppy: public fhandler_dev_raw
{ {
private:
int fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo);
protected: protected:
virtual int is_eom (int win_error); virtual int is_eom (int win_error);
virtual int is_eof (int win_error); virtual int is_eof (int win_error);

View File

@ -27,7 +27,9 @@ details. */
int int
fhandler_dev_floppy::is_eom (int win_error) 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) if (ret)
debug_printf ("end of medium"); debug_printf ("end of medium");
return ret; return ret;
@ -48,39 +50,11 @@ fhandler_dev_floppy::fhandler_dev_floppy ()
} }
int int
fhandler_dev_floppy::open (int flags, mode_t) fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo)
{ {
/* 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)
{
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; DISK_GEOMETRY di;
PARTITION_INFORMATION pi; PARTITION_INFORMATION pi;
DWORD bytes_read; DWORD bytes_read = 0;
if (!DeviceIoControl (get_handle (), if (!DeviceIoControl (get_handle (),
IOCTL_DISK_GET_DRIVE_GEOMETRY, IOCTL_DISK_GET_DRIVE_GEOMETRY,
@ -96,15 +70,16 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence)
di.TracksPerCylinder, di.TracksPerCylinder,
di.SectorsPerTrack, di.SectorsPerTrack,
di.BytesPerSector); di.BytesPerSector);
bytes_per_sector = di.BytesPerSector;
if (DeviceIoControl (get_handle (), if (DeviceIoControl (get_handle (),
IOCTL_DISK_GET_PARTITION_INFO, IOCTL_DISK_GET_PARTITION_INFO,
NULL, 0, NULL, 0,
&pi, sizeof (pi), &pi, sizeof (pi),
&bytes_read, NULL)) &bytes_read, NULL))
{ {
debug_printf ("partition info: %ld (%ld)", debug_printf ("partition info: offset %D length %D",
pi.StartingOffset.LowPart, pi.StartingOffset.QuadPart,
pi.PartitionLength.LowPart); pi.PartitionLength.QuadPart);
drive_size = pi.PartitionLength.QuadPart; drive_size = pi.PartitionLength.QuadPart;
} }
else else
@ -112,7 +87,53 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence)
drive_size = di.Cylinders.QuadPart * di.TracksPerCylinder * drive_size = di.Cylinders.QuadPart * di.TracksPerCylinder *
di.SectorsPerTrack * di.BytesPerSector; 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) if (whence == SEEK_END && drive_size > 0)
{ {
@ -122,134 +143,59 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence)
if (whence == SEEK_CUR) if (whence == SEEK_CUR)
{ {
low = SetFilePointer (get_handle (), 0, &high, FILE_CURRENT); lloffset += current_position - (devbufend - devbufstart);
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;
whence = SEEK_SET; whence = SEEK_SET;
} }
if (lloffset < 0 || if (whence != SEEK_SET
drive_size > 0 && lloffset > drive_size) || lloffset < 0
|| drive_size > 0 && lloffset >= drive_size)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
/* FIXME: sector can possibly be not 512 bytes long */ sector_aligned_offset = (lloffset / bytes_per_sector) * bytes_per_sector;
sector_aligned_offset = (lloffset / 512) * 512;
bytes_left = lloffset - sector_aligned_offset; bytes_left = lloffset - sector_aligned_offset;
if (whence == SEEK_SET) /* 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 ())
{ {
/* Invalidate buffer. */ __seterrno ();
devbufstart = devbufend = 0; 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);
size_t len = bytes_left;
raw_read (buf, len);
return sector_aligned_offset + bytes_left;
} }
set_errno (EINVAL); eom_detected (false);
return -1; current_position = sector_aligned_offset;
if (bytes_left)
{
size_t len = bytes_left;
raw_read (buf, len);
}
return current_position + bytes_left;
} }
int int
fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf) fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf)
{ {
DISK_GEOMETRY di; DISK_GEOMETRY di;
PARTITION_INFORMATION pi;
DWORD bytes_read; DWORD bytes_read;
_off64_t drive_size = 0;
_off64_t start = 0;
switch (cmd) switch (cmd)
{ {
case HDIO_GETGEO: case HDIO_GETGEO:
{ {
debug_printf ("HDIO_GETGEO"); debug_printf ("HDIO_GETGEO");
if (!DeviceIoControl (get_handle (), return get_drive_info ((struct hd_geometry *) buf);
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;
} }
case BLKGETSIZE: case BLKGETSIZE:
case BLKGETSIZE64: case BLKGETSIZE64:
{ {
debug_printf ("BLKGETSIZE"); 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) if (cmd == BLKGETSIZE)
*(long *)buf = drive_size >> 9UL; *(long *)buf = drive_size >> 9UL;
else else
@ -268,26 +214,13 @@ fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf)
__seterrno (); __seterrno ();
return -1; return -1;
} }
get_drive_info (NULL);
return 0; return 0;
} }
case BLKSSZGET: case BLKSSZGET:
{ {
debug_printf ("BLKSSZGET"); debug_printf ("BLKSSZGET");
if (!DeviceIoControl (get_handle (), *(int *)buf = bytes_per_sector;
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;
return 0; return 0;
} }
default: default:

View File

@ -51,6 +51,8 @@ fhandler_dev_raw::write_file (const void *buf, DWORD to_write,
*err = 0; *err = 0;
if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0))) if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0)))
*err = GetLastError (); *err = GetLastError ();
else
current_position += *written;
syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)",
ret, *err, get_handle (), buf, to_write, *written); ret, *err, get_handle (), buf, to_write, *written);
return ret; return ret;
@ -64,6 +66,8 @@ fhandler_dev_raw::read_file (void *buf, DWORD to_read, DWORD *read, int *err)
*err = 0; *err = 0;
if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0))) if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0)))
*err = GetLastError (); *err = GetLastError ();
else
current_position += *read;
syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)",
ret, *err, get_handle (), buf, to_read, *read); ret, *err, get_handle (), buf, to_read, *read);
return ret; return ret;
@ -188,7 +192,9 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen)
{ {
if (len >= devbufsiz) 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; tgt = p;
debug_printf ("read %d bytes direct from file",bytes_to_read); 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; tgt = devbuf;
bytes_to_read = devbufsiz; 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", debug_printf ("read %d bytes from file into buffer",
bytes_to_read); bytes_to_read);
} }
if (!bytes_to_read)
{
eom_detected (true);
break;
}
if (!read_file (tgt, bytes_to_read, &read2, &ret)) if (!read_file (tgt, bytes_to_read, &read2, &ret))
{ {
if (!is_eof (ret) && !is_eom (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; 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; fhc->devbufsiz = devbufsiz;
if (devbufsiz > 1L) if (devbufsiz > 1L)
fhc->devbuf = new char [devbufsiz]; fhc->devbuf = new char [devbufsiz];
@ -368,7 +385,7 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
mop.mt_count = op->rd_parm; mop.mt_count = op->rd_parm;
ret = ioctl (MTIOCTOP, &mop); ret = ioctl (MTIOCTOP, &mop);
} }
else if (op->rd_parm % 512) else if (op->rd_parm % bytes_per_sector)
ret = ERROR_INVALID_PARAMETER; ret = ERROR_INVALID_PARAMETER;
else if (devbuf && op->rd_parm < devbufend - devbufstart) else if (devbuf && op->rd_parm < devbufend - devbufstart)
ret = ERROR_INVALID_PARAMETER; ret = ERROR_INVALID_PARAMETER;