Exemple #1
0
void
verify_volume (void)
{
  int status;
#ifdef MTIOCTOP
  struct mtop t;
  int er;
#endif

  if (!diff_buf)
    diff_init ();
#ifdef MTIOCTOP
  t.mt_op = MTBSF;
  t.mt_count = 1;
  if (er = rmtioctl (archive, MTIOCTOP, (char *) &t), er < 0)
    {
      if (errno != EIO
	  || (er = rmtioctl (archive, MTIOCTOP, (char *) &t), er < 0))
	{
#endif
	  if (rmtlseek (archive, 0L, 0) != 0)
	    {

	      /* Lseek failed.  Try a different method.  */

	      WARN ((0, errno, _("Could not rewind archive file for verify")));
	      return;
	    }
#ifdef MTIOCTOP
	}
    }
#endif
  ar_reading = 1;
  now_verifying = 1;
  fl_read ();
  while (1)
    {
      status = read_header ();
      if (status == 0)
	{
	  unsigned n;

	  n = 0;
	  do
	    {
	      n++;
	      status = read_header ();
	    }
	  while (status == 0);
	  ERROR ((0, 0,
		  _("VERIFY FAILURE: %d invalid header(s) detected"), n));
	}
      if (status == 2 || status == EOF)
	break;
      diff_archive ();
    }
  ar_reading = 0;
  now_verifying = 0;

}
Exemple #2
0
int
rmtopen(char *tape, int mode)
{
	struct mtget mt;
	char buf[256];
	int fd;

	(void) snprintf(buf, sizeof (buf), "O%s\n%d\n", tape, mode);
	rmtstate = TS_OPEN;
	fd = rmtcall(tape, buf);
	if (fd != -1) {
		/* see if the rmt server supports the extended protocol */
		rmtversion = rmtioctl(-1, 0);

		/*
		 * Some rmt daemons apparently close the connection
		 * when they get a bogus ioctl.  See 1210852 (ignore
		 * the evaluation).  Make sure we can still talk to
		 * the device, re-opening it if necessary.
		 */
		if (rmtversion < 1) {
			if (rmtstatus(&mt) < 0) {
				rmtclose();
				rmtgetconn();
				rmtversion = 0;
			}
		}
	}
	return (fd);
}
Exemple #3
0
int
_rmtmtioctop(int fd, struct mtop *com)
{
#ifdef RMT
	if (host)
		return rmtioctl(com->mt_op, com->mt_count);
#endif
	return ioctl(fd, MTIOCTOP, com);
}
/* Move archive descriptor by COUNT records worth.  If COUNT is
   positive we move forward, else we move negative.  If it's a tape,
   MTIOCTOP had better work.  If it's something else, we try to seek
   on it.  If we can't seek, we lose!  */
static void
move_archive (off_t count)
{
  if (count == 0)
    return;

#ifdef MTIOCTOP
  {
    struct mtop operation;

    if (count < 0
	? (operation.mt_op = MTBSR,
	   operation.mt_count = -count,
	   operation.mt_count == -count)
	: (operation.mt_op = MTFSR,
	   operation.mt_count = count,
	   operation.mt_count == count))
      {
	if (0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
	  return;

	if (errno == EIO
	    && 0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation))
	  return;
      }
  }
#endif /* MTIOCTOP */

  {
    off_t position0 = rmtlseek (archive, (off_t) 0, SEEK_CUR);
    off_t increment = record_size * (off_t) count;
    off_t position = position0 + increment;

    if (increment / count != record_size
	|| (position < position0) != (increment < 0)
	|| (position = position < 0 ? 0 : position,
	    rmtlseek (archive, position, SEEK_SET) != position))
      seek_error_details (archive_name_array[0], position);

    return;
  }
}
Exemple #5
0
static void
move_archive (int count)
{
#ifdef MTIOCTOP
  {
    struct mtop operation;
    int status;

    if (count > 0)
      {
	operation.mt_op = MTFSR;
	operation.mt_count = count;
      }
    else
      {
	operation.mt_op = MTBSR;
	operation.mt_count = -count;
      }

    if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
	status >= 0)
      return;

    if (errno == EIO)
      if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
	  status >= 0)
      return;
  }
