[comp.sys.sgi] ecopy.c, Re: bug in reading from disk partitions

mike@BRL.MIL (Mike Muuss) (12/04/90)

You might find this program helpful in your quest to recover from your failing
disk drive.
	Best,
	 -Mike
----
/*
 *  			E C O P Y . C
 *  
 *  Quick program to do large DMAs until an error is found, and then
 *  do single-sector DMAs to isolate the bad block(s) in question.
 *  Input is on stdin.
 *  Data recovered is output on stdout.
 *  This program has the property that the output will be exactly the
 *  same length as the input, with a best-effort attempt at the contents
 *  of the file in cases of error.
 */
#include <stdio.h>
char *malloc();

#ifdef sel
#define SECTLEN	1024
#else
#define SECTLEN	512
#endif

main(argc, argv)
char **argv;
{
	register int i,j;
	int nsectors;
	int size;
	long pos;
	char *buf;

	if( argc < 2 || argc > 3 )  {
		fprintf(stderr,"Usage:  ecopy sectors/DMA [sectors_offset]\n");
		exit(1);
	}
	nsectors = atoi( argv[1] );
	if( nsectors < 1 || nsectors > 1024 )  {
		fprintf(stderr,"DMA size %d.*%d. unreasonable\n", nsectors, SECTLEN );
		exit(2);
	}
	size = nsectors * SECTLEN;
	if( (buf = malloc( size )) == ((char *)0) )  {
		fprintf(stderr,"Unable to malloc specified buffer\n");
		exit(3);
	}
	if( argc == 3 )
		pos = atoi( argv[2] ) * SECTLEN;
	else
		pos = 0L;
	fprintf(stderr,"Starting with %d*%d byte DMAs at sector %d\n",
		nsectors, SECTLEN, pos/SECTLEN );

	for( ; ; pos += size )  {
		if( lseek( 0, pos, 0 ) == -1L )
			perror("lseek");
		if( (i = read( 0, buf, size )) == size )  {
			write( 1, buf, size);
			continue;
		}
		fprintf(stderr,"error with starting sector %d, count was %d, s/b %d\n",
			pos/SECTLEN, i, size );
		if( i == 0 )  exit(0);
		for( j = 0; j < nsectors; j++ )  {
			if( lseek( 0, pos+(j*SECTLEN), 0 ) == -1L )  {
				perror("lseek");
				exit(1);
			}
			if( (i=read(0,buf,SECTLEN)) == SECTLEN )  {
				write(1, buf, SECTLEN);
				continue;
			}
			fprintf(stderr,"BAD sector %d, count was %d, s/b %d\n",
				(pos/SECTLEN)+j, i, SECTLEN );
			if( i == 0 )  exit(0);
			if( i < 0 )  i = SECTLEN;
			fprintf(stderr,"wrote %d bytes\n", i);
			write( 1, buf, i );
		}
	}
}