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:
authorCorinna Vinschen <corinna@vinschen.de>2004-03-14 21:01:45 +0300
committerCorinna Vinschen <corinna@vinschen.de>2004-03-14 21:01:45 +0300
commit6644f5097cdadf7e1747a7d23418e4ba8d03e350 (patch)
tree9cd2c36465d4457872b68f96a6c293a1d308c46a /winsup/cygwin/fhandler_tape.cc
parent83a74ea24a7e60c31858571cb521d2da4ca310f2 (diff)
* errno.cc (errmap): Map ERROR_BEGINNING_OF_MEDIA and
ERROR_SETMARK_DETECTED to EIO instead of ESPIPE. Handle ERROR_FILEMARK_DETECTED. * fhandler_tape.cc (TAPE_FUNC): Add comment that ERROR_BUS_RESET has still to be handled correctly. (fhandler_dev_tape::open): Accomodate fact that get.mt_dsreg also contains density code. (fhandler_dev_tape::ioctl): Rearrange slightly. Reset devbuf also on MTNOP, MTWSM, MTSETBLK, MTSETDRVBUFFER, MTSETPART and MTMKPART. (fhandler_dev_tape::tape_set_pos): Rearrange. Match behaviour to the Linux tape driver. (fhandler_dev_tape::tape_status): Call IOCTL_STORAGE_GET_MEDIA_TYPES_EX if available. Return device type and density code in appropriate mtget members. * wincap.h (wincaps::has_ioctl_storage_get_media_types_ex): New element. * wincap.cc: Implement above element throughout. * include/cygwin/mtio.h: Add tape device types as returned by IOCTL_STORAGE_GET_MEDIA_TYPES_EX. (MT_TAPE_INFO): Use above type codes. (struct mtget): Change mt_dsreg comment.
Diffstat (limited to 'winsup/cygwin/fhandler_tape.cc')
-rw-r--r--winsup/cygwin/fhandler_tape.cc249
1 files changed, 119 insertions, 130 deletions
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
index 0b7452080..2fa5f433f 100644
--- a/winsup/cygwin/fhandler_tape.cc
+++ b/winsup/cygwin/fhandler_tape.cc
@@ -12,7 +12,9 @@ details. */
#include "winsup.h"
#include <sys/termios.h>
#include <unistd.h>
+#include <stdlib.h>
#include <sys/mtio.h>
+#include <ddk/ntddstor.h>
#include "cygerrno.h"
#include "perprocess.h"
#include "security.h"
@@ -24,6 +26,10 @@ details. */
/* Media changes and bus resets are sometimes reported and the function
hasn't been executed. We repeat all functions which return with one
of these error codes. */
+/* FIXME: Note that this is wrong! The correct behaviour after getting
+ an ERROR_BUS_RESET is to raise a flag and then to block any access,
+ except for MTREW, MTOFFL, MT_RETEN, MTERASE, MTSEEK and MTEOM, and
+ to set errno to EIO in all other cases. */
#define TAPE_FUNC(func) do { \
lasterr = (func); \
} while (lasterr == ERROR_MEDIA_CHANGED \
@@ -127,12 +133,16 @@ fhandler_dev_tape::open (int flags, mode_t)
(varlen = sizeof dp, &varlen), &dp));
if (!ioctl (MTIOCGET, &get))
- /* Tape drive supports and is set to variable block size. */
- if (get.mt_dsreg == 0)
- devbufsiz = get.mt_maxblksize;
- else
- devbufsiz = get.mt_dsreg;
- varblkop = get.mt_dsreg == 0;
+ {
+ long blksize = (get.mt_dsreg & MT_ST_BLKSIZE_MASK)
+ >> MT_ST_BLKSIZE_SHIFT;
+ /* Tape drive supports and is set to variable block size. */
+ if (blksize == 0)
+ devbufsiz = get.mt_maxblksize;
+ else
+ devbufsiz = blksize;
+ varblkop = blksize == 0;
+ }
if (devbufsiz > 1L)
devbuf = new char [devbufsiz];
@@ -319,9 +329,11 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
ret = tape_set_pos (TAPE_REWIND, 0);
break;
case MTOFFL:
+ case MTUNLOAD:
ret = tape_prepare (TAPE_UNLOAD);
break;
case MTNOP:
+ reset_devbuf ();
break;
case MTRETEN:
if (!tape_get_feature (TAPE_DRIVE_END_OF_DATA))
@@ -350,63 +362,59 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
ret = ERROR_INVALID_PARAMETER;
break;
case MTSETBLK:
- {
- if (!tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
- {
- ret = ERROR_INVALID_PARAMETER;
- break;
- }
- if ((devbuf && (size_t) op->mt_count == devbufsiz)
- || (!devbuf && op->mt_count == 0))
- {
- /* Nothing has changed. */
- ret = 0;
- break;
- }
- if ((op->mt_count == 0
- && !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
- || (op->mt_count > 0
- && ((DWORD) op->mt_count < dp.MinimumBlockSize
- || (DWORD) op->mt_count > dp.MaximumBlockSize)))
- {
- ret = ERROR_INVALID_PARAMETER;
- break;
- }
- if (devbuf && devbufend - devbufstart > 0
- && (op->mt_count == 0
- || (op->mt_count > 0
- && (size_t) op->mt_count < devbufend - devbufstart)))
- {
- /* Not allowed if still data in devbuf. */
- ret = ERROR_INVALID_BLOCK_LENGTH; /* EIO */
- break;
- }
- if (!(ret = tape_set_blocksize (op->mt_count)))
- {
- char *buf = NULL;
- if (op->mt_count > 1L && !(buf = new char [op->mt_count]))
- {
- ret = ERROR_OUTOFMEMORY;
- break;
- }
- if (devbufsiz > 1L && op->mt_count > 1L)
- {
- memcpy (buf, devbuf + devbufstart,
- devbufend - devbufstart);
- devbufend -= devbufstart;
- }
- else
- devbufend = 0;
- devbufstart = 0;
- delete [] devbuf;
- devbuf = buf;
- devbufsiz = op->mt_count;
- varblkop = op->mt_count == 0;
- }
- }
- break;
- case MTSETDENSITY:
- ret = ERROR_INVALID_PARAMETER;
+ if (!tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
+ {
+ ret = ERROR_INVALID_PARAMETER;
+ break;
+ }
+ if ((devbuf && (size_t) op->mt_count == devbufsiz)
+ || (!devbuf && op->mt_count == 0))
+ {
+ /* Nothing has changed. */
+ ret = 0;
+ break;
+ }
+ if ((op->mt_count == 0
+ && !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
+ || (op->mt_count > 0
+ && ((DWORD) op->mt_count < dp.MinimumBlockSize
+ || (DWORD) op->mt_count > dp.MaximumBlockSize)))
+ {
+ ret = ERROR_INVALID_PARAMETER;
+ break;
+ }
+ if (devbuf && devbufend - devbufstart > 0
+ && (op->mt_count == 0
+ || (op->mt_count > 0
+ && (size_t) op->mt_count < devbufend - devbufstart)))
+ {
+ /* Not allowed if still data in devbuf. */
+ ret = ERROR_INVALID_BLOCK_LENGTH; /* EIO */
+ break;
+ }
+ if (!(ret = tape_set_blocksize (op->mt_count)))
+ {
+ char *buf = NULL;
+ if (op->mt_count > 1L && !(buf = new char [op->mt_count]))
+ {
+ ret = ERROR_OUTOFMEMORY;
+ break;
+ }
+ if (devbufsiz > 1L && op->mt_count > 1L)
+ {
+ memcpy (buf, devbuf + devbufstart,
+ devbufend - devbufstart);
+ devbufend -= devbufstart;
+ }
+ else
+ devbufend = 0;
+ devbufstart = 0;
+ delete [] devbuf;
+ devbuf = buf;
+ devbufsiz = op->mt_count;
+ varblkop = op->mt_count == 0;
+ }
+ reset_devbuf ();
break;
case MTSEEK:
if (tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK)
@@ -420,9 +428,6 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
if (!(ret = tape_get_pos (&block)))
op->mt_count = block;
break;
- case MTSETDRVBUFFER:
- ret = ERROR_INVALID_PARAMETER;
- break;
case MTFSS:
ret = tape_set_pos (TAPE_SPACE_SETMARKS, op->mt_count);
break;
@@ -431,6 +436,7 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
break;
case MTWSM:
ret = tape_write_marks (TAPE_SETMARKS, op->mt_count);
+ reset_devbuf ();
break;
case MTLOCK:
ret = tape_prepare (TAPE_LOCK);
@@ -441,14 +447,14 @@ fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
case MTLOAD:
ret = tape_prepare (TAPE_LOAD);
break;
- case MTUNLOAD:
- ret = tape_prepare (TAPE_UNLOAD);
- break;
case MTCOMPRESSION:
ret = tape_compression (op->mt_count);
break;
case MTSETPART:
case MTMKPART:
+ case MTSETDENSITY:
+ case MTSETDRVBUFFER:
+ reset_devbuf ();
default:
ret = ERROR_INVALID_PARAMETER;
break;
@@ -541,67 +547,29 @@ fhandler_dev_tape::_tape_set_pos (int mode, long count)
int
fhandler_dev_tape::tape_set_pos (int mode, long count, bool sfm_func)
{
- unsigned long pos, tgtpos;
-
switch (mode)
{
case TAPE_SPACE_RELATIVE_BLOCKS:
- if (tape_get_pos (&pos))
- return lasterr;
-
- tgtpos = pos + count;
-
- while (count && (_tape_set_pos (mode, count), IS_EOF (lasterr)))
- {
- if (tape_get_pos (&pos))
- return lasterr;
- count = tgtpos - pos;
- }
-
- if (lasterr == ERROR_BEGINNING_OF_MEDIA && !tgtpos)
- lasterr = NO_ERROR;
-
- break;
case TAPE_SPACE_FILEMARKS:
- if (count < 0)
- {
- if (pos > 0)
- {
- if (!_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -1)
- || (sfm_func))
- ++count;
- _tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, 1);
- }
-
- while (!_tape_set_pos (mode, -1) && count++ < 0)
- ;
-
- if (lasterr == ERROR_BEGINNING_OF_MEDIA)
- {
- if (!count)
- lasterr = NO_ERROR;
- }
- else if (!sfm_func)
- _tape_set_pos (mode, 1);
- }
- else
+ if (!count)
{
- if (sfm_func)
- {
- if (_tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, 1)
- == ERROR_FILEMARK_DETECTED)
- ++count;
- _tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -1);
- }
-
- if (!_tape_set_pos (mode, count) && sfm_func)
- _tape_set_pos (mode, -1);
+ lasterr = 0;
+ return tape_error ("tape_set_pos");
}
break;
case TAPE_ABSOLUTE_BLOCK:
- if (!tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK))
+ if (!tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK))
mode = TAPE_LOGICAL_BLOCK;
- _tape_set_pos (mode, count);
+ break;
+ }
+ _tape_set_pos (mode, count);
+ switch (mode)
+ {
+ case TAPE_SPACE_FILEMARKS:
+ if (!lasterr && sfm_func)
+ return tape_set_pos (mode, count > 0 ? -1 : 1, false);
+ break;
+ case TAPE_ABSOLUTE_BLOCK:
/* Workaround bug in Tandberg SLR device driver, which pretends
to support absolute block positioning but instead returns
ERROR_INVALID_FUNCTION. */
@@ -612,13 +580,7 @@ fhandler_dev_tape::tape_set_pos (int mode, long count, bool sfm_func)
_tape_set_pos (TAPE_LOGICAL_BLOCK, count);
}
break;
- case TAPE_SPACE_SETMARKS:
- case TAPE_SPACE_END_OF_DATA:
- case TAPE_REWIND:
- _tape_set_pos (mode, count);
- break;
}
-
return tape_error ("tape_set_pos");
}
@@ -693,10 +655,37 @@ fhandler_dev_tape::tape_status (struct mtget *get)
}
if (tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE) && !notape)
- get->mt_dsreg = mp.BlockSize;
+ get->mt_dsreg = (mp.BlockSize << MT_ST_BLKSIZE_SHIFT)
+ & MT_ST_BLKSIZE_MASK;
else
- get->mt_dsreg = dp.DefaultBlockSize;
-
+ get->mt_dsreg = (dp.DefaultBlockSize << MT_ST_BLKSIZE_SHIFT)
+ & MT_ST_BLKSIZE_MASK;
+ if (wincap.has_ioctl_storage_get_media_types_ex ())
+ {
+ DWORD size = sizeof (GET_MEDIA_TYPES) + 10 * sizeof (DEVICE_MEDIA_INFO);
+ void *buf = alloca (size);
+ if (DeviceIoControl (get_handle (), IOCTL_STORAGE_GET_MEDIA_TYPES_EX,
+ NULL, 0, buf, size, &size, NULL)
+ || GetLastError () == ERROR_MORE_DATA)
+ {
+ PGET_MEDIA_TYPES gmt = (PGET_MEDIA_TYPES) buf;
+ for (DWORD i = 0; i < gmt->MediaInfoCount; ++i)
+ {
+ PDEVICE_MEDIA_INFO dmi = &gmt->MediaInfo[i];
+#define TINFO DeviceSpecific.TapeInfo
+ if (dmi->TINFO.MediaCharacteristics & MEDIA_CURRENTLY_MOUNTED)
+ {
+ get->mt_type = dmi->DeviceSpecific.TapeInfo.MediaType;
+ if (dmi->TINFO.BusType == BusTypeScsi)
+ get->mt_dsreg |=
+ (dmi->TINFO.BusSpecificData.ScsiInformation.DensityCode
+ << MT_ST_DENSITY_SHIFT)
+ & MT_ST_DENSITY_MASK;
+ }
+#undef TINFO
+ }
+ }
+ }
if (notape)
get->mt_gstat |= GMT_DR_OPEN (-1);