summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_floppy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler_floppy.cc')
-rw-r--r--winsup/cygwin/fhandler_floppy.cc791
1 files changed, 0 insertions, 791 deletions
diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc
deleted file mode 100644
index eaa7f6a2e..000000000
--- a/winsup/cygwin/fhandler_floppy.cc
+++ /dev/null
@@ -1,791 +0,0 @@
-/* fhandler_floppy.cc. See fhandler.h for a description of the
- fhandler classes.
-
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009, 2011, 2012 Red Hat, Inc.
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#include "winsup.h"
-#include <alloca.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <winioctl.h>
-#include <cygwin/rdevio.h>
-#include <cygwin/hdreg.h>
-#include <cygwin/fs.h>
-#include "cygerrno.h"
-#include "security.h"
-#include "path.h"
-#include "fhandler.h"
-#include "ntdll.h"
-
-#define IS_EOM(err) ((err) == ERROR_INVALID_PARAMETER \
- || (err) == ERROR_SEEK \
- || (err) == ERROR_SECTOR_NOT_FOUND)
-
-#define bytes_per_sector devbufalign
-
-/**********************************************************************/
-/* fhandler_dev_floppy */
-
-fhandler_dev_floppy::fhandler_dev_floppy ()
- : fhandler_dev_raw (), status ()
-{
-}
-
-int
-fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo)
-{
- char dbuf[256];
- char pbuf[256];
-
- DISK_GEOMETRY_EX *dix = NULL;
- DISK_GEOMETRY *di = NULL;
- PARTITION_INFORMATION_EX *pix = NULL;
- PARTITION_INFORMATION *pi = NULL;
- DWORD bytes_read = 0;
-
- /* Always try using the new EX ioctls first (>= XP). If not available,
- fall back to trying the old non-EX ioctls.
- Unfortunately the EX ioctls are not implemented in the floppy driver. */
- if (wincap.has_disk_ex_ioctls () && get_major () != DEV_FLOPPY_MAJOR)
- {
- if (!DeviceIoControl (get_handle (),
- IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0,
- dbuf, 256, &bytes_read, NULL))
- __seterrno ();
- else
- {
- dix = (DISK_GEOMETRY_EX *) dbuf;
- di = &dix->Geometry;
- if (!DeviceIoControl (get_handle (),
- IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0,
- pbuf, 256, &bytes_read, NULL))
- __seterrno ();
- else
- pix = (PARTITION_INFORMATION_EX *) pbuf;
- }
- }
- if (!di)
- {
- if (!DeviceIoControl (get_handle (),
- IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
- dbuf, 256, &bytes_read, NULL))
- __seterrno ();
- else
- {
- di = (DISK_GEOMETRY *) dbuf;
- if (!DeviceIoControl (get_handle (),
- IOCTL_DISK_GET_PARTITION_INFO, NULL, 0,
- pbuf, 256, &bytes_read, NULL))
- __seterrno ();
- else
- pi = (PARTITION_INFORMATION *) pbuf;
- }
- }
- if (!di)
- {
- /* Up to Win2K, even IOCTL_DISK_GET_DRIVE_GEOMETRY fails when trying
- it on CD or DVD drives. In that case fall back to requesting
- simple file system information. */
- NTSTATUS status;
- IO_STATUS_BLOCK io;
- FILE_FS_SIZE_INFORMATION ffsi;
-
- status = NtQueryVolumeInformationFile (get_handle (), &io, &ffsi,
- sizeof ffsi,
- FileFsSizeInformation);
- if (!NT_SUCCESS (status))
- {
- __seterrno_from_nt_status (status);
- return -1;
- }
- debug_printf ("fsys geometry: (%D units)*(%u sec)*(%u bps)",
- ffsi.TotalAllocationUnits.QuadPart,
- ffsi.SectorsPerAllocationUnit,
- ffsi.BytesPerSector);
- bytes_per_sector = ffsi.BytesPerSector;
- drive_size = ffsi.TotalAllocationUnits.QuadPart
- * ffsi.SectorsPerAllocationUnit
- * ffsi.BytesPerSector;
- if (geo)
- {
- geo->heads = 1;
- geo->sectors = ffsi.SectorsPerAllocationUnit;
- geo->cylinders = ffsi.TotalAllocationUnits.LowPart;
- geo->start = 0;
- }
- }
- else
- {
- debug_printf ("disk geometry: (%D cyl)*(%u trk)*(%u sec)*(%u bps)",
- di->Cylinders.QuadPart,
- di->TracksPerCylinder,
- di->SectorsPerTrack,
- di->BytesPerSector);
- bytes_per_sector = di->BytesPerSector;
- if (pix)
- {
- debug_printf ("partition info: offset %D length %D",
- pix->StartingOffset.QuadPart,
- pix->PartitionLength.QuadPart);
- drive_size = pix->PartitionLength.QuadPart;
- }
- else if (pi)
- {
- debug_printf ("partition info: offset %D length %D",
- pi->StartingOffset.QuadPart,
- pi->PartitionLength.QuadPart);
- drive_size = pi->PartitionLength.QuadPart;
- }
- else
- {
- /* Getting the partition size by using the drive geometry information
- looks wrong, but this is a historical necessity. NT4 didn't
- maintain partition information for the whole drive (aka
- "partition 0"), but returned ERROR_INVALID_HANDLE instead. That
- got fixed in W2K. */
- drive_size = di->Cylinders.QuadPart * di->TracksPerCylinder
- * di->SectorsPerTrack * di->BytesPerSector;
- }
- if (geo)
- {
- geo->heads = di->TracksPerCylinder;
- geo->sectors = di->SectorsPerTrack;
- geo->cylinders = di->Cylinders.LowPart;
- if (pix)
- geo->start = pix->StartingOffset.QuadPart >> 9ULL;
- else if (pi)
- geo->start = pi->StartingOffset.QuadPart >> 9ULL;
- else
- geo->start = 0;
- }
- }
- debug_printf ("drive size: %D", drive_size);
-
- return 0;
-}
-
-/* Wrapper functions for ReadFile and WriteFile to simplify error handling. */
-BOOL
-fhandler_dev_floppy::read_file (void *buf, DWORD to_read, DWORD *read, int *err)
-{
- BOOL ret;
-
- *err = 0;
- if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0)))
- *err = GetLastError ();
- syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)",
- ret, *err, get_handle (), buf, to_read, *read);
- return ret;
-}
-
-/* See comment in write_file below. */
-BOOL
-fhandler_dev_floppy::lock_partition (DWORD to_write)
-{
- DWORD bytes_read;
-
- /* The simple case. We have only a single partition open anyway.
- Try to lock the partition so that a subsequent write succeeds.
- If there's some file handle open on one of the affected partitions,
- this fails, but that's how it works on Vista and later... */
- if (get_minor () % 16 != 0)
- {
- if (!DeviceIoControl (get_handle (), FSCTL_LOCK_VOLUME,
- NULL, 0, NULL, 0, &bytes_read, NULL))
- {
- debug_printf ("DeviceIoControl (FSCTL_LOCK_VOLUME) failed, %E");
- return FALSE;
- }
- return TRUE;
- }
-
- /* The tricky case. We're writing to the entire disk. What this code
- basically does is to find out if the current write operation affects
- one or more partitions on the disk. If so, it tries to lock all these
- partitions and stores the handles for a subsequent close(). */
- NTSTATUS status;
- IO_STATUS_BLOCK io;
- FILE_POSITION_INFORMATION fpi;
- /* Allocate space for 4 times the maximum partition count we can handle.
- The reason is that for *every* single logical drive in an extended
- partition on an MBR drive, 3 filler entries with partition number set
- to 0 are added into the partition table returned by
- IOCTL_DISK_GET_DRIVE_LAYOUT_EX. The first of them reproduces the data
- of the next partition entry, if any, except for the partiton number.
- Then two entries with everything set to 0 follow. Well, the
- documentation states that for MBR drives the number of partition entries
- in the PARTITION_INFORMATION_EX array is always a multiple of 4, but,
- nevertheless, how crappy is that layout? */
- const DWORD size = sizeof (DRIVE_LAYOUT_INFORMATION_EX)
- + 4 * MAX_PARTITIONS * sizeof (PARTITION_INFORMATION_EX);
- PDRIVE_LAYOUT_INFORMATION_EX pdlix = (PDRIVE_LAYOUT_INFORMATION_EX)
- alloca (size);
- BOOL found = FALSE;
-
- /* Fetch current file pointer position on disk. */
- status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
- FilePositionInformation);
- if (!NT_SUCCESS (status))
- {
- debug_printf ("NtQueryInformationFile(FilePositionInformation): %p",
- status);
- return FALSE;
- }
- /* Fetch drive layout to get start and end positions of partitions on disk. */
- if (!DeviceIoControl (get_handle (), IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0,
- pdlix, size, &bytes_read, NULL))
- {
- debug_printf ("DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT_EX): %E");
- return FALSE;
- }
- /* Scan through partition info to find the partition(s) into which we're
- currently trying to write. */
- PARTITION_INFORMATION_EX *ppie = pdlix->PartitionEntry;
- for (DWORD i = 0; i < pdlix->PartitionCount; ++i, ++ppie)
- {
- /* A partition number of 0 denotes an extended partition or one of the
- aforementioned filler entries. Just skip. */
- if (ppie->PartitionNumber == 0)
- continue;
- /* Check if our writing range affects this partition. */
- if (fpi.CurrentByteOffset.QuadPart < ppie->StartingOffset.QuadPart
- + ppie->PartitionLength.QuadPart
- && ppie->StartingOffset.QuadPart < fpi.CurrentByteOffset.QuadPart
- + to_write)
- {
- /* Yes. Now check if we can handle it. We can only handle
- up to MAX_PARTITIONS partitions. The partition numbering is
- one-based, so we decrement the partition number by 1 when using
- as index into the partition array. */
- DWORD &part_no = ppie->PartitionNumber;
- if (part_no >= MAX_PARTITIONS)
- return FALSE;
- found = TRUE;
- debug_printf ("%d %D->%D : %D->%D", part_no,
- ppie->StartingOffset.QuadPart,
- ppie->StartingOffset.QuadPart
- + ppie->PartitionLength.QuadPart,
- fpi.CurrentByteOffset.QuadPart,
- fpi.CurrentByteOffset.QuadPart + to_write);
- /* Do we already have partitions? If not, create it. */
- if (!partitions)
- {
- partitions = (part_t *) ccalloc_abort (HEAP_FHANDLER, 1,
- sizeof (part_t));
- partitions->refcnt = 1;
- }
- /* Next, check if the partition is already open. If so, skip it. */
- if (partitions->hdl[part_no - 1])
- continue;
- /* Now open the partition and lock it. */
- WCHAR part[MAX_PATH], *p;
- NTSTATUS status;
- UNICODE_STRING upart;
- OBJECT_ATTRIBUTES attr;
- IO_STATUS_BLOCK io;
-
- sys_mbstowcs (part, MAX_PATH, get_win32_name ());
- p = wcschr (part, L'\0') - 1;
- __small_swprintf (p, L"%d", part_no);
- RtlInitUnicodeString (&upart, part);
- InitializeObjectAttributes (&attr, &upart,
- OBJ_CASE_INSENSITIVE
- | ((get_flags () & O_CLOEXEC)
- ? 0 : OBJ_INHERIT),
- NULL, NULL);
- status = NtOpenFile (&partitions->hdl[part_no - 1],
- GENERIC_READ | GENERIC_WRITE, &attr,
- &io, FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
- if (!NT_SUCCESS (status))
- {
- debug_printf ("NtCreateFile(%W): %p", part, status);
- return FALSE;
- }
- if (!DeviceIoControl (partitions->hdl[part_no - 1], FSCTL_LOCK_VOLUME,
- NULL, 0, NULL, 0, &bytes_read, NULL))
- {
- debug_printf ("DeviceIoControl (%W, FSCTL_LOCK_VOLUME) "
- "failed, %E", part);
- return FALSE;
- }
- }
- }
- /* If we didn't find a single matching partition, the "Access denied"
- had another reason, so return FALSE in that case. */
- return found;
-}
-
-BOOL
-fhandler_dev_floppy::write_file (const void *buf, DWORD to_write,
- DWORD *written, int *err)
-{
- BOOL ret;
-
- *err = 0;
- if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0)))
- *err = GetLastError ();
- /* When writing to a disk or partition on Vista, an "Access denied" error
- is potentially a result of the raw disk write restriction. See
- http://support.microsoft.com/kb/942448 for details. What we have to
- do here is to lock the partition and retry. The previous solution
- locked one or all partitions immediately in open. Which is overly
- wasteful, given that the user might only want to change, say, the boot
- sector. */
- if (*err == ERROR_ACCESS_DENIED
- && wincap.has_restricted_raw_disk_access ()
- && get_major () != DEV_FLOPPY_MAJOR
- && get_major () != DEV_CDROM_MAJOR
- && (get_flags () & O_ACCMODE) != O_RDONLY
- && lock_partition (to_write))
- {
- *err = 0;
- if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0)))
- *err = GetLastError ();
- }
- syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)",
- ret, *err, get_handle (), buf, to_write, *written);
- return ret;
-}
-
-int
-fhandler_dev_floppy::open (int flags, mode_t)
-{
- int ret = fhandler_dev_raw::open (flags);
-
- if (ret)
- {
- DWORD bytes_read;
-
- if (get_drive_info (NULL))
- {
- close ();
- return 0;
- }
- if (!(flags & O_DIRECT))
- {
- /* Create sector-aligned buffer. As default buffer size, we're using
- some big, sector-aligned value. Since direct blockdev IO is
- usually non-buffered and non-cached, the performance without
- buffering is worse than access to a file system on same device.
- Whoever uses O_DIRECT has my condolences. */
- devbufsiz = MAX (16 * bytes_per_sector, 65536);
- devbufalloc = new char [devbufsiz + devbufalign];
- devbuf = (char *) roundup2 ((uintptr_t) devbufalloc, devbufalign);
- }
-
- /* If we're not trying to access a floppy disk, make sure we're actually
- allowed to read *all* of the device or volume. This is actually
- documented in the MSDN CreateFile man page. */
- if (get_major () != DEV_FLOPPY_MAJOR
- && !DeviceIoControl (get_handle (), FSCTL_ALLOW_EXTENDED_DASD_IO,
- NULL, 0, NULL, 0, &bytes_read, NULL))
- debug_printf ("DeviceIoControl (FSCTL_ALLOW_EXTENDED_DASD_IO) "
- "failed, %E");
- }
-
- return ret;
-}
-
-int
-fhandler_dev_floppy::close ()
-{
- int ret = fhandler_dev_raw::close ();
-
- if (partitions && InterlockedDecrement (&partitions->refcnt) == 0)
- {
- for (int i = 0; i < MAX_PARTITIONS; ++i)
- if (partitions->hdl[i])
- NtClose (partitions->hdl[i]);
- cfree (partitions);
- }
- return ret;
-}
-
-int
-fhandler_dev_floppy::dup (fhandler_base *child, int flags)
-{
- int ret = fhandler_dev_raw::dup (child, flags);
-
- if (!ret && partitions)
- InterlockedIncrement (&partitions->refcnt);
- return ret;
-}
-
-inline _off64_t
-fhandler_dev_floppy::get_current_position ()
-{
- LARGE_INTEGER off = { QuadPart: 0LL };
- off.LowPart = SetFilePointer (get_handle (), 0, &off.HighPart, FILE_CURRENT);
- return off.QuadPart;
-}
-
-void __stdcall
-fhandler_dev_floppy::raw_read (void *ptr, size_t& ulen)
-{
- DWORD bytes_read = 0;
- DWORD read2;
- DWORD bytes_to_read;
- int ret;
- size_t len = ulen;
- char *tgt;
- char *p = (char *) ptr;
-
- /* Checking a previous end of media */
- if (eom_detected () && !lastblk_to_read ())
- {
- set_errno (ENOSPC);
- goto err;
- }
-
- if (devbuf)
- {
- while (len > 0)
- {
- if (devbufstart < devbufend)
- {
- bytes_to_read = MIN (len, devbufend - devbufstart);
- debug_printf ("read %d bytes from buffer (rest %d)",
- bytes_to_read,
- devbufend - devbufstart - bytes_to_read);
- memcpy (p, devbuf + devbufstart, bytes_to_read);
- len -= bytes_to_read;
- p += bytes_to_read;
- bytes_read += bytes_to_read;
- devbufstart += bytes_to_read;
-
- if (lastblk_to_read ())
- {
- lastblk_to_read (false);
- break;
- }
- }
- if (len > 0)
- {
- if (len >= devbufsiz)
- {
- bytes_to_read = (len / bytes_per_sector) * bytes_per_sector;
- tgt = p;
- }
- else
- {
- tgt = devbuf;
- bytes_to_read = devbufsiz;
- }
- _off64_t current_position = get_current_position ();
- if (current_position + bytes_to_read >= drive_size)
- bytes_to_read = drive_size - current_position;
- if (!bytes_to_read)
- break;
-
- debug_printf ("read %d bytes from pos %U %s", bytes_to_read,
- current_position,
- len < devbufsiz ? "into buffer" : "directly");
- if (!read_file (tgt, bytes_to_read, &read2, &ret))
- {
- if (!IS_EOM (ret))
- {
- __seterrno ();
- goto err;
- }
-
- eom_detected (true);
-
- if (!read2)
- {
- if (!bytes_read)
- {
- debug_printf ("return -1, set errno to ENOSPC");
- set_errno (ENOSPC);
- goto err;
- }
- break;
- }
- lastblk_to_read (true);
- }
- if (!read2)
- break;
- if (tgt == devbuf)
- {
- devbufstart = 0;
- devbufend = read2;
- }
- else
- {
- len -= read2;
- p += read2;
- bytes_read += read2;
- }
- }
- }
- }
- else
- {
- _off64_t current_position = get_current_position ();
- bytes_to_read = len;
- if (current_position + bytes_to_read >= drive_size)
- bytes_to_read = drive_size - current_position;
- debug_printf ("read %d bytes from pos %U directly", bytes_to_read,
- current_position);
- if (bytes_to_read && !read_file (p, bytes_to_read, &bytes_read, &ret))
- {
- if (!IS_EOM (ret))
- {
- __seterrno ();
- goto err;
- }
- if (bytes_read)
- eom_detected (true);
- else
- {
- debug_printf ("return -1, set errno to ENOSPC");
- set_errno (ENOSPC);
- goto err;
- }
- }
- }
-
- ulen = (size_t) bytes_read;
- return;
-
-err:
- ulen = (size_t) -1;
-}
-
-int __stdcall
-fhandler_dev_floppy::raw_write (const void *ptr, size_t len)
-{
- DWORD bytes_written = 0;
- char *p = (char *) ptr;
- int ret;
-
- /* Checking a previous end of media */
- if (eom_detected ())
- {
- set_errno (ENOSPC);
- return -1;
- }
-
- if (!len)
- return 0;
-
- if (devbuf)
- {
- DWORD cplen, written;
-
- /* First check if we have an active read buffer. If so, try to fit in
- the start of the input buffer and write out the entire result.
- This also covers the situation after lseek since lseek fills the read
- buffer in case we seek to an address which is not sector aligned. */
- if (devbufend && devbufstart < devbufend)
- {
- _off64_t current_pos = get_current_position ();
- cplen = MIN (len, devbufend - devbufstart);
- memcpy (devbuf + devbufstart, p, cplen);
- LARGE_INTEGER off = { QuadPart:current_pos - devbufend };
- if (!SetFilePointerEx (get_handle (), off, NULL, FILE_BEGIN))
- {
- devbufstart = devbufend = 0;
- __seterrno ();
- return -1;
- }
- if (!write_file (devbuf, devbufend, &written, &ret))
- {
- devbufstart = devbufend = 0;
- goto err;
- }
- /* Align pointers, lengths, etc. */
- cplen = MIN (cplen, written);
- devbufstart += cplen;
- p += cplen;
- len -= cplen;
- bytes_written += cplen;
- if (len)
- devbufstart = devbufend = 0;
- }
- /* As long as there's still something left in the input buffer ... */
- while (len)
- {
- /* Compute the length to write. The problem is that the underlying
- driver may require sector aligned read/write. So we copy the data
- over to devbuf, which is guaranteed to be sector aligned. */
- cplen = MIN (len, devbufsiz);
- if (cplen >= bytes_per_sector)
- /* If the remaining len is >= sector size, write out the maximum
- possible multiple of the sector size which fits into devbuf. */
- cplen = rounddown (cplen, bytes_per_sector);
- else
- {
- /* If len < sector size, read in the next sector, seek back,
- and just copy the new data over the old one before writing. */
- LARGE_INTEGER off = { QuadPart:get_current_position () };
- if (!read_file (devbuf, bytes_per_sector, &written, &ret))
- goto err;
- if (!SetFilePointerEx (get_handle (), off, NULL, FILE_BEGIN))
- {
- __seterrno ();
- return -1;
- }
- }
- memcpy (devbuf, p, cplen);
- if (!write_file (devbuf, MAX (cplen, bytes_per_sector), &written,
- &ret))
- {
- bytes_written += MIN (cplen, written);
- goto err;
- }
- cplen = MIN (cplen, written);
- p += cplen;
- len -= cplen;
- bytes_written += cplen;
- }
- return bytes_written;
- }
-
- /* In O_DIRECT case, just write. */
- if (write_file (p, len, &bytes_written, &ret))
- return bytes_written;
-
-err:
- if (IS_EOM (ret))
- {
- eom_detected (true);
- if (!bytes_written)
- set_errno (ENOSPC);
- }
- else if (!bytes_written)
- __seterrno ();
- return bytes_written ?: -1;
-}
-
-_off64_t
-fhandler_dev_floppy::lseek (_off64_t offset, int whence)
-{
- char buf[bytes_per_sector];
- _off64_t current_pos = (_off64_t) -1;
- LARGE_INTEGER sector_aligned_offset;
- size_t bytes_left;
-
- if (whence == SEEK_END)
- {
- offset += drive_size;
- whence = SEEK_SET;
- }
- else if (whence == SEEK_CUR)
- {
- current_pos = get_current_position ();
- _off64_t exact_pos = current_pos - (devbufend - devbufstart);
- /* Shortcut when used to get current position. */
- if (offset == 0)
- return exact_pos;
- offset += exact_pos;
- whence = SEEK_SET;
- }
-
- if (whence != SEEK_SET || offset < 0 || offset > drive_size)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- /* If new position is in buffered range, adjust buffer and return */
- if (devbufstart < devbufend)
- {
- if (current_pos == (_off64_t) -1)
- current_pos = get_current_position ();
- if (current_pos - devbufend <= offset && offset <= current_pos)
- {
- devbufstart = devbufend - (current_pos - offset);
- return offset;
- }
- }
-
- sector_aligned_offset.QuadPart = rounddown (offset, bytes_per_sector);
- bytes_left = offset - sector_aligned_offset.QuadPart;
-
- /* Invalidate buffer. */
- devbufstart = devbufend = 0;
-
- if (!SetFilePointerEx (get_handle (), sector_aligned_offset, NULL,
- FILE_BEGIN))
- {
- __seterrno ();
- return -1;
- }
-
- eom_detected (false);
-
- if (bytes_left)
- {
- raw_read (buf, bytes_left);
- if (bytes_left == (size_t) -1)
- return -1;
- }
-
- return sector_aligned_offset.QuadPart + bytes_left;
-}
-
-int
-fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf)
-{
- int ret = 0;
- DWORD bytes_read;
-
- switch (cmd)
- {
- case HDIO_GETGEO:
- debug_printf ("HDIO_GETGEO");
- ret = get_drive_info ((struct hd_geometry *) buf);
- break;
- case BLKGETSIZE:
- case BLKGETSIZE64:
- debug_printf ("BLKGETSIZE");
- if (cmd == BLKGETSIZE)
- *(long *)buf = drive_size >> 9UL;
- else
- *(_off64_t *)buf = drive_size;
- break;
- case BLKRRPART:
- debug_printf ("BLKRRPART");
- if (!DeviceIoControl (get_handle (), IOCTL_DISK_UPDATE_PROPERTIES,
- NULL, 0, NULL, 0, &bytes_read, NULL))
- {
- __seterrno ();
- ret = -1;
- }
- else
- get_drive_info (NULL);
- break;
- case BLKSSZGET:
- debug_printf ("BLKSSZGET");
- *(int *)buf = bytes_per_sector;
- break;
- case BLKIOMIN:
- debug_printf ("BLKIOMIN");
- *(int *)buf = bytes_per_sector;
- break;
- case BLKIOOPT:
- debug_printf ("BLKIOOPT");
- *(int *)buf = bytes_per_sector;
- break;
- case BLKPBSZGET:
- debug_printf ("BLKPBSZGET");
- *(int *)buf = bytes_per_sector;
- break;
- case BLKALIGNOFF:
- debug_printf ("BLKALIGNOFF");
- *(int *)buf = 0;
- break;
- default:
- ret = fhandler_dev_raw::ioctl (cmd, buf);
- break;
- }
- return ret;
-}
-