newlib/winsup/cygwin/fhandler_tape.cc

843 lines
19 KiB
C++
Raw Normal View History

2000-02-17 20:38:33 +01:00
/* fhandler_tape.cc. See fhandler.h for a description of the fhandler
classes.
Copyright 1999, 2000, 2001, 2002 Red Hat, Inc.
2000-02-17 20:38:33 +01:00
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"
2000-02-17 20:38:33 +01:00
#include <sys/termios.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mtio.h>
#include "cygerrno.h"
2001-03-05 07:28:25 +01:00
#include "perprocess.h"
#include "security.h"
#include "fhandler.h"
Add "path.h" include throughout, where needed. Use new path_conv methods and operators to simplify testing for directory and attributes, throughout. * path.h (path_conv::exists): New method. (path_conv::has_attribute): Ditto. (path_conv::isdir): Ditto. (path_conv::DWORD &): New operator. (path_conv::int &): Ditto. * dir.cc (rmdir): Eliminate a goto. * dtable.cc (dtable::build_fhandler): Accept opt and suffix info for path_conv.check. Return fh == NULL on path_conv error. Pass unit to set_name as appropriate. (dtable::reset_unix_path_name): New method. * dtable.h (dtable): Declare new method. Reflect arg changes to build_fhandler. * fhandler.cc (fhandler_disk_dummy_name): Eliminate. (fhandler_base::set_name): Expect paths to be NULL. Build unix_path_name from win32_path_name when it is a device. (fhandler_base::reset_unix_path_name): New method. (fhandler_base::raw_read): Report EISDIR when ERROR_INVALID_FUNCTION or ERROR_INVALID_PARAMETER and reading a directory. (fhandler_disk_file::fstat): Don't call stat_dev since we should now never be calling fhandler_disk_file methods with devices. (fhandler_base::fhandler_base): Clear {unix,win32}_path_name. (fhandler_base::~fhandler_base): Always free {unix,win32}_path_name. (fhandler_disk_file::fhandler_disk_file): Remove set_no_free_names kludge. (fhandler_disk_file::open): Ditto. * fhandler.h (fhandler_base::no_free_names): Eliminate. (fhandler_base::set_no_free_names): Ditto. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Don't set unix_path_name here. * path.cc (fchdir): Lock fd table throughout. Use new dtable::reset_unix_path_name method to reset path. * syscalls.cc (stat_worker): Reorganize to always call fstat method. Pass path_conv method to fhandler_*::open. (chroot): Elminate a goto.
2001-10-01 06:10:07 +02:00
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
2000-02-17 20:38:33 +01:00
/**********************************************************************/
/* fhandler_dev_tape */
void
fhandler_dev_tape::clear (void)
{
lasterr = 0;
fhandler_dev_raw::clear ();
}
int
fhandler_dev_tape::is_eom (int win_error)
{
int ret = ((win_error == ERROR_END_OF_MEDIA)
|| (win_error == ERROR_EOM_OVERFLOW)
|| (win_error == ERROR_NO_DATA_DETECTED));
if (ret)
debug_printf ("end of medium");
return ret;
}
int
fhandler_dev_tape::is_eof (int win_error)
{
int ret = ((win_error == ERROR_FILEMARK_DETECTED)
|| (win_error == ERROR_SETMARK_DETECTED));
if (ret)
debug_printf ("end of file");
return ret;
}
fhandler_dev_tape::fhandler_dev_tape (int unit)
: fhandler_dev_raw (FH_TAPE, unit)
2000-02-17 20:38:33 +01:00
{
debug_printf ("unit: %d", unit);
2000-02-17 20:38:33 +01:00
}
int
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
fhandler_dev_tape::open (path_conv *real_path, int flags, mode_t)
2000-02-17 20:38:33 +01:00
{
int ret;
devbufsiz = 1L;
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
ret = fhandler_dev_raw::open (real_path, flags);
2000-02-17 20:38:33 +01:00
if (ret)
{
struct mtget get;
struct mtop op;
struct mtpos pos;
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
if (!ioctl (MTIOCGET, &get))
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
/* Tape drive supports and is set to variable block size. */
if (get.mt_dsreg == 0)
devbufsiz = get.mt_maxblksize;
else
2000-02-17 20:38:33 +01:00
devbufsiz = get.mt_dsreg;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
varblkop = get.mt_dsreg == 0;
2000-02-17 20:38:33 +01:00
if (devbufsiz > 1L)
devbuf = new char [devbufsiz];
2000-02-17 20:38:33 +01:00
/* The following rewind in position 0 solves a problem which appears
2000-02-17 20:38:33 +01:00
* in case of multi volume archives: The last ReadFile on first medium
* returns ERROR_NO_DATA_DETECTED. After media change, all subsequent
* ReadFile calls return ERROR_NO_DATA_DETECTED, too.
* The call to tape_set_pos seems to reset some internal flags. */
2000-02-17 20:38:33 +01:00
if ((! ioctl (MTIOCPOS, &pos)) && (! pos.mt_blkno))
{
op.mt_op = MTREW;
ioctl (MTIOCTOP, &op);
}
if (flags & O_APPEND)
{
/* In append mode, seek to beginning of next filemark */
op.mt_op = MTFSFM;
op.mt_count = 1;
ioctl (MTIOCTOP, &op);
}
}
return ret;
}
int
fhandler_dev_tape::close (void)
{
struct mtop op;
int ret = 0;
if (is_writing)
{
ret = writebuf ();
if ((has_written) && (! eom_detected))
{
/* if last operation was writing, write a filemark */
debug_printf ("writing filemark\n");
op.mt_op = MTWEOF;
op.mt_count = 1;
ioctl (MTIOCTOP, &op);
}
}
// To protected reads on signaling (e.g. Ctrl-C)
eof_detected = 1;
if (is_rewind_device ())
2000-02-17 20:38:33 +01:00
{
debug_printf ("rewinding\n");
op.mt_op = MTREW;
ioctl (MTIOCTOP, &op);
}
if (ret)
{
fhandler_dev_raw::close ();
return ret;
}
return fhandler_dev_raw::close ();
}
int
* cygwin.din (fstat64): New symbol. (ftruncate64): Ditto. (lseek64): Ditto. (lstat64): Ditto. (mmap64): Ditto. (seekdir64): Ditto. (stat64): Ditto. (telldir64): Ditto. (truncate64): Ditto. * dir.cc (telldir64): New function. (telldir): Call telldir64(). (seekdir64): New function. (seekdir): Call seekdir64(). * fhandler.h: Redefine all methods using __off32_t to use __off64_t. * fhandler.cc: Use __off64_t and struct __stat64 throughout. * fhandler_clipboard.cc: Ditto. * fhandler_disk_file.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_floppy.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_socket.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_zero.cc: Ditto. * pipe.cc: Ditto. * glob.c: Ditto, call lstat64 and stat64 in Cygwin. * mmap.cc: Use __off64_t throughout. (mmap64): New function. * sec_acl.cc (acl_worker): Use struct __stat64, call stat64 and lstat64. * syscalls.cc (lseek64): New function. (stat64_to_stat32): Ditto. (fstat64): Ditto. (stat64): Ditto. (lstat64): Ditto. (ftruncate64): Ditto. (truncate64): Ditto. (_fstat): Call fstat64. (_stat): Call stat64. (cygwin_lstat): Rename to avoid declaration problem. Call lstat64. (stat_worker): Use struct __stat64. (access): Ditto. (ftruncate): Call ftruncate64. (truncate): Call truncate64. * wincap.cc: Set flag has_64bit_file_access appropriately. * wincap.h: Add flag has_64bit_file_access. * winsup.h (ILLEGAL_SEEK): Define as __off64_t. (stat_dev): Declare using struct __stat64. (stat_worker): Ditto. * include/cygwin/stat.h (struct __stat32): Define if compiling Cygwin. (struct __stat64): Ditto. (struct stat): Revert definition with explicitly sized datatypes. Eliminate sized field names. * include/cygwin/types.h (blksize_t): New type. (__blkcnt32_t): Ditto. (__blkcnt64_t): Ditto. (blkcnt_t): Ditto.
2002-02-25 18:47:51 +01:00
fhandler_dev_tape::fstat (struct __stat64 *buf, path_conv *pc)
2000-02-17 20:38:33 +01:00
{
int ret;
if (!(ret = fhandler_base::fstat (buf, pc)))
2000-02-17 20:38:33 +01:00
{
struct mtget get;
if (! ioctl (MTIOCGET, &get))
{
buf->st_blocks = get.mt_capacity / buf->st_blksize;
}
}
return ret;
}
* cygwin.din (fstat64): New symbol. (ftruncate64): Ditto. (lseek64): Ditto. (lstat64): Ditto. (mmap64): Ditto. (seekdir64): Ditto. (stat64): Ditto. (telldir64): Ditto. (truncate64): Ditto. * dir.cc (telldir64): New function. (telldir): Call telldir64(). (seekdir64): New function. (seekdir): Call seekdir64(). * fhandler.h: Redefine all methods using __off32_t to use __off64_t. * fhandler.cc: Use __off64_t and struct __stat64 throughout. * fhandler_clipboard.cc: Ditto. * fhandler_disk_file.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_floppy.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_socket.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_zero.cc: Ditto. * pipe.cc: Ditto. * glob.c: Ditto, call lstat64 and stat64 in Cygwin. * mmap.cc: Use __off64_t throughout. (mmap64): New function. * sec_acl.cc (acl_worker): Use struct __stat64, call stat64 and lstat64. * syscalls.cc (lseek64): New function. (stat64_to_stat32): Ditto. (fstat64): Ditto. (stat64): Ditto. (lstat64): Ditto. (ftruncate64): Ditto. (truncate64): Ditto. (_fstat): Call fstat64. (_stat): Call stat64. (cygwin_lstat): Rename to avoid declaration problem. Call lstat64. (stat_worker): Use struct __stat64. (access): Ditto. (ftruncate): Call ftruncate64. (truncate): Call truncate64. * wincap.cc: Set flag has_64bit_file_access appropriately. * wincap.h: Add flag has_64bit_file_access. * winsup.h (ILLEGAL_SEEK): Define as __off64_t. (stat_dev): Declare using struct __stat64. (stat_worker): Ditto. * include/cygwin/stat.h (struct __stat32): Define if compiling Cygwin. (struct __stat64): Ditto. (struct stat): Revert definition with explicitly sized datatypes. Eliminate sized field names. * include/cygwin/types.h (blksize_t): New type. (__blkcnt32_t): Ditto. (__blkcnt64_t): Ditto. (blkcnt_t): Ditto.
2002-02-25 18:47:51 +01:00
__off64_t
fhandler_dev_tape::lseek (__off64_t offset, int whence)
2000-02-17 20:38:33 +01:00
{
struct mtop op;
struct mtpos pos;
debug_printf ("lseek (%s, %d, %d)\n", get_name (), offset, whence);
writebuf ();
eom_detected = eof_detected = 0;
lastblk_to_read = 0;
devbufstart = devbufend = 0;
if (ioctl (MTIOCPOS, &pos))
{
return ILLEGAL_SEEK;
2000-02-17 20:38:33 +01:00
}
switch (whence)
{
case SEEK_END:
op.mt_op = MTFSF;
op.mt_count = 1;
if (ioctl (MTIOCTOP, &op))
return -1;
break;
case SEEK_SET:
if (whence == SEEK_SET && offset < 0)
{
set_errno (EINVAL);
return -1;
}
break;
case SEEK_CUR:
break;
default:
set_errno (EINVAL);
return -1;
}
op.mt_op = MTFSR;
op.mt_count = offset / devbufsiz
- (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))
return -1;
return (pos.mt_blkno * devbufsiz);
}
int
fhandler_dev_tape::dup (fhandler_base *child)
{
fhandler_dev_tape *fhc = (fhandler_dev_tape *) child;
fhc->lasterr = lasterr;
return fhandler_dev_raw::dup (child);
}
int
fhandler_dev_tape::ioctl (unsigned int cmd, void *buf)
{
int ret = NO_ERROR;
unsigned long block;
if (cmd == MTIOCTOP)
{
struct mtop *op = (struct mtop *) buf;
if (! op)
ret = ERROR_INVALID_PARAMETER;
else
switch (op->mt_op)
{
case MTRESET:
break;
case MTFSF:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, op->mt_count);
break;
case MTBSF:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, -op->mt_count);
break;
case MTFSR:
ret = tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, op->mt_count);
break;
case MTBSR:
ret = tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS, -op->mt_count);
break;
case MTWEOF:
if (tape_get_feature (TAPE_DRIVE_WRITE_FILEMARKS))
ret = tape_write_marks (TAPE_FILEMARKS, op->mt_count);
else if (tape_get_feature (TAPE_DRIVE_WRITE_LONG_FMKS))
ret = tape_write_marks (TAPE_LONG_FILEMARKS, op->mt_count);
else
ret = tape_write_marks (TAPE_SHORT_FILEMARKS, op->mt_count);
2000-02-17 20:38:33 +01:00
break;
case MTREW:
ret = tape_set_pos (TAPE_REWIND, 0);
break;
case MTOFFL:
ret = tape_prepare (TAPE_UNLOAD);
break;
case MTNOP:
break;
case MTRETEN:
if (! tape_get_feature (TAPE_DRIVE_END_OF_DATA))
ret = ERROR_INVALID_PARAMETER;
else if (! (ret = tape_set_pos (TAPE_REWIND, 0, FALSE)))
ret = tape_prepare (TAPE_TENSION);
2000-02-17 20:38:33 +01:00
break;
case MTBSFM:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, -op->mt_count, TRUE);
break;
case MTFSFM:
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, op->mt_count, TRUE);
break;
case MTEOM:
if (tape_get_feature (TAPE_DRIVE_END_OF_DATA))
ret = tape_set_pos (TAPE_SPACE_END_OF_DATA, 0);
2000-02-17 20:38:33 +01:00
else
ret = tape_set_pos (TAPE_SPACE_FILEMARKS, 32767);
2000-02-17 20:38:33 +01:00
break;
case MTERASE:
ret = tape_erase (TAPE_ERASE_SHORT);
break;
case MTRAS1:
case MTRAS2:
case MTRAS3:
ret = ERROR_INVALID_PARAMETER;
break;
case MTSETBLK:
{
long min, max;
if (! tape_get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
{
ret = ERROR_INVALID_PARAMETER;
break;
}
ret = tape_get_blocksize (&min, NULL, &max, NULL);
if (ret)
break;
if (devbuf && (size_t) op->mt_count == devbufsiz && !varblkop)
2000-02-17 20:38:33 +01:00
{
ret = 0;
2000-02-17 20:38:33 +01:00
break;
}
if ((op->mt_count == 0
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
&& !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
|| (op->mt_count > 0
&& (op->mt_count < min || op->mt_count > max)))
2000-02-17 20:38:33 +01:00
{
ret = ERROR_INVALID_PARAMETER;
2000-02-17 20:38:33 +01:00
break;
}
if (devbuf && op->mt_count > 0
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
&& (size_t) op->mt_count < devbufend - devbufstart)
2000-02-17 20:38:33 +01:00
{
ret = ERROR_MORE_DATA;
2000-02-17 20:38:33 +01:00
break;
}
if (! (ret = tape_set_blocksize (op->mt_count)))
{
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
size_t size = 0;
if (op->mt_count == 0)
{
struct mtget get;
if ((ret = tape_status (&get)) != NO_ERROR)
break;
size = get.mt_maxblksize;
ret = NO_ERROR;
}
char *buf = NULL;
if (size > 1L && !(buf = new char [size]))
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
{
ret = ERROR_OUTOFMEMORY;
break;
}
if (devbufsiz > 1L && size > 1L)
2000-02-17 20:38:33 +01:00
{
memcpy(buf, devbuf + devbufstart,
devbufend - devbufstart);
2000-02-17 20:38:33 +01:00
devbufend -= devbufstart;
}
else
devbufend = 0;
if (devbufsiz > 1L)
delete [] devbuf;
devbufstart = 0;
devbuf = buf;
devbufsiz = size;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
varblkop = op->mt_count == 0;
2000-02-17 20:38:33 +01:00
}
}
break;
case MTSETDENSITY:
ret = ERROR_INVALID_PARAMETER;
break;
case MTSEEK:
if (tape_get_feature (TAPE_DRIVE_ABSOLUTE_BLK))
{
ret = tape_set_pos (TAPE_ABSOLUTE_BLOCK, op->mt_count);
break;
}
if (! (ret = tape_get_pos (&block)))
{
ret = tape_set_pos (TAPE_SPACE_RELATIVE_BLOCKS,
op->mt_count - block);
}
break;
case MTTELL:
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;
case MTBSS:
ret = tape_set_pos (TAPE_SPACE_SETMARKS, -op->mt_count);
break;
case MTWSM:
ret = tape_write_marks (TAPE_SETMARKS, op->mt_count);
break;
case MTLOCK:
ret = tape_prepare (TAPE_LOCK);
break;
case MTUNLOCK:
ret = tape_prepare (TAPE_UNLOCK);
break;
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:
default:
ret = ERROR_INVALID_PARAMETER;
break;
}
}
else if (cmd == MTIOCGET)
ret = tape_status ((struct mtget *) buf);
else if (cmd == MTIOCPOS)
{
ret = ERROR_INVALID_PARAMETER;
if (buf && (ret = tape_get_pos (&block)))
((struct mtpos *) buf)->mt_blkno = block;
}
else
return fhandler_dev_raw::ioctl (cmd, buf);
if (ret != NO_ERROR)
{
SetLastError (ret);
__seterrno ();
return -1;
}
return 0;
}
/* ------------------------------------------------------------------ */
/* Private functions used by `ioctl' */
/* ------------------------------------------------------------------ */
static int
tape_error (DWORD lasterr, const char *txt)
{
if (lasterr)
debug_printf ("%s: error: %d\n", txt, lasterr);
return lasterr;
}
int
fhandler_dev_tape::tape_write_marks (int marktype, DWORD len)
{
syscall_printf ("write_tapemark\n");
while (((lasterr = WriteTapemark (get_handle (),
marktype,
len,
FALSE)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
return tape_error (lasterr, "tape_write_marks");
}
int
fhandler_dev_tape::tape_get_pos (unsigned long *ret)
{
DWORD part, low, high;
while (((lasterr = GetTapePosition (get_handle (),
TAPE_ABSOLUTE_POSITION,
&part,
&low,
&high)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (! tape_error (lasterr, "tape_get_pos") && ret)
*ret = low;
return lasterr;
}
static int _tape_set_pos (HANDLE hTape, int mode, long count)
{
int err;
while (((err = SetTapePosition (hTape,
mode,
1,
count,
count < 0 ? -1 : 0,
FALSE)) == ERROR_MEDIA_CHANGED)
|| (err == ERROR_BUS_RESET))
;
return err;
}
int
fhandler_dev_tape::tape_set_pos (int mode, long count, BOOLEAN sfm_func)
{
unsigned long pos, tgtpos;
switch (mode)
{
case TAPE_SPACE_RELATIVE_BLOCKS:
lasterr = tape_get_pos (&pos);
if (lasterr)
return lasterr;
tgtpos = pos + count;
while (((lasterr = _tape_set_pos (get_handle (),
mode,
count)) == ERROR_FILEMARK_DETECTED)
|| (lasterr == ERROR_SETMARK_DETECTED))
{
lasterr = tape_get_pos (&pos);
if (lasterr)
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 (get_handle (),
TAPE_SPACE_RELATIVE_BLOCKS,
-1))
|| (sfm_func))
++count;
_tape_set_pos (get_handle (), TAPE_SPACE_RELATIVE_BLOCKS, 1);
}
while (! (lasterr = _tape_set_pos (get_handle (), mode, -1))
&& count++ < 0)
;
if (lasterr == ERROR_BEGINNING_OF_MEDIA)
{
if (! count)
lasterr = NO_ERROR;
}
else if (! sfm_func)
lasterr = _tape_set_pos (get_handle (), mode, 1);
}
else
{
if (sfm_func)
{
if (_tape_set_pos (get_handle (),
TAPE_SPACE_RELATIVE_BLOCKS,
1) == ERROR_FILEMARK_DETECTED)
++count;
_tape_set_pos (get_handle (), TAPE_SPACE_RELATIVE_BLOCKS, -1);
}
if (! (lasterr = _tape_set_pos (get_handle (), mode, count))
&& sfm_func)
lasterr = _tape_set_pos (get_handle (), mode, -1);
}
break;
case TAPE_SPACE_SETMARKS:
case TAPE_ABSOLUTE_BLOCK:
case TAPE_SPACE_END_OF_DATA:
case TAPE_REWIND:
lasterr = _tape_set_pos (get_handle (), mode, count);
break;
}
return tape_error (lasterr, "tape_set_pos");
}
int
fhandler_dev_tape::tape_erase (int mode)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
switch (mode)
{
case TAPE_ERASE_SHORT:
if (! lasterr && ! (dp.FeaturesLow & TAPE_DRIVE_ERASE_SHORT))
mode = TAPE_ERASE_LONG;
break;
case TAPE_ERASE_LONG:
if (! lasterr && ! (dp.FeaturesLow & TAPE_DRIVE_ERASE_LONG))
mode = TAPE_ERASE_SHORT;
break;
}
return tape_error (EraseTape (get_handle (), mode, FALSE), "tape_erase");
}
int
fhandler_dev_tape::tape_prepare (int action)
{
while (((lasterr = PrepareTape (get_handle (),
action,
FALSE)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
return tape_error (lasterr, "tape_prepare");
}
BOOLEAN
fhandler_dev_tape::tape_get_feature (DWORD parm)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return FALSE;
return ((parm & TAPE_DRIVE_HIGH_FEATURES)
? ((dp.FeaturesHigh & parm) != 0)
: ((dp.FeaturesLow & parm) != 0));
}
int
fhandler_dev_tape::tape_get_blocksize (long *min, long *def, long *max, long *cur)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
TAPE_GET_MEDIA_PARAMETERS mp;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return tape_error (lasterr, "tape_get_blocksize");
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_MEDIA_INFORMATION,
(varlen = sizeof dp, &varlen),
2000-02-17 20:38:33 +01:00
&mp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return tape_error (lasterr, "tape_get_blocksize");
if (min)
*min = (long) dp.MinimumBlockSize;
if (def)
*def = (long) dp.DefaultBlockSize;
if (max)
*max = (long) dp.MaximumBlockSize;
if (cur)
*cur = (long) mp.BlockSize;
return tape_error (lasterr, "tape_get_blocksize");
}
int
fhandler_dev_tape::tape_set_blocksize (long count)
{
long min, max;
TAPE_SET_MEDIA_PARAMETERS mp;
lasterr = tape_get_blocksize (&min, NULL, &max, NULL);
if (lasterr)
return lasterr;
if (count != 0 && (count < min || count > max))
2000-02-17 20:38:33 +01:00
return tape_error (ERROR_INVALID_PARAMETER, "tape_set_blocksize");
mp.BlockSize = count;
return tape_error (SetTapeParameters (get_handle (),
SET_TAPE_MEDIA_INFORMATION,
&mp),
"tape_set_blocksize");
}
static long long
get_ll (PLARGE_INTEGER i)
{
long long l = 0;
l = i->HighPart;
l <<= 32;
l |= i->LowPart;
return l;
}
int
fhandler_dev_tape::tape_status (struct mtget *get)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dp;
TAPE_GET_MEDIA_PARAMETERS mp;
int notape = 0;
if (! get)
return ERROR_INVALID_PARAMETER;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dp, &varlen),
&dp)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
/* Setting varlen to sizeof DP is by intention, actually! Never set
it to sizeof MP which seems to be more correct but results in a
ERROR_MORE_DATA error at least on W2K. */
2000-02-17 20:38:33 +01:00
if ((lasterr) || (lasterr = GetTapeParameters (get_handle (),
GET_TAPE_MEDIA_INFORMATION,
(varlen = sizeof dp, &varlen),
2000-02-17 20:38:33 +01:00
&mp)))
notape = 1;
memset (get, 0, sizeof *get);
get->mt_type = MT_ISUNKNOWN;
if (! notape && (dp.FeaturesLow & TAPE_DRIVE_TAPE_REMAINING))
{
get->mt_remaining = get_ll (&mp.Remaining);
get->mt_resid = get->mt_remaining >> 10;
}
if ((dp.FeaturesHigh & TAPE_DRIVE_SET_BLOCK_SIZE) && ! notape)
get->mt_dsreg = mp.BlockSize;
else
get->mt_dsreg = dp.DefaultBlockSize;
if (notape)
get->mt_gstat |= GMT_DR_OPEN (-1);
if (! notape)
{
if (dp.FeaturesLow & TAPE_DRIVE_GET_ABSOLUTE_BLK)
tape_get_pos ((unsigned long *) &get->mt_blkno);
if (! get->mt_blkno)
get->mt_gstat |= GMT_BOT (-1);
get->mt_gstat |= GMT_ONLINE (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_WRITE_PROTECT) && mp.WriteProtected)
get->mt_gstat |= GMT_WR_PROT (-1);
if (dp.FeaturesLow & TAPE_DRIVE_TAPE_CAPACITY)
get->mt_capacity = get_ll (&mp.Capacity);
}
if ((dp.FeaturesLow & TAPE_DRIVE_COMPRESSION) && dp.Compression)
get->mt_gstat |= GMT_HW_COMP (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_ECC) && dp.ECC)
get->mt_gstat |= GMT_HW_ECC (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_PADDING) && dp.DataPadding)
get->mt_gstat |= GMT_PADDING (-1);
if ((dp.FeaturesLow & TAPE_DRIVE_REPORT_SMKS) && dp.ReportSetmarks)
get->mt_gstat |= GMT_IM_REP_EN (-1);
get->mt_erreg = lasterr;
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;
2000-02-17 20:38:33 +01:00
return 0;
}
int
fhandler_dev_tape::tape_compression (long count)
{
DWORD varlen;
TAPE_GET_DRIVE_PARAMETERS dpg;
TAPE_SET_DRIVE_PARAMETERS dps;
while (((lasterr = GetTapeParameters (get_handle (),
GET_TAPE_DRIVE_INFORMATION,
(varlen = sizeof dpg, &varlen),
&dpg)) == ERROR_MEDIA_CHANGED)
|| (lasterr == ERROR_BUS_RESET))
;
if (lasterr)
return tape_error (lasterr, "tape_compression");
if (! (dpg.FeaturesLow & TAPE_DRIVE_COMPRESSION))
return ERROR_INVALID_PARAMETER;
if (count)
{
dps.ECC = dpg.ECC;
dps.Compression = count ? TRUE : FALSE;
dps.DataPadding = dpg.DataPadding;
dps.ReportSetmarks = dpg.ReportSetmarks;
dps.EOTWarningZoneSize = dpg.EOTWarningZoneSize;
lasterr = SetTapeParameters (get_handle (),
SET_TAPE_DRIVE_INFORMATION,
&dps);
if (lasterr)
return tape_error (lasterr, "tape_compression");
dpg.Compression = dps.Compression;
}
return 0;
}