/* * print a DOS-11 DECtape directory * */ #include unsigned char tape[576][512]; unsigned short uicblk[63][3]; char str[9]; /* J F M A M J J A S O N D */ int monthLen[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; char *monthNam[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; convdate( int date, char *str) { int year; int month; int day; int i; int dayinyear; date &= 0xfff; year = (date / 1000) + 1970; dayinyear = (date % 1000); for (i=0; i<12; i++){ month = i; if(dayinyear <= monthLen[i]){ day = dayinyear; break; } else{ dayinyear -= monthLen[i]; if(year != 2000){ if((i == 1)&&((year % 4) == 0)){ /* deal with Feb 29 */ if( dayinyear == 1 ){ day = 29; break; } } } } } sprintf(str, "%s %2d, %4d", monthNam[month], day, year); } /* * Convert Radix-50 integer to ASCII string. */ char atable[] = { ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '$', '.', '?', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; r50toc (r50, str) unsigned int r50; char *str; { r50 &= 0xffff; r50 = r50 & 65535; str[0] = atable[r50/03100L]; r50 = r50%03100L; str[1] = atable[r50/050]; str[2] = atable[r50%050]; str[3] = '\0'; } /* * UFD blocks: * +-------------------------------+ * | link to next UFD | * +-------------------------------+ * | rad50 file name | 28 file entries/blk * +- -+ * | | * +-------------------------------+ * | rad50 file extn | * +---+--------+------------------+ * |C/L| | 12 bit date | year = date/1000+1970 day = remainder * +-------------------------------+ * | next free byte | * +-------------------------------+ * | starting block | * +-------------------------------+ * | #blks in file | * +-------------------------------+ * | last block | * +------+-------+----------------+ * | lock | usage | protection byte| * +------+-------+----------------+ * */ printUFD(unsigned char *p) { unsigned char *blk; unsigned int i,n,j; unsigned int date, length, start, prot, nxtByte, lastBlk; p+=2; // skip over link word for(n=0; n<28; n++){ // 28 file names in the UFD i = *p; i |= *(p+1)<<8; p+=2; // file name if(i==0) continue; r50toc (i, str); printf("%s", str); i = *p; i |= *(p+1)<<8; p+=2; r50toc (i, str); printf("%s", str); printf("."); i = *p; i |= *(p+1)<<8; p+=2; r50toc (i, str); printf("%s ", str); date = *p; date |= *(p+1)<<8; p+=2; nxtByte = *p; nxtByte |= *(p+1)<<8; p+=2; // next byte start = *p; start |= *(p+1)<<8; p+=2; // start blk length= *p; length |= *(p+1)<<8; p+=2; lastBlk = *p; lastBlk |= *(p+1)<<8; p+=2; // last blk prot = *p; prot |= *(p+1)<<8; p+=2; printf("%5d",length); // #blks if(date&0x8000) putchar('C'); else putchar(' '); convdate( date, str); printf(" %s ",str); // date printf("<%3o>",prot&0xff); // prot printf(" start:%4o last:%4o byte:%d\n", start, lastBlk, nxtByte); blk = &tape[start][0]; i = start; if(date&0x8000){ // Contiguous file } else{ j = 1; #ifdef PRTBLKS while(1){ printf("%4o ", i); if(i == lastBlk) break; if((j++%16)==0) printf("\n"); i = *blk; i |= *(blk+1)<<8; blk = &tape[i][0]; } #endif } // printf("\n"); fflush(stdout); } } main(argc, argv) int argc; char **argv; { unsigned char *p; unsigned int i, n, secondUFD; FILE *fp; if(!(fp = fopen(argv[1],"rb"))) exit(1); if(fread(tape, 1, 294512, fp)!= 294512) exit(1); // image < 576 blks p = &tape[0100][0]; // addr of mfd blk #1 (blk 0100) i = *p | *(p+1)<<8; if(i != 0101) {printf("Not a DOS-11 format DECtape\n"); exit(1);} p = &tape[i][0]; // Adr of MFD blk #2 (should be 0101 == 0x41) p += 2; // link should be zero on dectapes // make list of UICs for(n=0; n<63; n++){ i = *p | *(p+1)<<8; uicblk[n][0] = i; p+=2; i = *p | *(p+1)<<8; uicblk[n][1] = i; p+=2; i = *p | *(p+1)<<8; uicblk[n][2] = i; p+=4; } // turns out on DECtape, multple MFD entries point to the // two UFD blocks p = &tape[0102][0]; printUFD(p); i = *p | *(p+1) << 8; p = &tape[i][0]; // pick up link word to second UFD printUFD(p); }