/***************************************************************************** * * (C) 1983, * Lee Merrick & Associated Limited * 75 The Donway West, Suite 1014 * Don Mills, Ontario M3C 2E9 * (416) 446-1011 * * Program: * ---------- * DUMPA.C * * Ver.Rv: Date: Author: Remarks: * ------- --------- ------- -------------------------------------- * 1.0 22-AUG-83 WGM New * * Command Line: * ---------------------------------------------------------------------- * -i* >* -s# -e# -b -c -? for help * * -i* input device or file (default DK:) * >* output device or file (default TT:) * -s# starting block number (default 0) * -e# ending block number (default 32767) * -b print (no -c)/display (-c) block numbers (default NO) * -c print CREATEs necessary for reconstruction (default NO) * * Description: * ---------------------------------------------------------------------- * Dump ASCII / Directory Reconstruction Program * * To dump a device or file in ascii format: * DUMPA -idevice:{file} >device:{file} -b * Examples: * DUMPA -iMYFILE.TXT !Text looks like KED display * DUMPA -iMYFILE.TXT -b !Will print block numbers * DUMPA -iMYFILE.TXT -s020 -b !Zero in front makes octal * DUMPA -iBIGFIL.TXT -s1000 -e1002 !Peeks inside big file * * Bytes are parity stripped and then output as follows: * 040 <= x <= 0176 as is * x == 011 (),012 (),015 () as is * x == 013 () as "VT" symbol * x == 014 () as "FF" symbol * x == 000 (), 177 (
) ignored * x == all others as "^" and x+0100, eg. 002 as ^B, etc. * * To reconstruct a directory (on physical device or archive file): * (1) DUMPA -idevice: >otherdevice:{file} -c * (2) INIT device: * (3) ASSIGN device: DK: * (4) @otherdevice:file * * Example: * DUMPA -iDY1: >DY0:DY1DIR.COM -c -b !display block numbers * !every 100 blocks * INIT DY1: * ASSIGN DY1: DK: * @DY0:DY1DIR.COM * * File names are created in the form Znnn.ext with 'nnn' starting * at zero and incrementing for each file, and 'ext' as follows: * (1) SAV Save file (bytes 041,043,0360 non-zero). * (2) VOL Beginning of physical device or archive * file (starts bytes 0240,000) The * directory is offset 6 blocks into * this area. If this is an archive file * a CREATE can be issued over this * file and the following files and * the archive successfully opened * if the archive directory is intact. * (3) LIB Object library (normally .OBJ) (starts bytes * 001,000,042,000,007,000) The following * .OBJ are often part of it, especially * if trailing nulls are 000. * (4) OBJ Object file (starts bytes * 001,000,056,000). * (5) C C source file (starts "/*", "#i", or "#d") * (6) MAC MACRO-11 source file (starts ";",";", * "; ",".TI",".TI"). * (7) TXT Other text file (no embedded nulls). * (8) UNK Unknown file (immediately follows .C * .MAC, or .TXT known to have ended because * of trailing nulls, but the next block * doesn't match any expected format. This * is often the remains of previously deleted * areas. * * The number of trailing nulls can be of some help in determining * if the divisions are real or imagined. Remember, the process * is by no means complete. The created files must be scanned, * renamed, and often grouped when imagined breaks are made. Files * created over what were previously deleted areas must also be deleted. * Hint: the purpose of .SAV files can often be determined by examining * the text literals stored within them. * *****************************************************************************/ #include #include #define BUFSIZ 512 TEXT *_prmpt = "-i* >* -s# -e# -b -c -h for help\r\n*"; TEXT *fil = 0; COUNT s = 0; COUNT prvs = 0; COUNT prv = 0; COUNT e = 32767; BOOL prbl = NO; BOOL prcr = NO; BOOL help = NO; BOOL oneovr = NO; TEXT buf[BUFSIZ] = ""; TEXT prvbuf[BUFSIZ] = ""; TEXT ch = '\0'; COUNT type = 0; COUNT ptype = 0; TEXT typ[4] = ""; TEXT prvtyp[4] = ""; COUNT i = 0; COUNT j = 0; COUNT trail = 0; COUNT filnum = 0; main(ac,av) COUNT ac; TEXT *av[]; { TEXT *_q; FILE fd; COUNT n; s = 0; e = 32767; prbl = NO; prcr = NO; help = NO; caparg(ac,av); if(_q = getflags(&ac,&av,"I*,S#,E#,B,C,H", &fil,&s,&e,&prbl,&prcr,&help)) { errfmt("?DUMPA-F-Invalid flags\n"); return(RETRY); } if (help) { errfmt("-i* input device or file (default DK:)\n"); errfmt("-s# starting block number (default 0)\n"); errfmt("-e# ending block number (default 32767)\n"); errfmt("-b print (no -c)/display (-c) block numbers (default NO)\n"); errfmt("-c print CREATEs necessary for reconstruction (default NO)\n"); return(RETRY); } if (!fil) { if((fd = open("DK:",READ,1)) < 0) { errfmt("?DUMPA-F-DK: failed to open\n"); return(RETRY); } } else { if((fd = open(fil,READ,1)) < 0) { errfmt("?DUMPA-F-File not found %p\n",fil); return(RETRY); } } lseek(fd,(long)s<<9,0); while (s <= e && 0 < (n = read(fd,buf,BUFSIZ))) { if (prcr) { if (prbl && !(s%100)) errfmt("\rBLOCK NUMBER %+06o (%+06i.)\r", s,s); if (typsav(buf)) { cpystr(typ,"SAV",NULL); type = 1; } else if (typvol(buf)) { cpystr(typ,"VOL",NULL); type = 2; } else if (typlib(buf)) { cpystr(typ,"LIB",NULL); type = 3; } else if (typobj(buf)) { cpystr(typ,"OBJ",NULL); type = 4; } else if (typc(buf)) { cpystr(typ,"C ",NULL); type = 5; } else if (typmac(buf)) { cpystr(typ,"MAC",NULL); type = 6; } else if (typtxt(buf)) { cpystr(typ,"TXT",NULL); type = 7; } else if (!prv || ptype == 5 || ptype == 6 || ptype == 7) { cpystr(typ,"UNK",NULL); type = 8; } else type = 0; if (type) { if (prv) { nulchk(prvbuf,&trail); putfmt("CREATE Z%+03i.%p/ALLOC:%+05i./START:%+05i. !Number of trailing nulls: %+03i\n", filnum++,prvtyp,s-prvs,prvs,trail); putch(-1); } cpystr(prvtyp,typ,NULL); prvs = s; ptype = type; prv = YES; } if (type == 5 || type == 6 || type == 7) { while ((nulchk(buf,&trail) == 0) && s+1 <= e && 0 < (n = read(fd,buf,BUFSIZ))) { if (prbl && !((s+1)%100)) errfmt("\rBLOCK NUMBER %+06o (%+06i.)\r",s+1,s+1); cpybuf(prvbuf,buf,BUFSIZ); s++; oneovr = YES; } } } if (!prcr) { if (prbl) { putfmt("\n\nBLOCK NUMBER %+06o (%+06i.)\n\n",s,s); } for (i=0;i= 040 && buf[i] < 0177 || buf[i] == 011 /* HT */ || buf[i] == 012 /* LF */ || buf[i] == 015) /* CR */ putfmt("%ac",buf[i]); else if (buf[i] == 000) /* NL */ ; else if (buf[i] == 013) /* VT */ putfmt("\033(0i\n\033(B"); else if (buf[i] == 014) /* FF */ putfmt("\033(0c\n\033(B"); else if (buf[i] == 0177) /* DL */ ; else /* other control code */ { ch = buf[i] + 0100; putfmt("^%ac",ch); } putch(-1); } } cpybuf(prvbuf,buf,BUFSIZ); s++; oneovr = YES; } if (oneovr) s--; if (prcr && prv) { nulchk(prvbuf,&trail); putfmt("CREATE Z%+03i.%p/ALLOC:%+05i./START:%+05i. !Number of trailing nulls: %+03i\n", filnum++,prvtyp,s-prvs,prvs,trail); putch(-1); } if (prcr && prbl) { errfmt("\rBLOCK NUMBER %+06o (%+06i.)\n", s,s); } else if (!prcr) putfmt("\n"); close(fd); exit(YES); } typsav(buf) TEXT buf[]; { /* Test for first block of .SAV */ for (i=0;i<040;i++) if (buf[i]) return(NO); for (i=060;i<0360;i++) if (buf[i]) return(NO); for (i=0400;i<01000;i++) if (buf[i]) return(NO); if (!buf[041] || !buf[043] || !buf[0360]) return(NO); return(YES); } typvol(buf) unsigned char buf[]; { /* Test for first block of .ARC */ for (i=0100;i<0200;i++) if (buf[i]) return(NO); for (i=0500;i<0600;i++) if (buf[i]) return(NO); if (buf[0] == 0240 && buf[1] == 0) return(YES); else return(NO); } typlib(buf) TEXT buf[]; { /* Test for first block of .OBJ library*/ if (buf[0] != 001 || buf[1] != 0 || buf[2] != 042 || buf[3] != 0 || buf[4] != 007 || buf[5] != 0) return(NO); return(YES); } typobj(buf) TEXT buf[]; { /* Test for first block of .OBJ */ if (buf[0] != 001 || buf[1] != 0 || buf[2] != 056 || buf[3] != 0) return(NO); return(YES); } typc(buf) TEXT buf[]; { /* Test for first block of .C */ if ((buf[0] == '#' && (buf[1] == 'i' || buf[1] == 'd')) || (buf[0] == '/' && buf[1] == '*')) { if (nulchk(buf,&trail) <= 1) return(YES); else return(NO); } else return(NO); } typmac(buf) TEXT buf[]; { /* Test for first block of .MAC */ if (buf[0] == ';' && (buf[1] == '\r' || buf[1] == '\011' || buf[1] == ' ') || buf[0] == '.' && buf[1] == 'T' && buf[2] == 'I' || buf[0] == '\011' && buf[1] == '.' && buf[2] == 'T' && buf[3] == 'I') { if (nulchk(buf,&trail) <= 1) return(YES); else return(NO); } else return(NO); } typtxt(buf) TEXT buf[]; { /* Test for block of text */ if ((nulchk(buf,&trail)) <= 1) { j = 0; for (i=0;i 016 && buf[i] < 033) || (buf[i] > 033 && buf[i] < 040) || buf[i] > 0176) j++; } if (j > 5) /* Tolerence of 5 weird chars per text blk */ return(NO); else return(YES); } else return(NO); } nulchk(buf,ptrail) TEXT buf[]; COUNT *ptrail; { for (i=BUFSIZ;i>0;i--) { if (buf[i-1]) break; } *ptrail = BUFSIZ-i; if (!i) return(2); /* All Nulls */ for (j=i;j>0;j--) { if (!buf[j-1]) break; } if (!j) { if (i == BUFSIZ) return(0); /* No Nulls */ else return(1); /* Trail Nulls */ } else return (3); /* Embedded Nulls */ }