#endif /* MTIOCTOP */

  {
    off_t position = rmtlseek (archive, 0L, 1);

    position += record_size * count;

    if (rmtlseek (archive, position, 0) != position)
      FATAL_ERROR ((0, 0, _("Could not re-position archive file")));

    return;
  }
}
Exemple #6
0
void
perform_operation (char *dev, int desc, short op, int count)
{
  struct mtop control;

  control.mt_op = op;
  control.mt_count = count;
  /* Debian hack: The rmtioctl function returns -1 in case of an
     error, not 0.  This bug has been reported to
     "*****@*****.**".  (96/7/10) -BEM */
  if (rmtioctl (desc, MTIOCTOP, (char*)&control) == -1)
    error (2, errno, _("%s: rmtioctl failed"), dev);
}
Exemple #7
0
/*
 * handle multiple dumps per tape by skipping forward to the
 * appropriate one.
 */
static void
setdumpnum(void)
{
	struct mtop tcom;

	if (dumpnum == 1 || volno != 1)
		return;
	if (pipein)
		errx(1, "Cannot have multiple dumps on pipe input");
	tcom.mt_op = MTFSF;
	tcom.mt_count = dumpnum - 1;
#ifdef RRESTORE
	if (host)
		rmtioctl(MTFSF, dumpnum - 1);
	else
#endif
		if (ioctl(mt, MTIOCTOP, (char *)&tcom) < 0)
			warn("ioctl MTFSF");
}
Exemple #8
0
/*
 * handle multiple dumps per tape by skipping forward to the
 * appropriate one.
 */
