⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fhandler_tape.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* fhandler_tape.cc.  See fhandler.h for a description of the fhandler   classes.   Copyright 1999, 2000, 2001, 2002 Red Hat, Inc.This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license.  Please consult the file "CYGWIN_LICENSE" fordetails. */#include "winsup.h"#include <sys/termios.h>#include <errno.h>#include <unistd.h>#include <sys/mtio.h>#include "cygerrno.h"#include "perprocess.h"#include "security.h"#include "fhandler.h"#include "path.h"#include "dtable.h"#include "cygheap.h"/**********************************************************************//* fhandler_dev_tape */voidfhandler_dev_tape::clear (void){  lasterr = 0;  fhandler_dev_raw::clear ();}intfhandler_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;}intfhandler_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){  debug_printf ("unit: %d", unit);}intfhandler_dev_tape::open (path_conv *real_path, int flags, mode_t){  int ret;  devbufsiz = 1L;  ret = fhandler_dev_raw::open (real_path, flags);  if (ret)    {      struct mtget get;      struct mtop op;      struct mtpos pos;      if (!ioctl (MTIOCGET, &get))	/* Tape drive supports and is set to variable block size. */	if (get.mt_dsreg == 0)	  devbufsiz = get.mt_maxblksize;	else	  devbufsiz = get.mt_dsreg;	varblkop = get.mt_dsreg == 0;      if (devbufsiz > 1L)	devbuf = new char [devbufsiz];      /* The following rewind in position 0 solves a problem which appears       * 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. */      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;}intfhandler_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");	  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 ())    {      debug_printf ("rewinding");      op.mt_op = MTREW;      ioctl (MTIOCTOP, &op);    }  if (ret)    {      fhandler_dev_raw::close ();      return ret;    }  return fhandler_dev_raw::close ();}intfhandler_dev_tape::fstat (struct __stat64 *buf, path_conv *pc){  int ret;  if (!(ret = fhandler_base::fstat (buf, pc)))    {      struct mtget get;      if (!ioctl (MTIOCGET, &get))	buf->st_blocks = get.mt_capacity / buf->st_blksize;    }  return ret;}__off64_tfhandler_dev_tape::lseek (__off64_t offset, int whence){  struct mtop op;  struct mtpos pos;  debug_printf ("lseek (%s, %d, %d)", get_name (), offset, whence);  writebuf ();  eom_detected = eof_detected = 0;  lastblk_to_read = 0;  devbufstart = devbufend = 0;  if (ioctl (MTIOCPOS, &pos))    {      return ILLEGAL_SEEK;    }  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);}intfhandler_dev_tape::dup (fhandler_base *child){  fhandler_dev_tape *fhc = (fhandler_dev_tape *) child;  fhc->lasterr = lasterr;  return fhandler_dev_raw::dup (child);}intfhandler_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);	    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);	    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);	    else	      ret = tape_set_pos (TAPE_SPACE_FILEMARKS, 32767);	    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)		{		  ret = 0;		  break;		}	      if ((op->mt_count == 0		   && !tape_get_feature (TAPE_DRIVE_VARIABLE_BLOCK))		  || (op->mt_count > 0		      && (op->mt_count < min || op->mt_count > max)))		{		  ret = ERROR_INVALID_PARAMETER;		  break;		}	      if (devbuf && op->mt_count > 0		  && (size_t) op->mt_count < devbufend - devbufstart)		{		  ret = ERROR_MORE_DATA;		  break;		}	      if (! (ret = tape_set_blocksize (op->mt_count)))		{		  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]))		    {		      ret = ERROR_OUTOFMEMORY;		      break;		    }		  if (devbufsiz > 1L && size > 1L)		    {		      memcpy (buf, devbuf + devbufstart,			      devbufend - devbufstart);		      devbufend -= devbufstart;		    }		  else		    devbufend = 0;		  if (devbufsiz > 1L)		    delete [] devbuf;		  devbufstart = 0;		  devbuf = buf;		  devbufsiz = size;		  varblkop = op->mt_count == 0;		}	    }	    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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -