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:
authorEgor Duda <deo@logos-m.ru>2001-02-28 12:59:54 +0300
committerEgor Duda <deo@logos-m.ru>2001-02-28 12:59:54 +0300
commit739db26a31c5a5585d2c0289752cb2d547c1a06f (patch)
tree0537b7c3269a92f9334437b0c3e68c7e351dc11d
parenta53136cc468fb88a7481eb7f6a86951222a688da (diff)
* fhandler_floppy.cc (fhandler_dev_floppy::lseek): Determine
drive geometry or partition size to allow seeking from the end of raw floppy device. Don't allow positioning past the end of media or to offsets bigger then max off_t.
-rw-r--r--winsup/cygwin/ChangeLog7
-rw-r--r--winsup/cygwin/fhandler_floppy.cc131
2 files changed, 91 insertions, 47 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 47ed0a0ad..d404037c2 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,10 @@
+2001-02-28 Egor Duda <deo@logos-m.ru>
+
+ * fhandler_floppy.cc (fhandler_dev_floppy::lseek): Determine
+ drive geometry or partition size to allow seeking from the end of
+ raw floppy device. Don't allow positioning past the end of media or
+ to offsets bigger then max off_t.
+
2001-02-27 Egor Duda <deo@logos-m.ru>
* fhandler.h (class fhandler_console): Make all variables that
diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc
index a767443b9..bab0b0a97 100644
--- a/winsup/cygwin/fhandler_floppy.cc
+++ b/winsup/cygwin/fhandler_floppy.cc
@@ -16,6 +16,7 @@ details. */
#include <unistd.h>
#include "fhandler.h"
#include "cygerrno.h"
+#include <winioctl.h>
/**********************************************************************/
/* fhandler_dev_floppy */
@@ -80,78 +81,114 @@ off_t
fhandler_dev_floppy::lseek (off_t offset, int whence)
{
int ret;
- DWORD off;
char buf[512];
-
- if (whence == SEEK_SET)
+ long long drive_size = 0;
+ long long lloffset = offset;
+ long long current_position;
+ off_t sector_aligned_offset;
+ off_t bytes_left;
+ DWORD low;
+ LONG high = 0;
+
+ if (os_being_run == winNT)
{
- if (offset < 0)
+ DISK_GEOMETRY di;
+ PARTITION_INFORMATION pi;
+ DWORD bytes_read;
+
+ if ( !DeviceIoControl ( get_handle(),
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL, 0,
+ &di, sizeof (di),
+ &bytes_read, NULL) )
{
- set_errno (EINVAL);
- return -1;
- }
-
- /* Invalidate buffer. */
- ret = writebuf ();
- if (ret)
- return ret;
- devbufstart = devbufend = 0;
-
- off = (offset / 512) * 512;
-
- if (SetFilePointer (get_handle (), off, NULL, FILE_BEGIN)
- == INVALID_SET_FILE_POINTER)
+ __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 ))
{
- __seterrno ();
- return -1;
- }
- return raw_read (buf, offset - off);
+ debug_printf ( "partition info: %ld (%ld)",
+ pi.StartingOffset.LowPart,
+ pi.PartitionLength.LowPart);
+ drive_size = (long long) pi.PartitionLength.QuadPart;
+ }
+ else
+ {
+ drive_size = (long long) di.Cylinders.QuadPart * di.TracksPerCylinder *
+ di.SectorsPerTrack * di.BytesPerSector;
+ }
+ debug_printf ( "drive size: %ld", drive_size );
}
- else if (whence == SEEK_CUR)
+
+ if (whence == SEEK_END && drive_size > 0)
{
- DWORD low;
- LONG high = 0;
+ lloffset = offset + drive_size;
+ whence = SEEK_SET;
+ }
+ if (whence == SEEK_CUR)
+ {
low = SetFilePointer (get_handle (), 0, &high, FILE_CURRENT);
if (low == INVALID_SET_FILE_POINTER && GetLastError ())
{
__seterrno ();
return -1;
}
- long long cur = (long long) high << 32 + low;
+ current_position = (long long) low + ((long long) high << 32);
if (is_writing)
- cur += devbufend - devbufstart;
+ current_position += devbufend - devbufstart;
else
- cur -= devbufend - devbufstart;
-
+ current_position -= devbufend - devbufstart;
+
+ lloffset += current_position;
+ whence = SEEK_SET;
+ }
+
+ if (lloffset < 0 ||
+ drive_size > 0 && lloffset > drive_size)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ high = lloffset >> 32;
+ low = lloffset & 0xffffffff;
+ if ( high || (off_t) low < 0 )
+ {
+ set_errno (EFBIG);
+ return -1;
+ }
+ offset = (off_t) low;
+
+ /* FIXME: sector can possibly be not 512 bytes long */
+ sector_aligned_offset = (offset / 512) * 512;
+ bytes_left = offset - sector_aligned_offset;
+
+ if (whence == SEEK_SET)
+ {
/* Invalidate buffer. */
ret = writebuf ();
if (ret)
return ret;
devbufstart = devbufend = 0;
- cur += offset;
- if (cur < 0)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- long long set = (cur / 512) * 512;
- high = set >> 32;
- low = set & 0xffffffff;
-
- off = cur - set;
-
- low = SetFilePointer (get_handle (), low, &high, FILE_BEGIN);
- if (low == INVALID_SET_FILE_POINTER && GetLastError ())
- {
+ if (SetFilePointer (get_handle (), sector_aligned_offset, NULL, FILE_BEGIN)
+ == INVALID_SET_FILE_POINTER)
+ {
__seterrno ();
return -1;
}
- return raw_read (buf, off);
+ return sector_aligned_offset + raw_read (buf, bytes_left);
}
- /* SEEK_END is not supported on raw disk devices. */
+
set_errno (EINVAL);
return -1;
}