Subject: Re: mt/st problems ? (fwd)
To: Peter L. Peres <plp@actcom.co.il>
From: Ed Gould <ed@left.wing.org>
List: port-i386
Date: 01/29/2005 12:42:19
This is a multipart MIME message.

--==_Exmh_-8846911240
Content-Type: text/plain; charset=us-ascii

> The tar files are complete. Even tar finds them, but only the *third* 
> time (try 3 times, without moving the tape, find nothing twice, 
> successfully !!! (there goes your backup) then the third time find it, 
> but still leave the tape on the last block). Using dd and other tools 
> seems to work correctly.

Attached is a program I haven't used for years, since I don't have a 
tape drive any more, but it served me well for many years before that.  
It scans a magtape, and reports the record and file-mark structure it 
finds.  Maybe it can help you diagnose this problem.

Last time I built it (in 2003, YMMV), it compiled with:

	cc -O2 -DMTIO -o mtscan mtscan.c -ltermcap

If your tape has data stored after a double-EOF (one suggestion was 
that yours does), run with the -F flag.  I never wrote a man page for 
this; if there's any real interest, I can do so.

Good luck.

	--Ed


--==_Exmh_-8846911240
Content-Type: text/plain ; name="mtscan.c"; charset=us-ascii
Content-Description: mtscan.c
Content-Disposition: attachment; filename="mtscan.c"

/*
 * mtscan - scan a mag tape for record structure
 */

#include <stdlib.h>

#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/file.h>

#if	MACH
#include <mach.h>
#endif

#ifdef	MTIO
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
#endif

#if	i386 && !defined(BIGBUFFERS)
#define	BUFLEN	(32L * 1024L)
#else
#define	BUFLEN	(64L * 1024L)
#endif

#define	MAXBUF	(256L * 1024L)

#define	BIG	5000

const	char	*tape	= "/dev/rst0";
char		*buf;
int		files	= 1;
long		buflen	= BUFLEN;
int		big	= BIG;
int		quiet	= 0;
char		termcap[1024];

char		*backspace(int);
void		done(int);

extern	int	tgetent(char *, char *);
extern	int	tgetflag(char *);

#define	qprintf	if(!quiet) printf

