lmc@denelcor.UUCP (09/03/84)
This program will copy a tape exactly, reading the tape in from a drive to a disk, and then back out to the same drive. See the manual page for details. ---------------------------------------------------------------------- : This is a shar archieve. Extract with sh, not csh. : The rest of this file will extract: : tcp.l tcp.c echo extracting - tcp.l sed 's/^X//' > tcp.l << 'FUNKYSTUFF' X.TH TCP 1 "21 Aug 1984" X.UC 4 X.SH NAME Xtcp \- tape copy with one tape drive X.SH SYNOPSIS X.B tcp X[ X.B \-i X] [ X.B \-o X] [ X.B \-1..15 X] [ X.B \-c X] [ X.B -nxx X] X.br X.SH DESCRIPTION XNeed to copy a tape, but only have a Xsingle tape drive? X.I Tcp Xwill do it. XIn the X.I \-i Xmode X.I tcp Xreads in all the files of a tape, Xcopying them to disk along with enough Xinformation to reconstruct the record Xblocking. The tape is assumed to be Xterminated with the usual double Xtape marks. In output mode ( X.I \-o X) X.I tcp Xreads the files and rebuilds the tape Xexactly as it was. The X.I \-n Xoption allows several tapes to be saved Xin a single directory, if that is Xrequired, by giving each a separate Xnumber (0-99), and then specifying Xthat number on both input and output. XThe X.I \-c Xoption specifies that a conversational Xmode is to be entered in the event Xof tape read errors, in which the user Xcan specify the action to be taken Xwhen such an error occurs: ignore the Xerror (copy whatever was received; this Xmay not give desired results on some Xsystems), retry the I/O, or abort the Xentire copy operation. (Note that the X.I \-c Xoption is only available on Berkeley Xsystems with mag tape ioctls.) XThe numeric options allow the tape drive Xdefault selection to be changed. The Xinput operation uses /dev/rmtX, where XX can be specified from 0 to 15, while Xon output /dev/nrmtX is used (which Xcan normally only accept 0-3 and 8-11 Xas valid drive numbers). In both cases Xthe default drive is drive 0. X.SH DIAGNOSTICS XThe usual usage diagnostic and Xothers for cannot open and tape Xread errors. X.PP XExit status is 0 normally, 1 for Xusage error and 2 for tape read error. X.SH DEFINES X.I MAXBUF Xdefines the maximum size of a tape Xblock. Default at 16000 works with both X4.2bsd and S3 on an 11/44. X.I MTIO, Xif defined, compiles in the conversational Xoption, which requires the mag tape Xioctls from the Berkeley distributions. X.SH AUTHOR XLyle McElhaney FUNKYSTUFF echo extracting - tcp.c sed 's/^X//' > tcp.c << 'FUNKYSTUFF' X/* X * tcp - this routine runs in input (-i) and output (-o) modes. On X * input, it reads a tape's contents (out to the double tape-marks) X * and writes that data to files in a the current directory, along X * with a file of data which will allow reconstruction of the tape X * in the output mode. X * X * Copyright (C) 1983, 1984 Lyle McElhaney X * Permission to copy for non-commercial use granted under condition X * that this notice remains intact in the copy. X * X * Address: 2489 W. Ridge Rd., Littleton, CO 80120 X * ....denelcor!lmc X * X */ X#include <stdio.h> X#include <sys/types.h> X#include <sys/ioctl.h> X#ifdef MTIO X#include <sys/mtio.h> X#endif X#ifndef YES X#define NO 0 X#define YES 1 X#endif X#define NYU 2 X Xextern char *index(); Xextern int errno; Xchar nrtape[]="/dev/nrmt0\0\0"; Xchar tape[]="/dev/rmt0\0\0"; Xchar ffh[]="tcp,f"; /* headers for temp filenames */ Xchar nfh[]="tcp,n"; Xchar format[]="%s%02d%05d"; /* format of filenames. args: [fcn]fh, tapen, nfile */ X#define FMTSIZ 13 /* limit on size of filenames created + 1 */ Xchar ffile[FMTSIZ], cfile[FMTSIZ]; X#define MAXBUF 16000 /* works on 11/44 under SYS3 */ Xchar buff[MAXBUF]; Xchar buf[10]; Xint nfile; Xint tapen=0; Xint inmode=NYU; /* input mode - not yet set. User must choose. */ XFILE *tapedev, *filedev, *ctldev; Xlong recno, nrec, fsize, filen; X#ifdef MTIO Xint convmode=NO; /* conversational mode default to no */ Xstruct mtop mtop; X#endif X Xmain (argc, argv) X int argc; X char **argv; X{ X char *p; X int n; X X argv++; X if (argc > 1) { X p = *argv; X if (*p == '-') { X p++; X while (*p != '\0') { X switch (*p++) { X#ifdef MTIO X case 'c': X convmode = YES; X break; X#endif X case 'i': X if (inmode != NYU) goto Usage; X inmode = YES; X break; X case 'o': X if (inmode != NYU) goto Usage; X inmode = NO; X break; X case 'n': X tapen = atoi (p); X break; X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X case '0': X tape[8] = nrtape[9] = *(p-1); X break; X case '1': X tape[8] = nrtape[9] = '1'; X if (*p >= '0' && *p <= '5') X tape[9] = nrtape[10] = *p++; X break; X default: XUsage: X fprintf (stderr, "Usage: tcp [-i] [-o] [-nxx] [-1...15]\n"); X exit (2); X } X } X argc--; X argv++; X } X } else goto Usage; X if (inmode == NYU) goto Usage; X X if (inmode) { X/* X * input mode - read tape into files. X */ X sprintf (cfile, format, nfh, tapen, 0); X if ((ctldev = fopen (cfile, "w+")) == NULL) { X fprintf (stderr, "tcp: cannot open %s\n", cfile); X exit (2); X } X if ((tapedev = fopen (tape, "r")) == NULL) { X fprintf (stderr, "tcp: cannot open %s\n", tape); X exit (2); X } X filen = 0; X for (;;) { X recno = nrec = fsize = 0; Xreread: while ((n = read (fileno (tapedev), buff, sizeof buff)) > 0) { X if (recno == 0) { X sprintf (ffile, format, ffh, tapen, filen); X if ((filedev = fopen (ffile, "w+")) == NULL) { X fprintf (stderr, "tcp: cannot open %s\n", ffile); X exit (2); X } X } X if (write (fileno (filedev), buff, n) <= 0) { X fprintf (stderr, "tcp: file write error #%d in %s\n", X errno, ffile); X exit (2); X } X if (fsize != 0 && fsize != n) { X fprintf (ctldev, "%d,%d\n", recno - nrec + 1, n); X nrec = recno; X } X fsize = n; X recno ++; X } X if (n == 0) X if (recno == 0) X break; X else { X fprintf (ctldev, "%d,%d\n0,0\n", recno - nrec, fsize); X filen ++; X fclose (filedev); X } X else { X printf ("Tape read error %d in record %ld\n", n, recno); X#ifdef MTIO X for (;;) { X if (convmode) { X printf ("Abort, Retry, or Ignore? "); X if (gets (buf) != NULL) { X if (*buf == 'R' || *buf == 'r') { X mtop.mt_count = 1; X mtop.mt_op = MTBSR; X if (ioctl (fileno (tapedev), MTIOCTOP, &mtop) < 0) { X printf ("error %d in ioctl; ignoring prev error.\n", errno); X recno ++; X } X goto reread; X } else if (*buf == 'I' || *buf == 'i') { X recno ++; X goto reread; X } else if (*buf == 'A' || *buf == 'a') X exit (1); X } X } else X exit (1); X } X#else X exit (1); X#endif MTIO X } X } X fclose (tapedev); X fprintf (ctldev, "0,1\n"); X fclose (ctldev); X } else { X/* X * output mode - copy files back out to tape. X */ X sprintf (cfile, format, nfh, tapen, 0); X if ((ctldev = fopen (cfile, "r")) == NULL) { X fprintf (stderr, "tcp: cannot open %s\n", cfile); X exit (2); X } X recno = 0; X for (;;) { X if (fgets (buf, sizeof(buf), ctldev) == NULL) { X fprintf (stderr, "tcp: file %s malformed.\n", cfile); X exit (2); X } X nrec = atoi (buf); X n = atoi (index (buf, ',') + 1); X if (nrec != 0) { X if (recno == 0) { X if ((tapedev = fopen (nrtape, "a")) == NULL) { X fprintf (stderr, "tcp: cannot open %s\n", nrtape); X exit (2); X } X sprintf (ffile, format, ffh, tapen, filen); X if ((filedev = fopen (ffile, "r")) == NULL) { X fprintf (stderr, "tcp: cannot open %s\n", ffile); X exit (2); X } X } X for (; nrec > 0; nrec--) { X if (read (fileno (filedev), buff, n) <= 0) { X fprintf (stderr, "tcp: file read error #%d in %s\n", X errno, ffile); X exit (2); X } X if (write (fileno (tapedev), buff, n) <= 0) { X fprintf (stderr, "tcp: tape write error #%d in %s\n", X errno, nrtape); X exit (2); X } X recno ++; X } X } else if (n == 0) { X fclose (filedev); X fclose (tapedev); X recno = 0; X } else X break; X } X fclose (ctldev); X } X exit (0); X} FUNKYSTUFF -- Lyle McElhaney (hao,brl-bmd,nbires,csu-cs,scgvaxd)!denelcor!lmc