static void
setdumpnum(void)
{
	struct mtop tcom;

	if (dumpnum == 1 || volno != 1)
		return;
	if (pipein) {
		fprintf(stderr, "Cannot have multiple dumps on pipe input\n");
		done(1);
	}
	tcom.mt_op = MTFSF;
	tcom.mt_count = dumpnum - 1;
#ifdef RRESTORE
	if (host)
		rmtioctl(MTFSF, dumpnum - 1);
	else
#endif
		if (!pipecmdin && ioctl(mt, MTIOCTOP, (char *)&tcom) < 0)
			fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno));
}
Exemple #9
0
void
print_status (char *dev, int desc)
{
  struct mtget status;

  if (rmtioctl (desc, MTIOCGET, (char*)&status) == -1)
    error (2, errno, _("%s: rmtioctl failed"), dev);

  printf ("drive type = %d\n", (int) status.mt_type);
#if defined(hpux) || defined(__hpux)
  printf ("drive status (high) = %d\n", (int) status.mt_dsreg1);
  printf ("drive status (low) = %d\n", (int) status.mt_dsreg2);
#else
  printf ("drive status = %d\n", (int) status.mt_dsreg);
#endif
  printf ("sense key error = %d\n", (int) status.mt_erreg);
  printf ("residue count = %d\n", (int) status.mt_resid);
#if !defined(ultrix) && !defined(__ultrix__) && !defined(hpux) && !defined(__hpux) && !defined(__osf__)
  printf ("file number = %d\n", (int) status.mt_fileno);
  printf ("block number = %d\n", (int) status.mt_blkno);
#endif
}
Exemple #10
0
int
ar_rdsync(void)
{
	long fsbz;
	off_t cpos;
	off_t mpos;
#ifdef HAVE_SYS_MTIO_H
	struct mtop mb;
#endif

	/*
	 * Fail resync attempts at user request (done) or if this is going to be
	 * an update/append to a existing archive. if last i/o hit media end,
	 * we need to go to the next volume not try a resync
	 */
	if ((done > 0) || (lstrval == 0))
		return -1;

	if ((act == APPND) || (act == ARCHIVE)) {
		tty_warn(1, "Cannot allow updates to an archive with flaws.");
		return -1;
	}
	if (io_ok)
		did_io = 1;

	switch(artyp) {
#ifdef SUPPORT_RMT
	case ISRMT:
#endif /* SUPPORT_RMT */
	case ISTAPE:
#ifdef HAVE_SYS_MTIO_H
		/*
		 * if the last i/o was a successful data transfer, we assume
		 * the fault is just a bad record on the tape that we are now
		 * past. If we did not get any data since the last resync try
		 * to move the tape forward one PHYSICAL record past any
		 * damaged tape section. Some tape drives are stubborn and need
		 * to be pushed.
		 */
		if (io_ok) {
			io_ok = 0;
			lstrval = 1;
			break;
		}
		mb.mt_op = MTFSR;
		mb.mt_count = 1;
#ifdef SUPPORT_RMT
		if (artyp == ISRMT) {
			if (rmtioctl(arfd, MTIOCTOP, &mb) < 0)
				break;
		} else {
#endif /* SUPPORT_RMT */
			if (ioctl(arfd, MTIOCTOP, &mb) < 0)
				break;
#ifdef SUPPORT_RMT
		}
#endif /* SUPPORT_RMT */
		lstrval = 1;
#else
		tty_warn(1, "System does not have tape support");
#endif
		break;
	case ISREG:
	case ISCHR:
	case ISBLK:
		/*
		 * try to step over the bad part of the device.
		 */
		io_ok = 0;
		if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG))
			fsbz = BLKMULT;
		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
			break;
		mpos = fsbz - (cpos % (off_t)fsbz);
		if (lseek(arfd, mpos, SEEK_CUR) < 0)
			break;
		lstrval = 1;
		break;
	case ISPIPE:
	default:
		/*
		 * cannot recover on these archive device types
		 */
		io_ok = 0;
		break;
	}
	if (lstrval <= 0) {
		tty_warn(1, "Unable to recover from an archive read failure.");
		return -1;
	}
	tty_warn(0, "Attempting to recover from an archive read failure.");
	return 0;
}
Exemple #11
0
static int
get_phys(void)
{
	int padsz = 0;
	int res;
	int phyblk;
	struct mtop mb;
	char scbuf[MAXBLK];

	/*
	 * move to the file mark, and then back up one record and read it.
	 * this should tell us the physical record size the tape is using.
	 */
	if (lstrval == 1) {
		/*
		 * we know we are at file mark when we get back a 0 from
		 * read()
		 */
#ifdef SUPPORT_RMT
		while ((res = rmtread_with_restart(arfd,
						   scbuf, sizeof(scbuf))) > 0)
#else
		while ((res = read_with_restart(arfd,
						scbuf, sizeof(scbuf))) > 0)
#endif /* SUPPORT_RMT */
			padsz += res;
		if (res < 0) {
			syswarn(1, errno, "Unable to locate tape filemark.");
			return -1;
		}
	}

	/*
	 * move backwards over the file mark so we are at the end of the
	 * last record.
	 */
	mb.mt_op = MTBSF;
	mb.mt_count = 1;
	if (
#ifdef SUPPORT_RMT
	    rmtioctl(arfd, MTIOCTOP, &mb)
#else
	    ioctl(arfd, MTIOCTOP, &mb)
#endif /* SUPPORT_RMT */
	    < 0) {
		syswarn(1, errno, "Unable to backspace over tape filemark.");
		return -1;
	}

	/*
	 * move backwards so we are in front of the last record and read it to
	 * get physical tape blocksize.
	 */
	mb.mt_op = MTBSR;
	mb.mt_count = 1;
	if (
#ifdef SUPPORT_RMT
	    rmtioctl(arfd, MTIOCTOP, &mb)
#else
	    ioctl(arfd, MTIOCTOP, &mb)
#endif /* SUPPORT_RMT */
	    < 0) {
		syswarn(1, errno, "Unable to backspace over last tape block.");
		return -1;
	}
	if ((phyblk =
#ifdef SUPPORT_RMT
	     rmtread_with_restart(arfd, scbuf, sizeof(scbuf))
#else
	     read_with_restart(arfd, scbuf, sizeof(scbuf))
#endif /* SUPPORT_RMT */
	    ) <= 0) {
		syswarn(1, errno, "Cannot determine archive tape blocksize.");
		return -1;
	}

	/*
	 * read forward to the file mark, then back up in front of the filemark
	 * (this is a bit paranoid, but should be safe to do).
	 */
	while ((res =
#ifdef SUPPORT_RMT
		rmtread_with_restart(arfd, scbuf, sizeof(scbuf))
#else
		read_with_restart(arfd, scbuf, sizeof(scbuf))
#endif /* SUPPORT_RMT */
	       ) > 0)
		;
	if (res < 0) {
		syswarn(1, errno, "Unable to locate tape filemark.");
		return -1;
	}
	mb.mt_op = MTBSF;
	mb.mt_count = 1;
	if (
#ifdef SUPPORT_RMT
	    rmtioctl(arfd, MTIOCTOP, &mb)
#else
	    ioctl(arfd, MTIOCTOP, &mb)
#endif /* SUPPORT_RMT */
	    < 0) {
		syswarn(1, errno, "Unable to backspace over tape filemark.");
		return -1;
	}

	/*
	 * set lstrval so we know that the filemark has not been seen
	 */
	lstrval = 1;

	/*
	 * return if there was no padding
	 */
	if (padsz == 0)
		return phyblk;

	/*
	 * make sure we can move backwards over the padding. (this should
	 * never fail).
	 */
	if (padsz % phyblk) {
		tty_warn(1, "Tape drive unable to backspace requested amount");
		return -1;
	}

	/*
	 * move backwards over the padding so the head is where it was when
	 * we were first called (if required).
	 */
	mb.mt_op = MTBSR;
	mb.mt_count = padsz/phyblk;
	if (
#ifdef SUPPORT_RMT
	    rmtioctl(arfd, MTIOCTOP, &mb)
#else
	    ioctl(arfd, MTIOCTOP, &mb)
#endif /* SUPPORT_RMT */
	    < 0) {
		syswarn(1, errno,
		    "Unable to backspace tape over %ld pad blocks",
		    (long)mb.mt_count);
		return -1;
	}
	return phyblk;
}
Exemple #12
0
int
ar_rev(off_t sksz)
{
	off_t cpos;
#ifdef HAVE_SYS_MTIO_H
	int phyblk;
	struct mtop mb;
#endif

	/*
	 * make sure we do not have try to reverse on a flawed archive
	 */
	if (lstrval < 0)
		return lstrval;

	switch(artyp) {
	case ISPIPE:
		if (sksz <= 0)
			break;
		/*
		 * cannot go backwards on these critters
		 */
		tty_warn(1, "Reverse positioning on pipes is not supported.");
		lstrval = -1;
		return -1;
	case ISREG:
	case ISBLK:
	case ISCHR:
	default:
		if (sksz <= 0)
			break;

		/*
		 * For things other than files, backwards movement has a very
		 * high probability of failure as we really do not know the
		 * true attributes of the device we are talking to (the device
		 * may not even have the ability to lseek() in any direction).
		 * First we figure out where we are in the archive.
		 */
		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) {
			syswarn(1, errno,
			   "Unable to obtain current archive byte offset");
			lstrval = -1;
			return -1;
		}

		/*
		 * we may try to go backwards past the start when the archive
		 * is only a single record. If this happens and we are on a
		 * multi-volume archive, we need to go to the end of the
		 * previous volume and continue our movement backwards from
		 * there.
		 */
		if ((cpos -= sksz) < (off_t)0L) {
			if (arvol > 1) {
				/*
				 * this should never happen
				 */
				tty_warn(1,
				    "Reverse position on previous volume.");
				lstrval = -1;
				return -1;
			}
			cpos = (off_t)0L;
		}
		if (lseek(arfd, cpos, SEEK_SET) < 0) {
			syswarn(1, errno, "Unable to seek archive backwards");
			lstrval = -1;
			return -1;
		}
		break;
	case ISTAPE:
#ifdef SUPPORT_RMT
	case ISRMT:
#endif /* SUPPORT_RMT */
#ifdef HAVE_SYS_MTIO_H
		/*
		 * Calculate and move the proper number of PHYSICAL tape
		 * blocks. If the sksz is not an even multiple of the physical
		 * tape size, we cannot do the move (this should never happen).
		 * (We also cannot handle trailers spread over two vols).
		 * get_phys() also makes sure we are in front of the filemark.
		 */
		if ((phyblk = get_phys()) <= 0) {
			lstrval = -1;
			return -1;
		}

		/*
		 * make sure future tape reads only go by physical tape block
		 * size (set rdblksz to the real size).
		 */
		rdblksz = phyblk;

		/*
		 * if no movement is required, just return (we must be after
		 * get_phys() so the physical blocksize is properly set)
		 */
		if (sksz <= 0)
			break;

		/*
		 * ok we have to move. Make sure the tape drive can do it.
		 */
		if (sksz % phyblk) {
			tty_warn(1,
			    "Tape drive unable to backspace requested amount");
			lstrval = -1;
			return -1;
		}

		/*
		 * move backwards the requested number of bytes
		 */
		mb.mt_op = MTBSR;
		mb.mt_count = sksz/phyblk;
		if (
#ifdef SUPPORT_RMT
		    rmtioctl(arfd, MTIOCTOP, &mb)
#else
		    ioctl(arfd, MTIOCTOP, &mb)
#endif /* SUPPORT_RMT */
		    < 0) {
			syswarn(1, errno, "Unable to backspace tape %ld blocks.",
			    (long) mb.mt_count);
			lstrval = -1;
			return -1;
		}
#else
		tty_warn(1, "System does not have tape support");
#endif
		break;
	}
	lstrval = 1;
	return 0;
}
Exemple #13
0
void
verify_volume (void)
{
  if (!diff_buffer)
    diff_init ();

  /* Verifying an archive is meant to check if the physical media got it
     correctly, so try to defeat clever in-memory buffering pertaining to
     this particular media.  On Linux, for example, the floppy drive would
     not even be accessed for the whole verification.

     The code was using fsync only when the ioctl is unavailable, but
     Marty Leisner says that the ioctl does not work when not preceded by
     fsync.  So, until we know better, or maybe to please Marty, let's do it
     the unbelievable way :-).  */

#if HAVE_FSYNC
  fsync (archive);
#endif
#ifdef FDFLUSH
  ioctl (archive, FDFLUSH);
#endif

#ifdef MTIOCTOP
  {
    struct mtop operation;
    int status;

    operation.mt_op = MTBSF;
    operation.mt_count = 1;
    if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation), status < 0)
      {
	if (errno != EIO
	    || (status = rmtioctl (archive, MTIOCTOP, (char *) &operation),
		status < 0))
	  {
#endif
	    if (rmtlseek (archive, 0L, 0) != 0)
	      {
		/* Lseek failed.  Try a different method.  */

		WARN ((0, errno,
		       _("Could not rewind archive file for verify")));
		return;
	      }
#ifdef MTIOCTOP
	  }
      }
  }
#endif

  access_mode = ACCESS_READ;
  now_verifying = 1;

  flush_read ();
  while (1)
    {
      enum read_header status = read_header ();

      if (status == HEADER_FAILURE)
	{
	  int counter = 0;

	  while (status == HEADER_FAILURE);
	    {
	      counter++;
	      status = read_header ();
	    }
	  ERROR ((0, 0,
		  _("VERIFY FAILURE: %d invalid header(s) detected"), counter));
	}
      if (status == HEADER_ZERO_BLOCK || status == HEADER_END_OF_FILE)
	break;

      diff_archive ();
    }

  access_mode = ACCESS_WRITE;
  now_verifying = 0;
}