summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_tape.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler_tape.cc')
-rw-r--r--winsup/cygwin/fhandler_tape.cc141
1 files changed, 80 insertions, 61 deletions
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
index d3fd3eee2..0b4e53773 100644
--- a/winsup/cygwin/fhandler_tape.cc
+++ b/winsup/cygwin/fhandler_tape.cc
@@ -1216,11 +1216,16 @@ fhandler_dev_tape::open (int flags, mode_t)
__seterrno ();
return 0;
}
- /* The O_TEXT flag is used to indicate write-through (non buffered writes)
- to the underlying fhandler_dev_raw::open call. */
- flags &= ~O_TEXT;
+
+ /* 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_TEXT;
+ flags |= O_SYNC;
+
ret = fhandler_dev_raw::open (flags);
if (ret)
{
@@ -1231,8 +1236,11 @@ fhandler_dev_tape::open (int flags, mode_t)
mt->drive (driveno ())->set_pos (get_handle (),
TAPE_SPACE_FILEMARKS, 1, true);
- devbufsiz = mt->drive (driveno ())->dp ()->MaximumBlockSize;
- devbuf = new char [devbufsiz];
+ if (!(flags & O_DIRECT))
+ {
+ devbufsiz = mt->drive (driveno ())->dp ()->MaximumBlockSize;
+ devbuf = new char [devbufsiz];
+ }
devbufstart = devbufend = 0;
}
else
@@ -1283,70 +1291,81 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
return;
}
block_size = mt->drive (driveno ())->mp ()->BlockSize;
- if (devbufend > devbufstart)
+ if (devbuf)
{
- 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)
+ if (devbufend > devbufstart)
{
- 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 {
+ 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 (bytes_read)
- lastblk_to_read (true);
- }
}
- if (!ret && len > 0)
+ if (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)
+ 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)
{
- devbufstart = len;
- devbufend = block_size;
- bytes_read += len;
- memcpy (buf, devbuf, len);
+ 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 (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 ();
}