/* EXACAT make simple list of what's on a BBSO Exabyte tape. Modifications: 11-Nov-96 JRV Begin 26-Nov-96 JRV Debugged, added five-line header to match old .TDA files. 07-Jun-98 JRV Modifications for Linux. 30-Sep-99 JRV Corrections for Y2K problems. 13-May-02 JRV Modifications for RH Linux kernel 2.4.9 04-Sep-03 JRV Fix problem with old DATE-OBS strings. */ #include #include #include #include #include #include #include #include #include #include "fitsio.h" #include "exacat.h" int tapehdrd(int tapefildes, unsigned char *tapebuff, char (**header)[81], int *maxln, int *bitpix, int *naxes) { char (*headbuf)[81] = NULL; int nbytesread, bytesread, i; /* Exabyte tape blocks are always 8192 bytes */ nbytesread = read(tapefildes, tapebuff, 8192); if (nbytesread != 8192) { if (nbytesread == 0) return -1; /* EOF read, end of cluster */ else if (nbytesread > 0) { printf("tapehdrd: read incorrect number of bytes: %d\n", nbytesread); return -2; } else { printf("tapehdrd: error reading header from tape\n"); perror("read call from tapehdrd"); return -2; } } /* copy header into FITS line array */ *maxln = 0; do { if (*maxln % 36 == 0) { headbuf = (char (*)[81]) xalloc(headbuf, (*maxln + 36) * 81); if (headbuf == NULL) { printf("tapehdrd: error allocating memory for FITS header\n"); return -3; } } memcpy (headbuf[*maxln], tapebuff + (*maxln * 80), 80); headbuf[*maxln][80] = '\0'; } while (strncmp(headbuf[(*maxln)++], "END ", 8) != 0); *header = headbuf; bytesread = fits_head_decode (headbuf, *maxln, bitpix, naxes); if (bytesread < 0) { switch(bytesread) { case -11: printf("FITS error -- not SIMPLE\n"); break; case -12: printf("FITS error -- BITPIX error\n"); break; case -13: printf("FITS error -- NAXES error\n"); break; case -14: printf("FITS error -- NAXIS1\n"); break; case -15: printf("FITS error -- NAXIS2\n"); break; default: printf("Error decoding FITS header\n"); break; } return -2; } return 0; } void julian(int mode, long *iy, long *m, double *d, double *djul) { /* from Explanatory Supplement to the Astronomical Almanac */ /* page 604. Valid for Gregorian dates with JD >= 0. */ /* The year 0 is equal to 1 BC. */ long l,n,i,j, d0, dj; double fd; if (mode == 0) { /* convert calendar date to Julian date */ d0 = (long) *d; fd = *d - (double) d0; dj = (1461 * ((*iy) + 4800 + ((*m) - 14)/12))/4 + (367*((*m) - 2 - 12 * (((*m) - 14)/12)))/12 - (3 * (((*iy) + 4900 + ((*m) - 14)/12)/100))/4 + d0 - 32075; *djul = (double) dj + (fd - 0.5); } else { /* convert Julian date to calendar date */ dj = (long) (*djul); fd = *djul - (double) dj; l = dj + 68569; n = (4 * l)/146097; l = l - (146097 * n + 3)/4; i = (4000 * (l + 1))/1461001; l = l - (1461 * i)/4 + 31; j = (80 * l)/2447; d0 = l - (2447 * j)/80; l = j/11; *m = (j + 2 - 12 * l); *iy = (100 * (n - 49) + i + l); *d = d0 + fd + 0.5; } } void xhinfo(char (*header)[81], datrec *dirrec, char *comment,int nend,int *datac) { char datestr[9], timestr[9], wavstr[9]; char typeobs[9], objstr[9]; char commstr[49]; char tdatestr[9]; int crval1, crval2, nframes, biasval, line; int id, imin, ih, isec, iy, m, lendateobs; long ly, lm; double d; double djul; dirrec->nframes = 1; line = freadi(header, nend, "CRVAL1", &crval1, NULL); dirrec->x = crval1; line = freadi(header, nend, "CRVAL2", &crval2, NULL); dirrec->y = crval2; line = freads(header, nend, "OBJECT", objstr, NULL); strcpy(dirrec->objnam, objstr); line = freads(header, nend, "TYPE-OBS", typeobs, NULL); /* figure out the observation type (what a mess!) */ line = freads(header, nend, "WAVLNTH", wavstr, NULL); /* printf("this is typeobs: x%sx\n", typeobs); */ dirrec->typobs = typeobs[0]; if (!strcmp(typeobs,"VMG")) dirrec->typobs = 'V'; if (!strcmp(typeobs,"VMG-Q")) dirrec->typobs = 'Q'; if (!strcmp(typeobs,"VMG-U")) dirrec->typobs = 'U'; if (!strcmp(typeobs,"DOPPL") || !strcmp(typeobs,"DOPPLER")) dirrec->typobs = 'D'; if (!strcmp(typeobs,"VMG W/L") || !strcmp(typeobs,"VMG W/L") || !strcmp(typeobs,"VMG-I")) dirrec->typobs = 'I'; if (!strcmp(typeobs,"DIRECT")) dirrec->typobs = 'J'; if (!strcmp(typeobs,"LINE MAP")) dirrec->typobs = 'X'; if (!strcmp(typeobs,"FULLDISK")) { dirrec->typobs = 'H'; if (!strcmp(wavstr,"KLINE")) dirrec->typobs = 'K'; if (!strcmp(wavstr,"W.L.")) dirrec->typobs = 'W'; } if (!strcmp(typeobs,"REGION")) { dirrec->typobs = 'F'; if (!strcmp(wavstr,"HALF")) dirrec->typobs = 'C'; if (!strcmp(wavstr,"HACL")) dirrec->typobs = 'C'; } line = freads(header, nend, "TIME-OBS", timestr, commstr); line = freads(header, nend, "DATE-OBS", datestr, commstr); lendateobs = strlen(datestr); if (lendateobs == 7) { /* this happens with the old DATE-OBS format if the day is between 1 and 9. The leading space is stripped by freads. We have to put it back here. */ strcpy(tdatestr, datestr); strcpy(datestr, " "); strcat(datestr, tdatestr); lendateobs = strlen(datestr); } if (lendateobs == 8) { /* old DATE-OBS format */ sscanf(datestr, "%2d%*1c%2d%*1c%2d", &id, &m, &iy); if (id == 0 && m == 0 && iy == 0) { id = 1; m = 1; iy = 68; } d = (double) id; iy = iy + 1900; /* Note that this is the FITS Y2K problem! */ } else { sscanf(datestr, "%d-%d-%d",&iy,&m,&id); d = (double) id; } sscanf(timestr, "%2d%*1c%2d%*1c%2d", &ih, &imin, &isec); d = d + (((double) (ih * 60) + imin + ((double) isec / 60.0)) / 1440.0); ly = iy; lm = m; julian(0, &ly, &lm, &d, &djul); dirrec->jd = djul; line = freadi(header, nend, "FRAMES", &nframes, commstr); dirrec->nframes = (long) nframes; *datac = FALSE; line = freadi(header, nend, "BIAS", &biasval, commstr); if (line != -1) *datac = TRUE; /* used Datacube system if BIAS keyword is present */ } void xtimestr(double realday, char *tstring) { int ihh, imm, iss, idd; double dtmp; idd = (int) realday; dtmp = realday - (double) idd; dtmp = 24.0 * dtmp; ihh = (int) dtmp; dtmp = dtmp - (double) ihh; dtmp = 60.0 * dtmp; imm = (int) dtmp; dtmp = dtmp - (double) imm; dtmp = 60.0 * dtmp; iss = (int) dtmp; sprintf(tstring, "%2.2d:%2.2i:%2.2i", ihh, imm, iss); } int main(int argc, char *argv[]) { int interflg, rmode, tapefp, maxln, bitpix; int naxes[4], result, xresult; int clustart, cluend, filstart, filend, ldblank, lfblank, istat; int flen, j, lset; int imm, ind2; int ltype; int leot = FALSE; int lrfdisp = FALSE; int lname, unitnum; int cnew, fnew,eofflag; int iclust, ifile, nfskip, nskip, i, ndblke, icfile; int ndbyte, bytesleft; int iy, mm, id; long ly, lm; double ldd; char string[81], uinput[81]; char lfil[81]; char tstr[9]; char tapdevnam[81], tapenam[81], filnam[84]; unsigned char tapebuff[8192]; char (*header)[81]; FILE *cfp; char filename[81], file[81], fillin[81]; char *comment = "COMMENT "; long tapeid, nimage; int datac; char thiscomm[49]; datrec thisimage; struct mtop mt_command; struct mtget mt_status; if (argc > 1) { unitnum = (int) strtol(argv[1], NULL, 10); if (unitnum == 0) { strcpy(tapdevnam, "/dev/nst0"); } else if (unitnum == 1) { strcpy(tapdevnam, "/dev/nst1"); } else { printf("Usage: EXACAT unitnum tapename\n"); exit(0); } } else { printf("Usage: EXACAT unitnum tapename\n"); exit(0); } if (argc == 3) { strcpy(tapenam, argv[2]); } else { printf("Usage: EXACAT unitnum tapename\n"); exit(0); } strcpy(filnam,tapenam); strcat(filnam,".cat"); printf("EXACAT 04 Sep 2003 Linux version\n"); printf(" Make simple list of what's on a BBSO Exabyte tape\n"); /* Attempt to access Exabyte drive */ if((tapefp = open(tapdevnam, O_RDONLY)) == -1) { printf("cannot open tape\n"); exit(0); } else { printf("Exabyte drive %s successfully accessed.\n", tapdevnam); } /* Set tape density */ mt_command.mt_op = MTSETDENSITY; mt_command.mt_count = 0x14; /* EXB-8200 density */ result = ioctl(tapefp, MTIOCTOP, &mt_command); if (result == -1) { printf("cannot set tape density\n"); exit(0); } mt_command.mt_op = MTSETBLK; mt_command.mt_count = 0; result = ioctl(tapefp, MTIOCTOP, &mt_command); if (result == -1) { printf("could not set variable tape block size\n"); exit(0); } /* Open output file for catalog */ cfp = fopen(filnam, "a"); /* Write header in catalog file */ fprintf(cfp, " Exabyte tape file directory\n"); fprintf(cfp, " Directory file name: %s\n", filnam); fprintf(cfp, "---------------------------------------------------------\n"); fprintf(cfp, " C File B Region T Itg X Y Time\n"); fprintf(cfp, "---------------------------------------------------------\n"); /* Position Exabyte tape at first file */ eofflag = FALSE; nimage = 0; iclust = 1; ifile = 0; icfile = 0; cnew = clustart; fnew = filstart; nfskip = fnew - 1; nskip = cnew - 1; /* Set up to start reading */ /* printf("ifile now %d\n", ifile); */ read_file: for (;;) { if (lrfdisp) { printf("Reading files...\n"); lrfdisp = FALSE; } /* printf("top of main loop\n"); */ /* Read and decode header */ xresult = tapehdrd(tapefp, tapebuff, &header, &maxln, &bitpix, naxes); /* printf("result from tapehdrd: %d\n",xresult); */ if (xresult == 0) { /* printf("maxln = %d\n", maxln); printf("bitpix = %d\n", bitpix); printf("naxes: %d %d\n", naxes[0], naxes[1]); */ eofflag = FALSE; /* get extra file info */ thisimage.bitpix = bitpix; xhinfo(header, &thisimage, thiscomm, maxln, &datac); /* printf("xhinfo completed OK\n"); */ /* Now skip over the data */ /* determine size of data, skip over it */ ndbyte = naxes[0] * naxes[1]; if (bitpix == 16) ndbyte = ndbyte * 2; ndblke = (ndbyte + 8191) / 8192; mt_command.mt_count = ndblke; for (i = 0; i < ndblke; i++) { result = read(tapefp, tapebuff, 8192); if (result != 8192) { if (result == 0) { /* EOF read */ goto cluster_change; } else if (result > 0) { printf("read incorrect number of bytes: %d\n", result); goto error_stop; } else { printf("tape file skip error\n"); perror("read call from file skip:"); goto error_stop; } } } /* printf("image data skipped OK\n"); */ ifile++; icfile++; thisimage.cumnum = ifile; thisimage.clustnum = iclust; thisimage.filenum = icfile; thisimage.nextobs = NULL; strcpy(thisimage.empty," "); /* now write the image info in the output file */ /* printf("jd = %f\n", thisimage.jd); */ julian(1,&ly,&lm,&ldd,&(thisimage.jd)); id = (int) ldd; iy = (int)ly; mm = (int)lm; /* printf("%d %d %f\n",iy,mm,ldd); */ xtimestr(ldd,tstr); /* printf("xtimestr returned OK\n"); */ fprintf(cfp,"%3ld%5ld%3ld %8s %1c%5ld%5ld%5ld %4.4d-%2.2d-%2.2d %8s\n", thisimage.clustnum, thisimage.filenum, thisimage.bitpix, thisimage.objnam, thisimage.typobs,thisimage.nframes,thisimage.x, thisimage.y,iy,mm,id,tstr); /* printf("wrote to catalog file\n"); */ } else if (xresult == -1) { goto cluster_change; } else { printf("Error during interpretation of header\n"); printf("in cluster %d and file %d.\n", iclust, icfile); printf("tapehdrd returns: %d.\n", xresult); printf("Program stops.\n"); goto error_stop; } /* printf("Bottom of main loop.\n"); */ } /* Come here if cluster changes */ cluster_change: if (!eofflag) { eofflag = TRUE; iclust++; icfile = 0; goto read_file; } else { goto normal_stop; } normal_stop: printf("%d images cataloged from tape\n", ifile); printf("Done.\n"); close(tapefp); fclose(cfp); exit(0); error_stop: printf("%d images cataloged from tape\n", ifile); printf("Exabyte Cluster and File numbers: %d %d\n", iclust, icfile); printf("Program exits.\n"); fclose(cfp); close(tapefp); exit(0); }