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:
Diffstat (limited to 'winsup/cygwin/fhandler_tape.cc')
-rw-r--r--winsup/cygwin/fhandler_tape.cc1517
1 files changed, 0 insertions, 1517 deletions
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
deleted file mode 100644
index 036407685..000000000
--- a/winsup/cygwin/fhandler_tape.cc
+++ /dev/null
@@ -1,1517 +0,0 @@
-/* fhandler_tape.cc. See fhandler.h for a description of the fhandler
- classes.
-
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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 "cygtls.h"
-#include <sys/termios.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/mtio.h>
-#include <sys/param.h>
-#include <ddk/ntddstor.h>
-#include "cygerrno.h"
-#include "perprocess.h"
-#include "security.h"
-#include "path.h"
-#include "fhandler.h"
-#include "dtable.h"
-#include "cygheap.h"
-#include "shared_info.h"
-#include "sigproc.h"
-#include "mtinfo.h"
-
-/* 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. */
-#define TAPE_FUNC(func) while ((lasterr = (func)) == ERROR_MEDIA_CHANGED) \
- { \
- initialize (drive, false); \
- part (partition)->initialize (0); \
- }
-
-#define IS_BOT(err) ((err) == ERROR_BEGINNING_OF_MEDIA)
-
-#define IS_EOF(err) ((err) == ERROR_FILEMARK_DETECTED \
- || (err) == ERROR_SETMARK_DETECTED)
-
-#define IS_SM(err) ((err) == ERROR_SETMARK_DETECTED)
-
-#define IS_EOD(err) ((err) == ERROR_END_OF_MEDIA \
- || (err) == ERROR_EOM_OVERFLOW \
- || (err) == ERROR_NO_DATA_DETECTED)
-
-#define IS_EOM(err) ((err) == ERROR_END_OF_MEDIA \
- || (err) == ERROR_EOM_OVERFLOW)
-
-/**********************************************************************/
-/* mtinfo_part */
-
-void
-mtinfo_part::initialize (long nblock)
-{
- block = nblock;
- if (block == 0)
- file = fblock = 0;
- else
- file = fblock = -1;
- smark = false;
- emark = no_eof;
-}
-
-/**********************************************************************/
-/* mtinfo_drive */
-
-void
-mtinfo_drive::initialize (int num, bool first_time)
-{
- drive = num;
- partition = 0;
- block = -1;
- lock = unlocked;
- if (first_time)
- {
- buffer_writes (true);
- async_writes (false);
- two_fm (false);
- fast_eom (false);
- auto_lock (false);
- sysv (false);
- nowait (false);
- }
- for (int i = 0; i < MAX_PARTITION_NUM; ++i)
- part (i)->initialize ();
-}
-
-int
-mtinfo_drive::get_dp (HANDLE mt)
-{
- DWORD len = sizeof _dp;
- TAPE_FUNC (GetTapeParameters (mt, GET_TAPE_DRIVE_INFORMATION, &len, &_dp));
- return error ("get_dp");
-}
-
-int
-mtinfo_drive::get_mp (HANDLE mt)
-{
- DWORD len = sizeof _mp;
- TAPE_FUNC (GetTapeParameters (mt, GET_TAPE_MEDIA_INFORMATION, &len, &_mp));
- return error ("get_mp");
-}
-
-int
-mtinfo_drive::open (HANDLE mt)
-{
- get_dp (mt);
- get_mp (mt);
- get_pos (mt);
- if (partition < MAX_PARTITION_NUM && part (partition)->block != block)
- part (partition)->initialize (block);
- /* The following rewind in position 0 solves a problem which appears
- * in case of multi volume archives (at least on NT4): The last ReadFile
- * on the previous medium returns ERROR_NO_DATA_DETECTED. After media
- * change, all subsequent ReadFile calls return ERROR_NO_DATA_DETECTED,
- * too. The call to set_pos apparently reset some internal flags.
- * FIXME: Is that really true or based on a misinterpretation? */
- if (!block)
- {
- debug_printf ("rewind in position 0");
- set_pos (mt, TAPE_REWIND, 0, false);
- }
- return error ("open");
-}
-
-int
-mtinfo_drive::close (HANDLE mt, bool rewind)
-{
- lasterr = 0;
- if (GetTapeStatus (mt) == ERROR_NO_MEDIA_IN_DRIVE)
- dirty = clean;
- if (dirty >= has_written)
- {
- /* If an async write is still pending, wait for completion. */
- if (dirty == async_write_pending)
- lasterr = async_wait (mt, NULL);
- if (!lasterr)
- {
- /* if last operation was writing, write a filemark */
- debug_printf ("writing filemark");
- write_marks (mt, TAPE_FILEMARKS, two_fm () ? 2 : 1);
- if (two_fm () && !lasterr && !rewind) /* Backspace over 2nd fmark. */
- {
- set_pos (mt, TAPE_SPACE_FILEMARKS, -1, false);
- if (!lasterr)
- part (partition)->fblock = 0; /* That's obvious, isn't it? */
- }
- }
- }
- else if (dirty == has_read && !rewind)
- {
- if (sysv ())
- {
- /* Under SYSV semantics, the tape is moved past the next file mark
- after read. */
- if (part (partition)->emark == no_eof)
- set_pos (mt, TAPE_SPACE_FILEMARKS, 1, false);
- else if (part (partition)->emark == eof_hit)
- part (partition)->emark = eof;
- }
- else
- {
- /* Under BSD semantics, we must check if the filemark has been
- inadvertendly crossed. If so cross the filemark backwards
- and position the tape right before EOF. */
- if (part (partition)->emark == eof_hit)
- set_pos (mt, TAPE_SPACE_FILEMARKS, -1, false);
- }
- }
- if (rewind)
- {
- debug_printf ("rewinding");
- set_pos (mt, TAPE_REWIND, 0, false);
- }
- if (auto_lock () && lock == auto_locked)
- prepare (mt, TAPE_UNLOCK);
- dirty = clean;
- return error ("close");
-}
-
-int
-mtinfo_drive::read (HANDLE mt, HANDLE mt_evt, void *ptr, size_t &ulen)
-{
- BOOL ret;
- DWORD bytes_read = 0;
-
- if (GetTapeStatus (mt) == ERROR_NO_MEDIA_IN_DRIVE)
- return lasterr = ERROR_NO_MEDIA_IN_DRIVE;
- if (lasterr == ERROR_BUS_RESET)
- {
- ulen = 0;
- goto out;
- }
- /* If an async write is still pending, wait for completion. */
- if (dirty == async_write_pending)
- lasterr = async_wait (mt, NULL);
- dirty = clean;
- if (part (partition)->emark == eof_hit)
- {
- part (partition)->emark = eof;
- lasterr = ulen = 0;
- goto out;
- }
- else if (part (partition)->emark == eod_hit)
- {
- part (partition)->emark = eod;
- lasterr = ulen = 0;
- goto out;
- }
- else if (part (partition)->emark == eod)
- {
- lasterr = ERROR_NO_DATA_DETECTED;
- ulen = (size_t) -1;
- goto out;
- }
- else if (part (partition)->emark == eom_hit)
- {
- part (partition)->emark = eom;
- lasterr = ulen = 0;
- goto out;
- }
- else if (part (partition)->emark == eom)
- {
- lasterr = ERROR_END_OF_MEDIA;
- ulen = (size_t) -1;
- goto out;
- }
- part (partition)->smark = false;
- if (auto_lock () && lock < auto_locked)
- prepare (mt, TAPE_LOCK, true);
- ov.Offset = ov.OffsetHigh = 0;
- ov.hEvent = mt_evt;
- ret = ReadFile (mt, ptr, ulen, &bytes_read, &ov);
- lasterr = ret ? 0 : GetLastError ();
- if (lasterr == ERROR_IO_PENDING)
- lasterr = async_wait (mt, &bytes_read);
- ulen = (size_t) bytes_read;
- if (bytes_read > 0)
- {
- long blocks_read = mp ()->BlockSize == 0
- ? 1 : howmany (bytes_read, mp ()->BlockSize);
- block += blocks_read;
- part (partition)->block += blocks_read;
- if (part (partition)->fblock >= 0)
- part (partition)->fblock += blocks_read;
- }
- if (IS_EOF (lasterr))
- {
- block++;
- part (partition)->block++;
- if (part (partition)->file >= 0)
- part (partition)->file++;
- part (partition)->fblock = 0;
- part (partition)->smark = IS_SM (lasterr);
- part (partition)->emark = bytes_read > 0 ? eof_hit : eof;
- lasterr = 0;
- }
- else if (IS_EOD (lasterr))
- {
- if (part (partition)->emark == eof)
- part (partition)->emark = IS_EOM (lasterr) ? eom : eod;
- else
- {
- part (partition)->emark = IS_EOM (lasterr) ? eom_hit : eod_hit;
- lasterr = 0;
- }
- }
- else
- {
- part (partition)->emark = no_eof;
- /* This happens if the buffer is too small when in variable block
- size mode. Linux returns ENOMEM here. We're doing the same. */
- if (lasterr == ERROR_MORE_DATA)
- lasterr = ERROR_NOT_ENOUGH_MEMORY;
- }
- if (!lasterr)
- dirty = has_read;
-out:
- return error ("read");
-}
-
-int
-mtinfo_drive::async_wait (HANDLE mt, DWORD *bytes_written)
-{
- DWORD written;
-
- bool ret = GetOverlappedResult (mt, &ov, &written, TRUE);
- if (bytes_written)
- *bytes_written = written;
- return ret ? 0 : GetLastError ();
-}
-
-int
-mtinfo_drive::write (HANDLE mt, HANDLE mt_evt, const void *ptr, size_t &len)
-{
- BOOL ret;
- DWORD bytes_written = 0;
- int async_err = 0;
-
- if (GetTapeStatus (mt) == ERROR_NO_MEDIA_IN_DRIVE)
- return lasterr = ERROR_NO_MEDIA_IN_DRIVE;
- if (lasterr == ERROR_BUS_RESET)
- {
- len = 0;
- return error ("write");
- }
- if (dirty == async_write_pending)
- async_err = async_wait (mt, &bytes_written);
- dirty = clean;
- part (partition)->smark = false;
- if (auto_lock () && lock < auto_locked)
- prepare (mt, TAPE_LOCK, true);
- ov.Offset = ov.OffsetHigh = 0;
- ov.hEvent = mt_evt;
- ret = WriteFile (mt, ptr, len, &bytes_written, &ov);
- lasterr = ret ? 0: GetLastError ();
- if (lasterr == ERROR_IO_PENDING)
- {
- if (async_writes () && mp ()->BlockSize == 0)
- dirty = async_write_pending;
- else
- /* Wait for completion if a non-async write. */
- lasterr = async_wait (mt, &bytes_written);
- }
- len = (size_t) bytes_written;
- if (bytes_written > 0)
- {
- long blocks_written = mp ()->BlockSize == 0
- ? 1 : howmany (bytes_written, mp ()->BlockSize);
- block += blocks_written;
- part (partition)->block += blocks_written;
- if (part (partition)->fblock >= 0)
- part (partition)->fblock += blocks_written;
- }
- if (!lasterr && async_err)
- lasterr = async_err;
- if (lasterr == ERROR_EOM_OVERFLOW)
- part (partition)->emark = eom;
- else if (lasterr == ERROR_END_OF_MEDIA)
- ; // FIXME?: part (partition)->emark = eom_hit;
- else
- {
- part (partition)->emark = no_eof;
- if (!lasterr)
- dirty = has_written;
- else if (lasterr == ERROR_IO_PENDING)
- dirty = async_write_pending;
- }
- return error ("write");
-}
-
-int
-mtinfo_drive::get_pos (HANDLE mt, long *ppartition, long *pblock)
-{
- DWORD p, low, high;
-
- TAPE_FUNC (GetTapePosition (mt, TAPE_LOGICAL_POSITION, &p, &low, &high));
- if (lasterr == ERROR_INVALID_FUNCTION)
- TAPE_FUNC (GetTapePosition (mt, TAPE_ABSOLUTE_POSITION, &p, &low, &high));
- if (!lasterr)
- {
- if (p > 0)
- partition = (long) p - 1;
- block = (long) low;
- if (ppartition)
- *ppartition= partition;
- if (pblock)
- *pblock = block;
- }
- else
- {
- partition = 0;
- block = -1;
- }
- return error ("get_pos");
-}
-
-int
-mtinfo_drive::_set_pos (HANDLE mt, int mode, long count, int partition,
- BOOL dont_wait)
-{
- /* If an async write is still pending, wait for completion. */
- if (dirty == async_write_pending)
- lasterr = async_wait (mt, NULL);
- dirty = clean;
- TAPE_FUNC (SetTapePosition (mt, mode, partition, count, count < 0 ? -1 : 0,
- dont_wait));
- return lasterr;
-}
-
-int
-mtinfo_drive::set_pos (HANDLE mt, int mode, long count,
- bool sfm_func)
-{
- int err = 0;
- long undone = count;
- BOOL dont_wait = FALSE;
-
- switch (mode)
- {
- case TAPE_SPACE_RELATIVE_BLOCKS:
- case TAPE_SPACE_FILEMARKS:
- case TAPE_SPACE_SETMARKS:
- if (!count)
- {
- lasterr = 0;
- goto out;
- }
- break;
- case TAPE_ABSOLUTE_BLOCK:
- case TAPE_LOGICAL_BLOCK:
- case TAPE_REWIND:
- dont_wait = nowait () ? TRUE : FALSE;
- break;
- }
- if (mode == TAPE_SPACE_FILEMARKS)
- {
- while (!err && undone > 0)
- if (!(err = _set_pos (mt, mode, 1, 0, FALSE)) || IS_SM (err))
- --undone;
- while (!err && undone < 0)
- if (!(err = _set_pos (mt, mode, -1, 0, FALSE)) || IS_SM (err))
- ++undone;
- }
- else
- err = _set_pos (mt, mode, count, 0, dont_wait);
- switch (mode)
- {
- case TAPE_ABSOLUTE_BLOCK:
- case TAPE_LOGICAL_BLOCK:
- get_pos (mt);
- part (partition)->initialize (block);
- break;
- case TAPE_REWIND:
- if (!err)
- {
- block = 0;
- part (partition)->initialize (0);
- }
- else
- {
- get_pos (mt);
- part (partition)->initialize (block);
- }
- break;
- case TAPE_SPACE_END_OF_DATA:
- get_pos (mt);
- part (partition)->initialize (block);
- part (partition)->emark = IS_EOM (err) ? eom : eod;
- break;
- case TAPE_SPACE_FILEMARKS:
- if (!err || IS_SM (err))
- {
- get_pos (mt);
- part (partition)->block = block;
- if (count > 0)
- {
- if (part (partition)->file >= 0)
- part (partition)->file += count - undone;
- part (partition)->fblock = 0;
- part (partition)->smark = IS_SM (err);
- }
- else
- {
- if (part (partition)->file >= 0)
- part (partition)->file += count - undone;
- part (partition)->fblock = -1;
- part (partition)->smark = false;
- }
- if (sfm_func)
- err = set_pos (mt, mode, count > 0 ? -1 : 1, false);
- else
- part (partition)->emark = count > 0 ? eof : no_eof;
- }
- else if (IS_EOD (err))
- {
- get_pos (mt);
- part (partition)->block = block;
- if (part (partition)->file >= 0)
- part (partition)->file += count - undone;
- part (partition)->fblock = -1;
- part (partition)->smark = false;
- part (partition)->emark = IS_EOM (err) ? eom : eod;
- }
- else if (IS_BOT (err))
- {
- block = 0;
- part (partition)->initialize (0);
- }
- else
- {
- get_pos (mt);
- part (partition)->initialize (block);
- }
- break;
- case TAPE_SPACE_RELATIVE_BLOCKS:
- if (!err)
- {
- block += count;
- part (partition)->block += count;
- if (part (partition)->fblock >= 0)
- part (partition)->fblock += count;
- part (partition)->smark = false;
- part (partition)->emark = no_eof;
- }
- else if (IS_EOF (err))
- {
- get_pos (mt);
- part (partition)->block = block;
- if (part (partition)->file >= 0)
- part (partition)->file += count > 0 ? 1 : -1;
- part (partition)->fblock = count > 0 ? 0 : -1;
- part (partition)->smark = (count > 0 && IS_SM (err));
- part (partition)->emark = count > 0 ? eof : no_eof;
- }
- else if (IS_EOD (err))
- {
- get_pos (mt);
- part (partition)->fblock = block - part (partition)->block;
- part (partition)->block = block;
- part (partition)->smark = false;
- part (partition)->emark = IS_EOM (err) ? eom : eod;
- }
- else if (IS_BOT (err))
- {
- block = 0;
- part (partition)->initialize (0);
- }
- break;
- case TAPE_SPACE_SETMARKS:
- get_pos (mt);
- part (partition)->block = block;
- if (!err)
- {
- part (partition)->file = -1;
- part (partition)->fblock = -1;
- part (partition)->smark = true;
- }
- break;
- }
- lasterr = err;
-out:
- return error ("set_pos");
-}
-
-int
-mtinfo_drive::create_partitions (HANDLE mt, long count)
-{
- if (dp ()->MaximumPartitionCount <= 1)
- return ERROR_INVALID_PARAMETER;
- if (set_pos (mt, TAPE_REWIND, 0, false))
- goto out;
- partition = 0;
- part (partition)->initialize (0);
- debug_printf ("Format tape with %s partition(s)", count <= 0 ? "one" : "two");
- if (get_feature (TAPE_DRIVE_INITIATOR))
- {
- if (count <= 0)
- TAPE_FUNC (CreateTapePartition (mt, TAPE_INITIATOR_PARTITIONS,
- count <= 0 ? 0 : 2, (DWORD) count));
- }
- else if (get_feature (TAPE_DRIVE_FIXED))
- {
- /* This is supposed to work for Tandberg SLR drivers up to version
- 1.6 which missed to set the TAPE_DRIVE_INITIATOR flag. According
- to Tandberg, CreateTapePartition(TAPE_FIXED_PARTITIONS) apparently
- does not ignore the dwCount parameter. Go figure! */
- TAPE_FUNC (CreateTapePartition (mt, TAPE_FIXED_PARTITIONS,
- count <= 0 ? 0 : 2, (DWORD) count));
- }
- else
- lasterr = ERROR_INVALID_PARAMETER;
-out:
- return error ("partition");
-}
-
-int
-mtinfo_drive::set_partition (HANDLE mt, long count)
-{
- if (count < 0 || (unsigned long) count >= MAX_PARTITION_NUM)
- lasterr = ERROR_INVALID_PARAMETER;
- else if ((DWORD) count >= dp ()->MaximumPartitionCount)
- lasterr = ERROR_IO_DEVICE;
- else
- {
- int part_block = part (count)->block >= 0 ? part (count)->block : 0;
- int err = _set_pos (mt, TAPE_LOGICAL_BLOCK, part_block, count + 1, FALSE);
- if (err)
- {
- int sav_block = block;
- int sav_partition = partition;
- get_pos (mt);
- if (sav_partition != partition)
- {
- if (partition < MAX_PARTITION_NUM
- && part (partition)->block != block)
- part (partition)->initialize (block);
- }
- else if (sav_block != block && partition < MAX_PARTITION_NUM)
- part (partition)->initialize (block);
- lasterr = err;
- }
- else
- {
- partition = count;
- if (part (partition)->block == -1)
- part (partition)->initialize (0);
- }
- }
- return error ("set_partition");
-}
-
-int
-mtinfo_drive::write_marks (HANDLE mt, int marktype, DWORD count)
-{
- /* If an async write is still pending, wait for completion. */
- if (dirty == async_write_pending)
- {
- lasterr = async_wait (mt, NULL);
- dirty = has_written;
- }
- if (marktype != TAPE_SETMARKS)
- dirty = clean;
- if (marktype == TAPE_FILEMARKS
- && !get_feature (TAPE_DRIVE_WRITE_FILEMARKS))
- {
- if (get_feature (TAPE_DRIVE_WRITE_LONG_FMKS))
- marktype = TAPE_LONG_FILEMARKS;
- else
- marktype = TAPE_SHORT_FILEMARKS;
- }
- TAPE_FUNC (WriteTapemark (mt, marktype, count, FALSE));
- int err = lasterr;
- if (!err)
- {
- block += count;
- part (partition)->block += count;
- if (part (partition)->file >= 0)
- part (partition)->file += count;
- part (partition)->fblock = 0;
- part (partition)->emark = eof;
- part (partition)->smark = (marktype == TAPE_SETMARKS);
- }
- else
- {
- int sav_block = block;
- int sav_partition = partition;
- get_pos (mt);
- if (sav_partition != partition)
- {
- if (partition < MAX_PARTITION_NUM
- && part (partition)->block != block)
- part (partition)->initialize (block);
- }
- else if (sav_block != block && partition < MAX_PARTITION_NUM)
- part (partition)->initialize (block);
- lasterr = err;
- }
- return error ("write_marks");
-}
-
-int
-mtinfo_drive::erase (HANDLE mt, int mode)
-{
- switch (mode)
- {
- case TAPE_ERASE_SHORT:
- if (!get_feature (TAPE_DRIVE_ERASE_SHORT))
- mode = TAPE_ERASE_LONG;
- break;
- case TAPE_ERASE_LONG:
- if (!get_feature (TAPE_DRIVE_ERASE_LONG))
- mode = TAPE_ERASE_SHORT;
- break;
- }
- TAPE_FUNC (EraseTape (mt, mode, nowait () ? TRUE : FALSE));
- part (partition)->initialize (0);
- return error ("erase");
-}
-
-int
-mtinfo_drive::prepare (HANDLE mt, int action, bool is_auto)
-{
- BOOL dont_wait = FALSE;
-
- /* If an async write is still pending, wait for completion. */
- if (dirty == async_write_pending)
- lasterr = async_wait (mt, NULL);
- dirty = clean;
- if (action == TAPE_UNLOAD || action == TAPE_LOAD || action == TAPE_TENSION)
- dont_wait = nowait () ? TRUE : FALSE;
- TAPE_FUNC (PrepareTape (mt, action, dont_wait));
- /* Reset buffer after all successful preparations but lock and unlock. */
- switch (action)
- {
- case TAPE_FORMAT:
- case TAPE_UNLOAD:
- case TAPE_LOAD:
- initialize (drive, false);
- break;
- case TAPE_TENSION:
- part (partition)->initialize (0);
- break;
- case TAPE_LOCK:
- lock = lasterr ? lock_error : is_auto ? auto_locked : locked;
- break;
- case TAPE_UNLOCK:
- lock = lasterr ? lock_error : unlocked;
- break;
- }
- return error ("prepare");
-}
-
-int
-mtinfo_drive::set_compression (HANDLE mt, long count)
-{
- if (!get_feature (TAPE_DRIVE_SET_COMPRESSION))
- return ERROR_INVALID_PARAMETER;
- TAPE_SET_DRIVE_PARAMETERS sdp =
- {
- dp ()->ECC,
- count ? TRUE : FALSE,
- dp ()->DataPadding,
- dp ()->ReportSetmarks,
- dp ()->EOTWarningZoneSize
- };
- TAPE_FUNC (SetTapeParameters (mt, SET_TAPE_DRIVE_INFORMATION, &sdp));
- int err = lasterr;
- if (!err)
- dp ()->Compression = sdp.Compression;
- else
- get_dp (mt);
- lasterr = err;
- return error ("set_compression");
-}
-
-int
-mtinfo_drive::set_blocksize (HANDLE mt, long count)
-{
- TAPE_SET_MEDIA_PARAMETERS smp = {count};
- TAPE_FUNC (SetTapeParameters (mt, SET_TAPE_MEDIA_INFORMATION, &smp));
- return error ("set_blocksize");
-}
-
-int
-mtinfo_drive::get_status (HANDLE mt, struct mtget *get)
-{
- int notape = 0;
- DWORD tstat;
-
- if (!get)
- return ERROR_INVALID_PARAMETER;
-
- if ((tstat = GetTapeStatus (mt)) == ERROR_NO_MEDIA_IN_DRIVE)
- notape = 1;
-
- memset (get, 0, sizeof *get);
-
- get->mt_type = MT_ISUNKNOWN;
-
- if (!notape && get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
- get->mt_dsreg = (mp ()->BlockSize << MT_ST_BLKSIZE_SHIFT)
- & MT_ST_BLKSIZE_MASK;
- else
- 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 (mt, 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];
- get->mt_type = dmi->DeviceSpecific.TapeInfo.MediaType;
-#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;
- break;
- }
-#undef TINFO
- }
- }
- }
-
- if (!notape)
- {
- get->mt_resid = partition;
- get->mt_fileno = part (partition)->file;
- get->mt_blkno = part (partition)->fblock;
-
- if (get->mt_blkno == 0)
- if (get->mt_fileno == 0)
- get->mt_gstat |= GMT_BOT (-1);
- else
- get->mt_gstat |= GMT_EOF (-1);
- if (part (partition)->emark >= eod_hit)
- get->mt_gstat |= GMT_EOD (-1);
- if (part (partition)->emark >= eom_hit)
- get->mt_gstat |= GMT_EOT (-1);
-
- if (part (partition)->smark)
- get->mt_gstat |= GMT_SM (-1);
-
- get->mt_gstat |= GMT_ONLINE (-1);
-
- if (mp ()->WriteProtected)
- get->mt_gstat |= GMT_WR_PROT (-1);
-
- get->mt_capacity = get_ll (mp ()->Capacity);
- get->mt_remaining = get_ll (mp ()->Remaining);
- }
-
- if (notape)
- get->mt_gstat |= GMT_DR_OPEN (-1);
-
- if (buffer_writes ())
- get->mt_gstat |= GMT_IM_REP_EN (-1); /* TODO: Async writes */
-
- if (tstat == ERROR_DEVICE_REQUIRES_CLEANING)
- get->mt_gstat |= GMT_CLN (-1);
-
- /* Cygwin specials: */
- if (dp ()->ReportSetmarks)
- get->mt_gstat |= GMT_REP_SM (-1);
- if (dp ()->DataPadding)
- get->mt_gstat |= GMT_PADDING (-1);
- if (dp ()->ECC)
- get->mt_gstat |= GMT_HW_ECC (-1);
- if (dp ()->Compression)
- get->mt_gstat |= GMT_HW_COMP (-1);
- if (two_fm ())
- get->mt_gstat |= GMT_TWO_FM (-1);
- if (fast_eom ())
- get->mt_gstat |= GMT_FAST_MTEOM (-1);
- if (auto_lock ())
- get->mt_gstat |= GMT_AUTO_LOCK (-1);
- if (sysv ())
- get->mt_gstat |= GMT_SYSV (-1);
- if (nowait ())
- get->mt_gstat |= GMT_NOWAIT (-1);
- if (async_writes ())
- get->mt_gstat |= GMT_ASYNC (-1);
-
- get->mt_erreg = 0; /* FIXME: No softerr counting */
-
- get->mt_minblksize = dp ()->MinimumBlockSize;
- get->mt_maxblksize = dp ()->MaximumBlockSize;
- get->mt_defblksize = dp ()->DefaultBlockSize;
- get->mt_featureslow = dp ()->FeaturesLow;
- get->mt_featureshigh = dp ()->FeaturesHigh;
- get->mt_eotwarningzonesize = dp ()->EOTWarningZoneSize;
-
- return 0;
-}
-
-int
-mtinfo_drive::set_options (HANDLE mt, long options)
-{
- long what = (options & MT_ST_OPTIONS);
- bool call_setparams = false;
- bool set;
- TAPE_SET_DRIVE_PARAMETERS sdp =
- {
- dp ()->ECC,
- dp ()->Compression,
- dp ()->DataPadding,
- dp ()->ReportSetmarks,
- dp ()->EOTWarningZoneSize
- };
-
- lasterr = 0;
- switch (what)
- {
- case 0:
- if (options == 0 || options == 1)
- {
- buffer_writes ((options == 1));
- }
- break;
- case MT_ST_BOOLEANS:
- buffer_writes (!!(options & MT_ST_BUFFER_WRITES));
- async_writes (!!(options & MT_ST_ASYNC_WRITES));
- two_fm (!!(options & MT_ST_TWO_FM));
- fast_eom (!!(options & MT_ST_FAST_MTEOM));
- auto_lock (!!(options & MT_ST_AUTO_LOCK));
- sysv (!!(options & MT_ST_SYSV));
- nowait (!!(options & MT_ST_NOWAIT));
- if (get_feature (TAPE_DRIVE_SET_ECC))
- sdp.ECC = !!(options & MT_ST_ECC);
- if (get_feature (TAPE_DRIVE_SET_PADDING))
- sdp.DataPadding = !!(options & MT_ST_PADDING);
- if (get_feature (TAPE_DRIVE_SET_REPORT_SMKS))
- sdp.ReportSetmarks = !!(options & MT_ST_REPORT_SM);
- if (sdp.ECC != dp ()->ECC || sdp.DataPadding != dp ()->DataPadding
- || sdp.ReportSetmarks != dp ()->ReportSetmarks)
- call_setparams = true;
- break;
- case MT_ST_SETBOOLEANS:
- case MT_ST_CLEARBOOLEANS:
- set = (what == MT_ST_SETBOOLEANS);
- if (options & MT_ST_BUFFER_WRITES)
- buffer_writes (set);
- if (options & MT_ST_ASYNC_WRITES)
- async_writes (set);
- if (options & MT_ST_TWO_FM)
- two_fm (set);
- if (options & MT_ST_FAST_MTEOM)
- fast_eom (set);
- if (options & MT_ST_AUTO_LOCK)
- auto_lock (set);
- if (options & MT_ST_SYSV)
- sysv (set);
- if (options & MT_ST_NOWAIT)
- nowait (set);
- if (options & MT_ST_ECC)
- sdp.ECC = set;
- if (options & MT_ST_PADDING)
- sdp.DataPadding = set;
- if (options & MT_ST_REPORT_SM)
- sdp.ReportSetmarks = set;
- if (sdp.ECC != dp ()->ECC || sdp.DataPadding != dp ()->DataPadding
- || sdp.ReportSetmarks != dp ()->ReportSetmarks)
- call_setparams = true;
- break;
- case MT_ST_EOT_WZ_SIZE:
- if (get_feature (TAPE_DRIVE_SET_EOT_WZ_SIZE))
- {
- sdp.EOTWarningZoneSize = (options & ~MT_ST_OPTIONS);
- if (sdp.EOTWarningZoneSize != dp ()->EOTWarningZoneSize)
- call_setparams = true;
- }
- break;
- }
- if (call_setparams)
- {
- TAPE_FUNC (SetTapeParameters (mt, SET_TAPE_DRIVE_INFORMATION, &sdp));
- int err = lasterr;
- if (!err)
- {
- dp ()->ECC = sdp.ECC;
- dp ()->DataPadding = sdp.DataPadding;
- dp ()->ReportSetmarks = sdp.ReportSetmarks;
- }
- else
- get_dp (mt);
- lasterr = err;
- }
- return error ("set_options");
-}
-
-int
-mtinfo_drive::ioctl (HANDLE mt, unsigned int cmd, void *buf)
-{
- myfault efault;
- if (efault.faulted ())
- return ERROR_NOACCESS;
- if (cmd == MTIOCTOP)
- {
- struct mtop *op = (struct mtop *) buf;
- if (lasterr == ERROR_BUS_RESET)
- {
- /* If a bus reset occurs, block further access to this device
- until the user rewinds, unloads or in any other way tries
- to maintain a well-known tape position. */
- if (op->mt_op != MTREW && op->mt_op != MTOFFL
- && op->mt_op != MTRETEN && op->mt_op != MTERASE
- && op->mt_op != MTSEEK && op->mt_op != MTEOM)
- return ERROR_BUS_RESET;
- /* Try to maintain last lock state after bus reset. */
- if (lock >= auto_locked && PrepareTape (mt, TAPE_LOCK, FALSE))
- {
- debug_printf ("Couldn't relock drive after bus reset.");
- lock = unlocked;
- }
- }
- switch (op->mt_op)
- {
- case MTRESET:
- break;
- case MTFSF:
- set_pos (mt, TAPE_SPACE_FILEMARKS, op->mt_count, false);
- break;
- case MTBSF:
- set_pos (mt, TAPE_SPACE_FILEMARKS, -op->mt_count, false);
- break;
- case MTFSR:
- set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS, op->mt_count, false);
- break;
- case MTBSR:
- set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS, -op->mt_count, false);
- break;
- case MTWEOF:
- write_marks (mt, TAPE_FILEMARKS, op->mt_count);
- break;
- case MTREW:
- set_pos (mt, TAPE_REWIND, 0, false);
- break;
- case MTOFFL:
- case MTUNLOAD:
- prepare (mt, TAPE_UNLOAD);
- break;
- case MTNOP:
- lasterr = 0;
- break;
- case MTRETEN:
- if (!get_feature (TAPE_DRIVE_TENSION))
- lasterr = ERROR_INVALID_PARAMETER;
- else if (!set_pos (mt, TAPE_REWIND, 0, false))
- prepare (mt, TAPE_TENSION);
- break;
- case MTBSFM:
- set_pos (mt, TAPE_SPACE_FILEMARKS, -op->mt_count, true);
- break;
- case MTFSFM:
- set_pos (mt, TAPE_SPACE_FILEMARKS, op->mt_count, true);
- break;
- case MTEOM:
- if (fast_eom () && get_feature (TAPE_DRIVE_END_OF_DATA))
- set_pos (mt, TAPE_SPACE_END_OF_DATA, 0, false);
- else
- set_pos (mt, TAPE_SPACE_FILEMARKS, 32767, false);
- break;
- case MTERASE:
- erase (mt, TAPE_ERASE_LONG);
- break;
- case MTRAS1:
- case MTRAS2:
- case MTRAS3:
- lasterr = ERROR_INVALID_PARAMETER;
- break;
- case MTSETBLK:
- if (!get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
- {
- lasterr = ERROR_INVALID_PARAMETER;
- break;
- }
- if ((DWORD) op->mt_count == mp ()->BlockSize)
- {
- /* Nothing has changed. */
- lasterr = 0;
- break;
- }
- if ((op->mt_count == 0 && !get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
- || (op->mt_count > 0
- && ((DWORD) op->mt_count < dp ()->MinimumBlockSize
- || (DWORD) op->mt_count > dp ()->MaximumBlockSize)))
- {
- lasterr = ERROR_INVALID_PARAMETER;
- break;
- }
- if (set_blocksize (mt, op->mt_count)
- && lasterr == ERROR_INVALID_FUNCTION)
- lasterr = ERROR_INVALID_BLOCK_LENGTH;
- break;
- case MTSEEK:
- if (get_feature (TAPE_DRIVE_LOGICAL_BLK))
- set_pos (mt, TAPE_LOGICAL_BLOCK, op->mt_count, false);
- else if (!get_pos (mt))
- set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS,
- op->mt_count - block, false);
- break;
- case MTTELL:
- if (!get_pos (mt))
- op->mt_count = block;
- break;
- case MTFSS:
- set_pos (mt, TAPE_SPACE_SETMARKS, op->mt_count, false);
- break;
- case MTBSS:
- set_pos (mt, TAPE_SPACE_SETMARKS, -op->mt_count, false);
- break;
- case MTWSM:
- write_marks (mt, TAPE_SETMARKS, op->mt_count);
- break;
- case MTLOCK:
- prepare (mt, TAPE_LOCK);
- break;
- case MTUNLOCK:
- prepare (mt, TAPE_UNLOCK);
- break;
- case MTLOAD:
- prepare (mt, TAPE_LOAD);
- break;
- case MTCOMPRESSION:
- set_compression (mt, op->mt_count);
- break;
- case MTSETPART:
- set_partition (mt, op->mt_count);
- break;
- case MTMKPART:
- create_partitions (mt, op->mt_count);
- break;
- case MTSETDRVBUFFER:
- set_options (mt, op->mt_count);
- break;
- case MTSETDENSITY:
- default:
- lasterr = ERROR_INVALID_PARAMETER;
- break;
- }
- }
- else if (cmd == MTIOCGET)
- get_status (mt, (struct mtget *) buf);
- else if (cmd == MTIOCPOS && !get_pos (mt))
- ((struct mtpos *) buf)->mt_blkno = block;
-
- return lasterr;
-}
-
-/**********************************************************************/
-/* mtinfo */
-
-void
-mtinfo::initialize ()
-{
- char name[CYG_MAX_PATH];
- HANDLE mtx;
-
- shared_name (name, "mtinfo_mutex", 0);
- if (!(mtx = CreateMutex (&sec_all_nih, FALSE, name)))
- api_fatal ("CreateMutex '%s', %E. Terminating.", name);
- WaitForSingleObject (mtx, INFINITE);
- if (!magic)
- {
- magic = MTINFO_MAGIC;
- version = MTINFO_VERSION;
- for (unsigned i = 0; i < MAX_DRIVE_NUM; ++i)
- drive (i)->initialize (i, true);
- ReleaseMutex (mtx);
- CloseHandle (mtx);
- }
- else
- {
- ReleaseMutex (mtx);
- CloseHandle (mtx);
- if (magic != MTINFO_MAGIC)
- api_fatal ("MT magic number screwed up: %lu, should be %lu",
- magic, MTINFO_MAGIC);
- if (version != MTINFO_VERSION)
- system_printf ("MT version number mismatch: %lu, should be %lu",
- version, MTINFO_VERSION);
- }
-}
-
-static mtinfo mt __attribute__((section (".cygwin_dll_common"), shared));
-
-void __stdcall
-mtinfo_init ()
-{
- mt.initialize ();
-}
-
-/**********************************************************************/
-/* fhandler_dev_tape */
-
-#define lock(err_ret_val) if (!_lock ()) return err_ret_val;
-
-inline bool
-fhandler_dev_tape::_lock ()
-{
- HANDLE obj[2] = { mt_mtx, signal_arrived };
- BOOL ret = WaitForMultipleObjects (2, obj, FALSE, INFINITE) == WAIT_OBJECT_0;
- if (!ret)
- {
- debug_printf ("signal_arrived"); \
- set_errno (EINTR);
- }
- return ret;
-}
-
-inline int
-fhandler_dev_tape::unlock (int ret)
-{
- ReleaseMutex (mt_mtx);
- return ret;
-}
-
-fhandler_dev_tape::fhandler_dev_tape ()
- : fhandler_dev_raw ()
-{
- debug_printf ("unit: %d", dev ().minor);
-}
-
-int
-fhandler_dev_tape::open (int flags, mode_t)
-{
- int ret;
-
- if (driveno () >= MAX_DRIVE_NUM)
- {
- set_errno (ENOENT);
- return 0;
- }
- if (!(mt_mtx = CreateMutex (&sec_all, TRUE, NULL)))
- {
- __seterrno ();
- return 0;
- }
-
- /* The O_SYNC flag is not supported by the tape driver. Use the
- MT_ST_BUFFER_WRITES and MT_ST_ASYNC_WRITES flags in the drive
- settings instead. In turn, the MT_ST_BUFFER_WRITES is translated
- into O_SYNC, which controls the FILE_WRITE_THROUGH flag in the
- NtCreateFile call in fhandler_base::open. */
- flags &= ~O_SYNC;
- if (!mt.drive (driveno ())->buffer_writes ())
- flags |= O_SYNC;
-
- ret = fhandler_dev_raw::open (flags);
- if (ret)
- {
- mt.drive (driveno ())->open (get_handle ());
-
- /* In append mode, seek to beginning of next filemark */
- if (flags & O_APPEND)
- mt.drive (driveno ())->set_pos (get_handle (),
- TAPE_SPACE_FILEMARKS, 1, true);
-
- if (!(flags & O_DIRECT))
- {
- devbufsiz = mt.drive (driveno ())->dp ()->MaximumBlockSize;
- devbuf = new char [devbufsiz];
- }
- devbufstart = devbufend = 0;
- }
- else
- ReleaseMutex (mt_mtx);
- return ret;
-}
-
-int
-fhandler_dev_tape::close ()
-{
- int ret = 0;
- int cret = 0;
-
- if (!hExeced)
- {
- lock (-1);
- ret = mt.drive (driveno ())->close (get_handle (), is_rewind_device ());
- if (ret)
- __seterrno_from_win_error (ret);
- cret = fhandler_dev_raw::close ();
- unlock (0);
- }
- if (mt_evt)
- CloseHandle (mt_evt);
- CloseHandle (mt_mtx);
- return ret ? -1 : cret;
-}
-
-void
-fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
-{
- char *buf = (char *) ptr;
- size_t len = ulen;
- size_t block_size;
- size_t bytes_to_read;
- size_t bytes_read = 0;
- int ret = 0;
-
- if (lastblk_to_read ())
- {
- lastblk_to_read (false);
- ulen = 0;
- return;
- }
- if (!_lock ())
- {
- ulen = (size_t) -1;
- return;
- }
- block_size = mt.drive (driveno ())->mp ()->BlockSize;
- if (devbuf)
- {
- if (devbufend > devbufstart)
- {
- 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 (buf, devbuf + devbufstart, bytes_to_read);
- len -= bytes_to_read;
- bytes_read += bytes_to_read;
- buf += bytes_to_read;
- devbufstart += bytes_to_read;
- if (devbufstart == devbufend)
- devbufstart = devbufend = 0;
- /* If a switch to variable block_size occured, just return the buffer
- remains until the buffer is empty, then proceed with usual variable
- block size handling (one block per read call). */
- if (!block_size)
- len = 0;
- }
- if (len > 0)
- {
- if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
- debug_printf ("Creating event failed, %E");
- size_t block_fit = !block_size ? len : rounddown(len, block_size);
- if (block_fit)
- {
- debug_printf ("read %d bytes from tape (rest %d)",
- block_fit, len - block_fit);
- ret = mt.drive (driveno ())->read (get_handle (), mt_evt, buf,
- block_fit);
- if (ret)
- __seterrno_from_win_error (ret);
- else if (block_fit)
- {
- len -= block_fit;
- bytes_read += block_fit;
- buf += block_fit;
- /* Only one block in each read call, please. */
- if (!block_size)
- len = 0;
- }
- else {
- len = 0;
- if (bytes_read)
- lastblk_to_read (true);
- }
- }
- if (!ret && len > 0)
- {
- debug_printf ("read %d bytes from tape (one block)", block_size);
- ret = mt.drive (driveno ())->read (get_handle (), mt_evt, devbuf,
- block_size);
- if (ret)
- __seterrno_from_win_error (ret);
- else if (block_size)
- {
- devbufstart = len;
- devbufend = block_size;
- bytes_read += len;
- memcpy (buf, devbuf, len);
- }
- else if (bytes_read)
- lastblk_to_read (true);
- }
- }
- }
- else
- {
- if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
- debug_printf ("Creating event failed, %E");
- bytes_read = ulen;
- ret = mt.drive (driveno ())->read (get_handle (), mt_evt, ptr,
- bytes_read);
- }
- ulen = (ret ? (size_t) -1 : bytes_read);
- unlock ();
-}
-
-int
-fhandler_dev_tape::raw_write (const void *ptr, size_t len)
-{
- lock (-1);
- if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
- debug_printf ("Creating event failed, %E");
- int ret = mt.drive (driveno ())->write (get_handle (), mt_evt, ptr, len);
- if (ret)
- __seterrno_from_win_error (ret);
- return unlock (ret ? -1 : (int) len);
-}
-
-_off64_t
-fhandler_dev_tape::lseek (_off64_t offset, int whence)
-{
- struct mtop op;
- struct mtpos pos;
- DWORD block_size;
- _off64_t ret = ILLEGAL_SEEK;
-
- lock (ILLEGAL_SEEK);
-
- debug_printf ("lseek (%s, %d, %d)", get_name (), offset, whence);
-
- block_size = mt.drive (driveno ())->mp ()->BlockSize;
- if (block_size == 0)
- {
- set_errno (EIO);
- goto out;
- }
-
- if (ioctl (MTIOCPOS, &pos))
- goto out;
-
- switch (whence)
- {
- case SEEK_END:
- op.mt_op = MTFSF;
- op.mt_count = 1;
- if (ioctl (MTIOCTOP, &op))
- goto out;
- break;
- case SEEK_SET:
- if (whence == SEEK_SET && offset < 0)
- {
- set_errno (EINVAL);
- goto out;
- }
- break;
- case SEEK_CUR:
- break;
- default:
- set_errno (EINVAL);
- goto out;
- }
-
- op.mt_op = MTFSR;
- op.mt_count = offset / block_size
- - (whence == SEEK_SET ? pos.mt_blkno : 0);
-
- if (op.mt_count < 0)
- {
- op.mt_op = MTBSR;
- op.mt_count = -op.mt_count;
- }
-
- if (ioctl (MTIOCTOP, &op) || ioctl (MTIOCPOS, &pos))
- goto out;
-
- ret = pos.mt_blkno * block_size;
-
-out:
- return unlock (ret);
-}
-
-int
-fhandler_dev_tape::fstat (struct __stat64 *buf)
-{
- int ret;
-
- if (driveno () >= MAX_DRIVE_NUM)
- {
- set_errno (ENOENT);
- return -1;
- }
- if (!(ret = fhandler_base::fstat (buf)))
- buf->st_blocks = 0;
- return ret;
-}
-
-int
-fhandler_dev_tape::dup (fhandler_base *child)
-{
- lock (-1);
- fhandler_dev_tape *fh = (fhandler_dev_tape *) child;
- if (!DuplicateHandle (hMainProc, mt_mtx, hMainProc, &fh->mt_mtx, 0, TRUE,
- DUPLICATE_SAME_ACCESS))
- {
- debug_printf ("dup(%s) failed, mutex handle %x, %E",
- get_name (), mt_mtx);
- __seterrno ();
- return unlock (-1);
- }
- fh->mt_evt = NULL;
- if (mt_evt &&
- !DuplicateHandle (hMainProc, mt_evt, hMainProc, &fh->mt_evt, 0, TRUE,
- DUPLICATE_SAME_ACCESS))
- {
- debug_printf ("dup(%s) failed, event handle %x, %E",
- get_name (), mt_evt);
- __seterrno ();
- return unlock (-1);
- }
- return unlock (fhandler_dev_raw::dup (child));
-}
-
-void
-fhandler_dev_tape::fixup_after_fork (HANDLE parent)
-{
- fhandler_dev_raw::fixup_after_fork (parent);
- fork_fixup (parent, mt_mtx, "mt_mtx");
- if (mt_evt)
- fork_fixup (parent, mt_evt, "mt_evt");
-}
-
-void
-fhandler_dev_tape::set_close_on_exec (bool val)
-{
- fhandler_dev_raw::set_close_on_exec (val);
- set_no_inheritance (mt_mtx, val);
- if (mt_evt)
- set_no_inheritance (mt_evt, val);
-}
-
-int
-fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
-{
- int ret = 0;
- lock (-1);
- if (cmd == MTIOCTOP || cmd == MTIOCGET || cmd == MTIOCPOS)
- {
- ret = mt.drive (driveno ())->ioctl (get_handle (), cmd, buf);
- if (ret)
- __seterrno_from_win_error (ret);
- return unlock (ret ? -1 : 0);
- }
- return unlock (fhandler_dev_raw::ioctl (cmd, buf));
-}