/* Program to read NCAR tapes and dump the data to disk files. * * Options: * * ddncar [-v] [-n from_f,to_f] [-f tape_station] [ -e experiment ] directory * from_f: first file to process (the first file is file no 0) * to_f: last file to process * default tape_station is "/dev/rmt2h" * * Disk record format: * ... * recl: record length in bytes excl. recl word (4 bytes) incl. checksum * ncar prologue/data: 2 byte words * checksum: XOR over record incl. recl word (4 bytes) */ #include #include #include #include #include #include #include #include #include #ifndef DEFTNAME #define DEFTNAME "/dev/rmt/2" #endif #define DATDIR "/data/ncar" #define MAXSIZE 4097 char *tname=DEFTNAME; int tape_fd; struct tape_block { char data_tp[MAXSIZE]; char *p_ptr; char *last_ptr; } tape; #if defined(__STDC__) void put_rec(int fd, short buf[]); char *expname(short modexp); int main(int argc, char **argv) #else void put_rec(); char *expname(); int main(argc, argv) int argc; char **argv; #endif /* int main(int argc, char **argv) */ { extern char *optarg; extern int optind, opterr; int c; int from_f,to_f,ifile; int verbose = 0; int wtfil = 0; char fname[256],*fptr,*cptr; char *exp = 0; int force_expname = 0; int disk_fd[4]; int ftype = 0; FILE *wtfil_fp = 0; char datdir[MAXPATHLEN]; short in_prol[16]; short *out_prol, *buf, *new_buf; int bufsize = 8192; int ngot,i; struct stat statbuf; buf = (short *) malloc(bufsize); out_prol = buf; memset(out_prol, '\0', 16*sizeof(short)); from_f = 0; to_f = 9999; /* Parse options: */ while ((c = getopt(argc, argv, "e:f:n:v")) != EOF) { if ( c=='n' ) sscanf(optarg,"%d%c%d", &from_f, &c, &to_f); else if ( c=='e' ) { exp = optarg; force_expname = 1; } else if ( c=='f' ) tname = optarg; else if ( c=='v' ) verbose = 1; } #ifdef DATDIR strcpy(datdir, DATDIR); #else getwd(datdir); #endif if ( argv[optind]!=NULL ) if ( argv[optind][0] == '/' ) strcpy(datdir, argv[optind]); else strcat(datdir, argv[optind]); /* Initialize tape: */ tape_fd=open(tname, O_RDONLY); if ( tape_fd<0 ) { perror("ddncar"); exit(1); } tape.p_ptr = tape.data_tp; tape.last_ptr = tape.data_tp; for (i=0; i<4; i++) disk_fd[i] = -1; for (i=0; i0 ) { close(disk_fd[i]); disk_fd[i] = -1; } } memset(out_prol, '\0', 16*sizeof(short)); /* If last file wanted, then break: */ if ( ++ifile>to_f ) break; /* check for double EOF: */ if ( (ngot=get_block()) <= 0 ) { if (verbose) printf("E-O-T\n"); exit(0); } } memcpy(in_prol, tape.p_ptr, 16*2); if ( wtfil=(in_prol[1]!=1002) ) { /* New text (wtfil) file?: */ if ( wtfil_fp == 0 ) { /* Change to exp directory: */ chdir(datdir); if ( !force_expname ) exp = expname(in_prol[3]); if ( stat(exp, &statbuf) == -1 ) mkdir(exp, 0777); if (verbose) printf("ddncar: Experiment %s, ", exp); chdir(exp); /* Get file name: */ tape.p_ptr += 80; strncpy(fname, tape.p_ptr, 6); fname[6] = '\0'; if ( fptr = strchr(fname, ' ') ) *fptr = '\0'; strcat(fname, ".wtfil"); /* If file exists, insert version nr: */ if ( stat(fname, &statbuf) == 0 ) { fptr = strchr(fname, '.'); i = 0; while (++i<100) { sprintf(strchr(fname, '.'), ".%d\0", i); strcat(fname, ".wtfil"); if ( stat(fname, &statbuf) == -1 ) break; } } if (verbose) printf(" open %s\n", fname); /* Open disk file: */ if ( (wtfil_fp=fopen(fname, "w")) == 0 ) { fprintf(stderr, "ddncar: cannot open %s\n", fname); exit(1); } } while ( tape.p_ptr < tape.last_ptr ) { fptr = tape.p_ptr + 79; while ( (fptr >= tape.p_ptr) && ((*fptr == ' ') || !isprint(*fptr)) ) fptr--; cptr = tape.p_ptr; while ( cptr<=fptr ) fputc(*cptr++, wtfil_fp); fputc('\n', wtfil_fp); tape.p_ptr += 80; } } else { /* Data file */ while( rest()>0 ) { memcpy(in_prol, tape.p_ptr, 16*2); /* Check if it's a continuation of the ncar record from the previous block: */ if ( memcmp(&out_prol[1], &in_prol[1], 14*2)==0 ) { tape.p_ptr += (in_prol[12] + in_prol[13]*2 + in_prol[14])*2; /* Make sure big enough buffer: */ if ( bufsize < ((out_prol[0] + in_prol[14]*in_prol[15])*2) ) { new_buf = (short *) malloc((out_prol[0] + in_prol[14]*in_prol[15])*2); memcpy(new_buf, buf, bufsize); free(buf); buf = new_buf; out_prol = new_buf; bufsize = (out_prol[0] + in_prol[14]*in_prol[15])*2; } get_data(buf + (out_prol[0] - 16), in_prol[14]*in_prol[15]*2); out_prol[15] += in_prol[15]; out_prol[0] = ltot(out_prol); } else { /* If not, put the previous record to disk: */ put_rec(disk_fd[ftype], buf); /* Find out the new record type: */ ftype = 0; if ( in_prol[2]==72 ) if ( (in_prol[3]%2)==0 ) fname[0] = 't'; else { fname[0] = 'p'; ftype = 1; } else if ( in_prol[2]==71 ) fname[0] = 'k'; else if ( in_prol[2]==73 ) fname[0] = 's'; else if ( in_prol[2]==74 ) fname[0] = 'v'; else if ( in_prol[2]==70 ) fname[0] = 'a'; else { fprintf(stderr, "ddncar: Unknown site code, skipping on...\n"); if ( fsf_tape()<0 ) { perror("ddncar"); exit(1); } continue; } /* Open the disk files: */ if ( disk_fd[ftype]<0 ) { /* Change to exp directory: */ chdir(datdir); if ( !force_expname ) exp = expname(in_prol[3]); if ( stat(exp, &statbuf) == -1 ) mkdir(exp, 0777); chdir(exp); sprintf(fname+1, "%02d%02d%02d%02d%02d%02d.ndtst", in_prol[4]%100, in_prol[5]/100, in_prol[5]%100, in_prol[6]/100, in_prol[6]%100, in_prol[7]/100); if ( stat(fname, &statbuf) == 0 ) { fprintf(stderr, "%s: file %s exists\n", argv[0], fname); exit(1); } if (verbose) printf("ddncar: open %s/%s\n", exp, fname); if ( (disk_fd[ftype] = open(fname, O_RDWR|O_CREAT, 0666))<0 ) { perror("ddncar"); exit(1); } } /* Get the record and save the prologue as the previous one: */ memcpy(out_prol, in_prol, 16*sizeof(short)); get_data(buf, in_prol[0]*2); } } } } close(tape_fd); exit(0); } int get_block() { int ngot; if ( (ngot = read(tape_fd, tape.data_tp, sizeof(tape.data_tp))) > 0 ) { if ( ngot >= MAXSIZE ) { fprintf(stderr, "ddncar: too big blocksize, please recompile me\n"); exit(1); } #ifdef SWAP swab(tape.data_tp, tape.data_tp, ngot); #endif /* printf("%i %i %i %i %i\n", *((short *) tape.data_tp), *((short *) tape.data_tp + 1), *((short *) tape.data_tp + 2), *((short *) tape.data_tp + 3), *((short *) tape.data_tp + 4)); */ tape.p_ptr = tape.data_tp + 2; tape.last_ptr = tape.data_tp + ngot - 2; } return ngot; } int rest() { return tape.last_ptr - tape.p_ptr; } #if defined(__STDC__) int get_data(void *buf, int nget) #else int get_data(buf, nget) void *buf; int nget; #endif { if ( nget > (tape.last_ptr-tape.p_ptr) ) nget = tape.last_ptr-tape.p_ptr; memcpy(buf, tape.p_ptr, nget); tape.p_ptr += nget; return nget; } int fsf_tape() { struct mtop tape_com; tape_com.mt_op = MTFSF; tape_com.mt_count = 1; return ioctl(tape_fd, MTIOCTOP, &tape_com); } #if defined(__STDC__) void put_rec(int fd, short buf[]) #else void put_rec(fd, buf) int fd; short buf[]; #endif { int recl,chksum,*top,*ptr; if ( buf[0]>0 ) { recl = buf[0]*2+4; if ( (recl%4)!=0 ) recl=((recl%4)+1)*4; chksum = recl; ptr = (int *) buf; top = ptr + (recl-4)/4; while ( ptr6998 ) strcpy(name, "sp-exp"); else { strcpy(name, "cp-"); sprintf(name+3, "%d-\0\0", (modexp-6000)/100); name[strlen(name)] = "abcdefghijklmnopqrstvuvz"[(modexp%100)/2 - 1]; } return name; }