Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog20
-rw-r--r--winsup/cygwin/fhandler.h6
-rw-r--r--winsup/cygwin/fhandler_floppy.cc225
-rw-r--r--winsup/cygwin/fhandler_raw.cc21
4 files changed, 124 insertions, 148 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 368b984d6..94356e391 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 bdc73bfbf..ac1e4e9a9 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 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:
diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc
index 24525ef40..fe27bbd91 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;