int
main(
	int argc,
	char * const *argv
) {
	int i;
	int n;
	int mt;
	int eflag	= 0;
	int fflag	= 0;
	int hardcopy	= 1;
	int previous;
	int repeat	= 0;
	int first;
	int preveof	= 0;
	int nfiles	= 0;
	long nrec	= 1000000L;
	long count	= 0;
	char *term;
	extern int optind;
	extern char *optarg;
#ifdef	MTIO
	int rewind	= 0;
	int rewindafter	= 0;
	int unload	= 0;
	int unload_err	= 0;
	struct mtop mtop;
#endif

	if(isatty(fileno(stdout)) && (term = getenv("TERM")) != NULL &&
	   tgetent(termcap, term) > 0)
		hardcopy = tgetflag("hc");
	while((i = getopt(argc, argv, "B:b:eFf:hn:qrsUu")) != -1) {
		switch(i) {

		case 'B':
			big = atoi(optarg);
			break;

		case 'b':
			buflen = atol(optarg);
			if(buflen > MAXBUF) {
				fprintf(stderr,
					"Buffer (%ld) too big, set to %ld\n",
					buflen, MAXBUF);
				buflen = MAXBUF;
			}
			break;

		case 'e':
			eflag++;
			break;

		case 'F':
			fflag++;
			break;

		case 'f':
			nfiles = atoi(optarg);
			break;

		case 'h':
			hardcopy++;
			break;

		case 'n':
			nrec = atol(optarg);
			break;

		case 'q':
			quiet++;
			break;

		case 's':
			hardcopy = 0;
			break;

#ifdef	MTIO
		case 'R':
			rewindafter++;
			break;

		case 'r':
			rewind++;
			break;

		case 'U':
			unload_err++;
			break;

		case 'u':
			unload++;
			break;
#endif

		case '?':
		default:
			fprintf(stderr, "unknown flag '%c'\n", i);
			exit(1);
		}
	}
#if	MACH
	if(vm_allocate(task_self(), (vm_address_t *)&buf, buflen, 1) !=
								KERN_SUCCESS) {
		perror("vm_allocate");
		exit(1);
	}
#else
	buf = malloc(buflen);
	if(buf == NULL) {
		perror("no memory");
		exit(1);
	}
#endif
	if(optind < argc)
		tape = argv[optind++];
	mt = open(tape, O_RDONLY, 0);
	if(mt < 0) {
		perror(tape);
		exit(1);
	}
#ifdef	MTIO
	if(rewind) {
		bzero(&mtop, sizeof(mtop));
		mtop.mt_op = MTREW;
		if(ioctl(mt, MTIOCTOP, &mtop) < 0) {
			perror("MTIOCTOP rewind");
			exit(1);
		}
	}
	if(optind < argc) {
		bzero(&mtop, sizeof(mtop));
		mtop.mt_op = MTFSF;
		mtop.mt_count = atoi(argv[optind++]);
		files += mtop.mt_count;
		if(ioctl(mt, MTIOCTOP, &mtop) < 0) {
			perror("MTIOCTOP skip files");
			exit(1);
		}
	}
#endif
	if(optind < argc) {
		fprintf(stderr, "arg count\n");
		exit(1);
	}
	signal(SIGINT, done);
	i = 0;
	previous = -1;
	first = 1;
	while(count < nrec) {
		n = read(mt, buf, buflen);
		i++;
		count++;
		if(n != previous) {
			if(repeat > 0) {
				qprintf("      \r   same through record %d\n",
									i-1);
				fflush(stdout);
			}
			repeat = 0;
			first = 1;
			previous = -1;
		}
		if(n < 0) {
			if(repeat > 0)
				qprintf("\n");
			qprintf("error record %d", i);
			if(eflag) {
				qprintf(" ignored\n");
				fflush(stdout);
				repeat = 0;
				first = 1;
				previous = -1;
				continue;
			} else {
				qprintf("\n");
				fflush(stdout);
				break;
			}
		}
		if(n == 0) {
			if(repeat > 0)
				qprintf("\n");
			qprintf("End of file %d\n", files);
			fflush(stdout);
			i = 0;
			previous = -1;
			repeat = 0;
			if(preveof && !fflag)
				break;
			if(nfiles && (files >= nfiles))
				break;
			files++;
		} else {
			if(n == previous) {
				repeat++;
				if((n > big || i%10 == 0) && !hardcopy) {
					if(first) {
					    qprintf("   same through record ");
					    first = 0;
					}
					qprintf("%d%s", i, backspace(i));
				}
			} else
				qprintf("record %d is length %d\n", i, n);
			fflush(stdout);
			previous = n;
		}
		preveof = n==0;
	}
	qprintf("\n\n%d file%s read.\n", files, files==1?"":"s");
#ifdef	MTIO
	if(rewindafter) {
		bzero(&mtop, sizeof(mtop));
		mtop.mt_op = MTREW;
		if(ioctl(mt, MTIOCTOP, &mtop) < 0) {
			perror("MTIOCTOP rewind after");
			exit(1);
		}
	}
	if(unload) {
		bzero(&mtop, sizeof(mtop));
		mtop.mt_op = MTOFFL;
		if(ioctl(mt, MTIOCTOP, &mtop) < 0) {
			perror("MTIOCTOP offline");
			exit(1);
		}
	}
#endif
	if(nfiles && (files != nfiles)) {
		if(unload_err) {
			bzero(&mtop, sizeof(mtop));
			mtop.mt_op = MTOFFL;
			if(ioctl(mt, MTIOCTOP, &mtop) < 0) {
				perror("MTIOCTOP offline after error");
				exit(1);
			}
		}
		return(1);
	}
	return(0);
}

char *
backspace(int n) {
	static char bs[32];
	int log10;

	for(log10 = 0; n; n /= 10)
		log10++;
	bs[log10] = '\0';
	while(log10-- > 0)
		bs[log10] = '\010';
	return(bs);
}

void
done(int s) {
	if(s)
		qprintf("\nInterrupted.\n");
	qprintf("\n\n%d file%s read.\n", files, files==1?"":"s");
	fflush(stdout);
	exit(s);
}

--==_Exmh_-8846911240--