#include #include #include #define BUFLEN 16384 char buf[BUFLEN+2]; char rcl[4]; char rc2[4]; FILE *tp; unsigned long packit( char x[4] ) { return (x[0] & 0x00ff) | ((x[1] << 8) & 0xff00) | ((x[2] << 16) & 0xff0000) | ((x[3] << 24) & 0xff000000); } int read_record( char buf[], unsigned int buf_size, FILE *fd ) { int n; char tbuf1[4]; char tbuf2[4]; int reclen1; int reclen2; n = fread( tbuf1, sizeof(char), 4, fd ); if( n == 0 ) { return -1; } if( n < 4 ) { fprintf( stderr, "Bad read length %d\n", n ); exit(1); } reclen1 = packit( tbuf1 ); if( reclen1 == 0 ) { return 0; } if( reclen1 > buf_size) { fprintf( stderr, "ERROR: tape record too big: %d max is %s\n", reclen1, buf_size ); exit(1); } n = fread( buf, sizeof(char), reclen1, fd ); if( n != reclen1 ) { fprintf( stderr, "ERROR: short read\n" ); exit(1); } /* ** check end count */ n = fread( tbuf2, sizeof(char), 4, fd ); if( n != 4 ) { fprintf( stderr, "ERROR: end length missing\n" ); exit(1); } reclen2 = packit( tbuf2 ); if( reclen1 != reclen2 ) { fprintf( stderr, "ERROR: record lengths do not match [%d,%d]\n", reclen1, reclen2 ); exit(1); } return reclen1; } void dump_buf( char buf[], int buf_len ) { int i,j; for( i = 0; i < buf_len; i += 16 ) { printf( " " ); for( j = 0; j < 16; j++ ) { if( (i+j) >= buf_len ) printf( "-- " ); else printf( "%02x ", (buf[i+j] & 0xff) ); } printf( " [" ); for( j = 0; j < 16; j++ ) { if( (i + j) >= buf_len ) printf( " " ); else if( (buf[i+j] < 32) || ((buf[i+j] & 0xff) >= 127) ) printf( " " ); else printf( "%c", buf[i+j] ); } printf( "]\n" ); } } int skip_file( FILE *fd ) { int reclen; while(1) { reclen = read_record( buf, BUFLEN, fd ); if( reclen <= 0 ) return reclen; } } int read_logical_record( char buf[], int buf_size, FILE *fd ) { int n; char xbuf[BUFLEN+2]; int cksum, ckval; int rl; int i; int cw; n = read_record( xbuf, BUFLEN, fd ); if( n <= 0 ) return n; rl = ((xbuf[0] << 8) & 0xff00) | (xbuf[1] & 0x00ff); if( rl > (n-2) ) { fprintf( stderr, "FATAL: logical/physical mismatch: phy %d log %d\n", n, rl ); skip_file (tp); return; // // exit(1); } cksum = 0; for( i = 0; i < rl-2; i++ ) { buf[i] = xbuf[i+2]; if( (i & 1) == 0 ) { /* upper byte */ cw = (buf[i] << 8) & 0xff00; } else { /* lower byte */ cw |= ((int) buf[i]) & 0x00ff; cksum += cw; } } if( (i & 1) != 0 ) cksum += cw; ckval = ((xbuf[rl] << 8) & 0xff00) | (xbuf[rl+1] & 0x00ff); cksum &= 0xffff; ckval &= 0xffff; if( cksum != ckval ) { fprintf( stderr, "FATAL: checksum failed: %04x %04x\n", cksum, ckval ); exit(1); } return rl-2; } void unpack_buffer( char buf[], int bflen, int start ) { int bcnt; int n; int i; bcnt = start; while( bcnt < bflen ) { n = ((buf[bcnt] << 8) & 0xff00) | (buf[bcnt+1] & 0x00ff); bcnt += 2; printf( " =%3d= ", n ); for( i = 0; i < n; i++ ) printf( "%c", buf[bcnt++] ); printf( "\n" ); } } int unpack_file( char buf[], int bflen, int start, FILE *fd ) { int bcnt, blen, i, n; char dl1[32], dl2[32], dl3[32], dl4[32]; FILE *sd; char lbuf[BUFLEN+2]; char *xbuf; int xmax; int reclen; int rl; char fname[2048],pname[2048]; int l; char *rectype; bcnt = start; n = ((buf[bcnt] << 8) & 0xff00) | (buf[bcnt+1] & 0x00ff); bcnt += 2; if( n != 16 ) { fprintf( stderr, "Phase error in unpack hdr for 1\n" ); skip_file (tp); return; //exit(1); } for( i = 0; i < n; i++ ) dl1[i] = buf[bcnt++]; dl1[i] = 0; n = ((buf[bcnt] << 8) & 0xff00) | (buf[bcnt+1] & 0x00ff); bcnt += 2; if( n != 10 ) { fprintf( stderr, "Phase error in unpack hdr for 2\n" ); exit(1); } for( i = 0; i < n; i++ ) dl2[i] = buf[bcnt++]; dl2[i] = 0; n = ((buf[bcnt] << 8) & 0xff00) | (buf[bcnt+1] & 0x00ff); bcnt += 2; if( n != 26 ) { fprintf( stderr, "Phase error in unpack hdr for 3\n" ); exit(1); } for( i = 0; i < n; i++ ) dl3[i] = buf[bcnt++]; dl3[i] = 0; n = ((buf[bcnt] << 8) & 0xff00) | (buf[bcnt+1] & 0x00ff); bcnt += 2; if( n != 26 ) { fprintf( stderr, "Phase error in unpack hdr for 3\n" ); exit(1); } for( i = 0; i < n; i++ ) dl4[i] = buf[bcnt++]; dl4[i] = 0; /* ** figure out type of file */ if( dl2[0] == 'A' ) rectype = "ABS"; else if( dl2[0] == 'R' ) rectype = "REL"; else if( dl2[0] == 'D' ) rectype = "DIG"; else rectype = "UNK"; /* ** now, read the rest of the records and save them to a file */ strcpy( pname, dl1 ); #if 0 for( i = 0; i < strlen(pname); i++ ) if( pname[i] == ' ' ) pname[i] = '_'; l = strlen(pname); strcat( pname, "_" ); strcat( pname, dl3 ); #else l = 0; #endif for( i = strlen(pname)-1; i > l; i-- ) if( pname[i] == ' ' ) pname[i] = 0; else if( pname[i] != ' ' ) break; for( i = l; i < strlen(pname); i++ ) if( pname[i] == ' ' ) pname[i] = '_'; else if( pname[i] == '/' ) pname[i] = '_'; sprintf( fname, "tapes/%s", pname ); if( (sd = fopen( fname, "w" )) == NULL ) { fprintf( stderr, "FATAL: Can't open %s for writing\n", fname ); return 0; } printf( "Creating file %s\n", fname ); xbuf = (char *) malloc( sizeof(char) * (BUFLEN * 10) ); xmax = BUFLEN * 10; if( xbuf == NULL ) { fprintf( stderr, "FATAL: out of memory\n" ); exit(1); } blen = 0; while( (reclen = read_logical_record( lbuf, BUFLEN, fd )) > 0 ) { if( (blen + reclen) > xmax ) { xbuf = realloc( xbuf, xmax + (10 * BUFLEN) ); xmax += (10 * BUFLEN); if( xbuf == NULL ) { fprintf( stderr, "FATAL: out of memory\n" ); exit(1); } } for( i = 0; i < reclen; i++ ) xbuf[blen++] = lbuf[i]; } bcnt = 0; while( bcnt < blen ) { rl = ((xbuf[bcnt] << 8) & 0xff00) | (xbuf[bcnt+1] & 0x00ff); bcnt += 2; if( (rl & 0x8000) != 0 ) /* check for end */ break; fwrite( &(xbuf[bcnt]), sizeof(char), rl, sd ); bcnt += rl; } fclose(sd); return 1; } int main( int argc, char *argv[] ) { unsigned int reclen; unsigned int reccnt; unsigned long byte_cnt; char dl1[32], dl2[32], dl3[32], dl4[32]; char *rectp; reccnt = 0; byte_cnt = 0; if( argc < 2 ) { fprintf( stderr, "Usage: saveit tape\n" ); exit(1); } if( (tp = fopen(argv[1],"r")) == NULL ) { fprintf( stderr, "FATAL: Can't open %s\n", argv[1] ); exit(1); } skip_file( tp ); /* header? */ skip_file( tp ); /* prog to read tape? */ while( 1 ) { reclen = read_logical_record( buf, BUFLEN, tp ); if( reclen < 0 ) { printf( "**** End of Tape\n" ); break; } else if( reclen == 0 ) { printf( "**** File Mark\n" ); break; } byte_cnt += reclen; reccnt++; /* printf( "**** record %d size %d total size %ld\n", reccnt+1, reclen, byte_cnt ); */ if( unpack_file( buf, reclen, 4, tp ) == 0 ) break; /* saw eof */ } fclose(tp); return 0; }