diff --git a/SEL32/taptools/README.md b/SEL32/taptools/README.md new file mode 100644 index 0000000..c3d1171 --- /dev/null +++ b/SEL32/taptools/README.md @@ -0,0 +1,171 @@ +This directory contains several utilites to work with .tap metadata +files used by the simh simulators. Some of these would be usable +for any simulator, not just the SEL32 simulator. General use MPX +utilities are also attached that help with file format conversion +between MPX and UNIX files. + +Users should create the directories /system and /system/bin to hold +the utilities. The directories should be world readable/writable. +chmod 777 /system /system/bin +The following two lines should be added to your ~/.bashrc so you +will be able to execute the utilities from anywhere: +PATH=$PATH:/system/bin +export PATH +You can test to see if correct by typing 'echo $PATH' and you +should get a response with /system/bin in the directory list. + +Compile and install the utilities by typing 'make install' to +install utilities into the /system/bin directory. + + +cutostap - This program scans a metadata .tap file and copies files + until an EOF is found. This program is used to remove + the sdt image from a .tap file to be used in another + .tap sdt image. The mkfmcopy can be used to create a + user sdt tape with files following the sdt image. + command filelist stdout + input - stdin file to be written with sdt image + +diskload - This program reads an MPX load module and stores it into + simulated diskfile. The MPX-1.x SMD entry for the file + is entered into the SMD for the file. Will not work for + MPX 3.x file systems. + command: diskload -la program diskfile + option -a - add filename to diskfile + option -l - list files in diskfile SMD, ignore filename + input - filename - file to copy to system disk + - diskfile - simulated system disk + output - modified system disk + +filelist - This program scans a metadata .tap file and prints the + file count and sizes. Used to determine the file + format contained in the metadata .tap file. + command filelist stdout + input - stdin stdout + input - file.tap file to dump + output - stdout filelist and sizes + output - directory/files extracted to current directory + +sdtfmgrcopy - This program reads a MPX 1.x filemgr save tape or a + user SDT followed by filemgr saves. The filemgr tape + must contain a filemgr save image with 4608 byte records. + A sdt tape starts with a 1920 byte record followed by + multiple 768 byte records to finish the sdt system image. + A sdt tape can be followed by one or more filemgr save + images of 4608 bytes. The boot image is put into bootfile1 + in the current directory. The program will create a + directory in the current directory for each different + username. A null username will be the system directory. + Within each directory each file contained on the tape is + extracted and written as binary data to the named file. + The .tap file MUST be a filemgr save tape and not a + MPX 3.x volmgr save tape. + command sdtfmgrcopy file.tap >stdout + input - file.tap file to dump + output - stdout filelist and sizes + output - if tape contains a sdt image, it will be output + to the file bootfil1 + output - directory/files extracted to current directory + +tapdump - This program reads a metadata .tap file and prints a side + by side hexdump of the file contents. The records are + displayed as 256 byte chuncks. After each record if 256 + bytes are displayed, hitting will continue dump, + hitting will terminate the display, and hitting + will skip to the next file on the simulated tape. + command tapdump stdout + input - stdin stdout + input - file.tap file to scan + output - stdout filelist and sizes + +volmcopy - This program reads a MPX 3.x volmgrr save tape. The tape + must contain a volmgr save image with 6144 byte records + containing a list of saved files. Followed by directdory + entries of 1536 bytes and finally file data of 1 to 8 768 + byte records. Files larger than 6144 bytes will be output + as modulo 6144 bytes. There is an EOF after each file + definition. The program will create a directory in the + current directory for each different directory. Within + each directory each file contained on the tape is extracted + and written as binary data to the named file. The .tap + file MUST be a volmgr save tape and not a MPX-1.x SDT/save + tape. + command fmgrcopy file.tap >stdout + input - file.tap file to dump + output - stdout filelist and sizes + output - directory/files extracted to current directory + +General utilities for MPX + +ddump - Create a sys by side ascii dump of a file. Same operation + as the DDUMP utility in MPX. 256 bytes are displayed at + a time. Hitting will continue to next 256 bytes. A + hex address can be input to display data at a given offset + in the file. Optionall, the file data can be modified. + command - ddump -r filename + option - -r means open file read only + input - filename file to read + output - side by size ascii dump of file + +deblk - read and convert mpx blocked ifile to unblocked unix file + format. Compressed and uncompressed files records can be + read. Output is an ascii string with '\n' termination. + command - deblk [filename] + input - filename or if non specified, stdin + output - ascii sting to stdout + +mpxblk - Create an MPX blocked file from a '\n' terminated ascii + character string file. Trailing blanks are not deleted + from the source file. Max line size is 254 bytes. + command - mpxblk fileout + input - read ascii file from stdin + output - write mpx blocked file to stdout + +renum - Create a numbered file from a '\n' terminated ascii file. + The input file is assumed to be a standard unix file. The + input lines are truncated or expaned to lines of 72 chars. + A line number in the form of XXXX.000 are appended to + create 80 char '\n' terminated lines. + command - renum fileout + input - read ascii file from stdin + output - write numbered ascii file to stdout + +small - Remove line numbers and trailing blanks from an ascii '\n' + terminated file. Lines are terminated at 72 chars and then + stripped of trailing blanks. Output is '\n' terminated + ascii files. + command - small fileout + input - read ascii file from stdin + output - write stripped ascii file to stdout + diff --git a/SEL32/taptools/cutostap.c b/SEL32/taptools/cutostap.c new file mode 100644 index 0000000..64a544f --- /dev/null +++ b/SEL32/taptools/cutostap.c @@ -0,0 +1,213 @@ +/* + * cutostap.c + * + * This program scans a metatape file and copies files until EOF is found. + * This program has the net effect of removing the sdt image from a file. + * The program will make sure 2 eof's and 1 eom are written to the tape. + * input - specified filename + * output - specified filename + */ + +#include +#include +#include +#include +#include +#include + +int filen = 1; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int oldsize, newsize; +FILE *outfp; +int inp; +int ln; + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int32_t n1, n2, hc, tc, n; + + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)4); + if (n1 <= 0) { + hc = -1; /* at EOM on disk file */ + return hc; /* return EOM */ + } + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) { /* check for garbage, assume EOF */ + hc = -1; /* at EOM on disk file */ + return hc; /* return EOM */ + } + + /* check for EOF & EOM on tape data */ + if (hc == 0) { + /* we are at tape EOF */ + if (++EOFcnt < 2) /* if 1st EOF, print file info */ + { + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + fprintf(stderr, "file %d: EOF after %d records: %d bytes\n\n", filen, count, size); + filen++; /* set next file number */ + } + else + { + fprintf(stderr, "second EOF after %d files: %d bytes\n", filen-1, tsize+size); + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + return 0; /* return EOF on tape data */ + } + + /* check for EOM */ + if (hc == -1) { + return -1; /* at EOM on disk file */ + } + + /* read the data */ + n = read(inp, s, (size_t)hc); + if (n <= 0) + return -1; /* at EOM on disk file */ + + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)4); + if (n2 <= 0) + return -1; /* at EOM on disk file */ + + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) + { + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +void putrec(int cnt, char *buf) +{ + int32_t n1, n2, nw; + int32_t hc = (cnt + 1) & ~1; /* make byte count even */ + +//printf("writing %d chars\n", cnt); + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&hc), (size_t)1, (size_t)4, outfp); + /* write the data mod 2 */ + nw = fwrite((char *)buf, (size_t)1, (size_t)hc, outfp); + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&hc), (size_t)1, (size_t)4, outfp); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "write (%d) failure\n", nw); + fprintf(stderr, "Operation aborted\n"); + fclose(outfp); + close(inp); + free(buf); + exit(1); + } +} + +int main (int argc, char *argv[]) +{ + char *buf; + size_t buf_size = 256 * 1024; + int ll, gotboth = 0; + int32_t zero = 0; + + if (argc != 3) { + fprintf(stderr, "usage: %s infile outfile\n", argv[0]); + exit(1); + } + + /* open input file */ + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + + close(inp); /* close input */ + outfp = fopen(argv[1],"r"); /* reopen */ + fseek(outfp, 0, SEEK_END); /* seek to end */ + oldsize = ftell(outfp); /* get filesize in bytes */ + fclose(outfp); /* now close it */ + + /* open input file */ + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + + /* open output file */ + outfp = fopen(argv[2],"w"); + if (outfp == NULL) { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[2]); + exit(1); + } + + /* init counts */ +// ln = -2; /* look for 2 eof */ + ln = -1; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + + /* get a 256k buffer */ + if ((buf = malloc(buf_size)) == NULL) { + fprintf(stderr, "Can't allocate memory for %s\n", argv[0]); + return (4); + } + + /* get buffers until eof */ +domore: + while ((ll=getloi(buf, buf_size)) > 0) { +//printf("got %d char\n", ll); + /* we have data to write */ + putrec(ll, buf); /* write the buffer */ + gotboth = 0; + } +//printf("we have EOF or EOM, DONE\n"); + /* We have EOM, see if EOF's needed */ + switch (gotboth) { + case 0: /* we have written no EOFs, so write two */ + fwrite((char *)(&zero), (size_t)1, (size_t)4, outfp); + /* drop through */ + case 1: /* we have written 1 EOF, so write one more */ + fwrite((char *)(&zero), (size_t)1, (size_t)4, outfp); + /* drop through */ + default: + case 2: /* we have written 2 EOFs, now do EOM */ + zero = -1; + fwrite((char *)(&zero), (size_t)1, (size_t)4, outfp); + } + fprintf(stderr, "EOM after 2 EOFs %d files: %d bytes\n", filen-1, tsize); + + newsize = ftell(outfp); /* get filesize in bytes */ + fprintf(stderr, "Size of file changed from %d to %d\n", oldsize, newsize); + + /* we done */ + fclose(outfp); + close(inp); + free(buf); + exit(0); +} diff --git a/SEL32/taptools/ddump.c b/SEL32/taptools/ddump.c new file mode 100644 index 0000000..178c9de --- /dev/null +++ b/SEL32/taptools/ddump.c @@ -0,0 +1,220 @@ +/* + ddump - file dump utility for listing files in side-by-side hex + and ascii, plus having the option to modify the file giving + a hexadecimal byte offset into the file and the hex data + which will be written to the supplied address. + Usage is: + + ddump file + + where: + + file1 is the file to dump and/or modify. + + written by Rick Beery + modified many times by Jim Bevier + + The program fd.c written by M. Kraieski has been incorporated + into this program. + +*/ + +#include +#include +#include + +void dodump(); +int modify(); +void modify_file(); + +int main(argc,args) +int argc; +char *args[]; +{ + FILE *fp, *fopen(); + int i; + char *tempstring; + + if ((argc < 2) || (argc > 3)) { + printf("usage: %s [-r] file\n", args[0]); + printf(" -r uses read-only mode\n"); + exit(1); + } /* end of if */ + + if (argc == 3) +#ifdef mpx + /* open read and unblocked */ + if (strcmp("-r",args[1]) == 0) fp = fopen(args[2],"ru"); +#else + if (strcmp("-r",args[1]) == 0) fp = fopen(args[2],"r"); +#endif + else { + printf("Invalid option %s ignored\n", args[1]); +#ifdef mpx + /* open read/write unblocked */ + fp = fopen(args[2],"r+u"); +#else + fp = fopen(args[2],"r+"); +#endif + } +#ifdef mpx + /* open read/write unblocked */ + else fp = fopen(args[1],"r+u"); +#else + else fp = fopen(args[1],"r+"); +#endif + + if (fp == NULL) { + fprintf(stderr,"%s: fopen: unable to open file %s\n", args[0], args[1]); + exit(1); + } /* end of if */ + dodump(fp,0); + fclose(fp); +} /* end of main */ + +#define PRINTABLE(x) ((x < 32) || (x > 126)) ? '.' : x + +void dodump(fp, fileadr) +FILE *fp; +int fileadr; +{ + char buff[257]; + int file_byte_count=0, curchar, buffptr, bufflen; + + buffptr = 0; + bufflen = 16; + + fseek(fp,fileadr,0); + while ((curchar = getc(fp)) != EOF) { + file_byte_count++; + if (!buffptr) printf(" %06x : ",fileadr); + printf("%02x",curchar); + buff[buffptr++] = PRINTABLE(curchar); + if (!(buffptr % 4)) printf(" "); + if (buffptr >= bufflen) { + buff[buffptr] = 0; + printf(" |%s|\n",buff); + buffptr = 0; + fileadr += bufflen; + if (!(file_byte_count % 256)) { + modify_file(fp); + } /* end of if */ + } /* end of if */ + } /* end of while */ + + if (buffptr) { + buff[buffptr] = 0; + while (buffptr++ < bufflen) { + printf(" "); + if (!(buffptr % 4)) printf(" "); + } /* end of while */ + printf(" |%s|\n",buff); + } /* end of if */ + modify_file(fp); + return; +} /* end of dodump */ + +int modify(fp1) + FILE *fp1; +{ + char hexstring[33]; + int num_chars, digit, i, byte=0, stat, file_offset=0, indx=0; + int power(); + void gethex_string(); + int asciihex_digit_to_decimal(); + + gethex_string(hexstring); + num_chars = strlen(hexstring); + for (i=num_chars-1; i>=0; i--) { + digit = asciihex_digit_to_decimal(hexstring[indx++]); + file_offset += digit*power(16,i); + } /* end of for */ + if ((fseek(fp1,file_offset,0)) != -1) { + /* read characters from the terminal */ + printf("\nenter new hex data > "); + gethex_string(hexstring); + num_chars = strlen(hexstring); + + /* convert character to numeric field and + new set of data at offset in file specified */ + for (i=0; i='0' && c<='9') || (c>='a' && c<='f')) + hex[indx++] = c; + else { + while ((c=getchar()) != '\n' ); + indx = 0; + printf("Invalid hex number; please re-enter > "); + } + } + hex[indx] = '\0'; +} /* end of gethex_string */ + +int asciihex_digit_to_decimal(c) + char c; +{ + int digit; + + if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; + else if (c>= '0' && c <= '9') digit = c -'0'; + else digit = -1; /* error */ + return(digit); +} /* end of asciihex_digit_to_decimal */ + +int power(x,n) + int x, n; +{ + int p; + + for (p=1; n>0; --n) + p = p*x; + return (p); +} /* end of routine power */ + +void modify_file(fp) + FILE *fp; +{ + int ans, modify(),modified_addr; + + printf("\n hex address, - continue, q = quit > "); + ans = getchar(); + if ((ans>='0' && ans<='9') || (ans>='a' && ans<='f')) { + ungetc(ans, stdin); + modified_addr = modify(fp); + printf("\n"); + dodump(fp, (modified_addr/256)*256); + } /* end of "if" part of if - then */ + else { + if (ans == 'q') { + fclose(fp); + exit(1); + } + else { + if (ans != '\n') while ((ans=getchar()) != '\n' ); + } + } /* end of if -then */ +} /* end of modify_file */ diff --git a/SEL32/taptools/deblk.c b/SEL32/taptools/deblk.c new file mode 100644 index 0000000..a9f9ad8 --- /dev/null +++ b/SEL32/taptools/deblk.c @@ -0,0 +1,603 @@ +/* + * deblk.c + * + * This program reads MPX blocked and/or MPX compressed files and + * deblocks blocked files and uncompresses compressed files and + * deletes trailing blanks from a source file. The program will + * also process standard ASCII newline ('\n') terminated files. + * input - stdin / filename + * output - stdout + */ + +/* + * MPX blocked file format + * bytes 0-1 - not used and are zero + * bytes 2-3 - next record position in buffer + * byte 4 - start/end of block flag + * - 0x20 - EOB end of block + * - 0x40 - BOB start of block + * byte 5 - last record byte count + * byte 6 - this blocks flags + * - 0x00 - valid data + * - 0x20 - EOB end of block + * - 0x80 - EOF end of file + * - 0xa0 - EOB/EOF end of file + * byte 7 - bytes in this record + * data byte - cnt data bytes + * byte cnt+4- 0x20 EOB status + * byte cnt+5- last record count + */ + +/* + * Compressed record + * byte 0 - 0xbf -> start of record + * 0x9f -> start of next record + * byte 1 - record count + * byte 2 - high order byte of 16 bit checksum + * byte 3 - low order byte of 16 bit checksum + * + */ + +/* +* +* AN O.S. COMPRESSED RECORD CONSISTS OF 120 BYTES: +* +* 6 CONTROL BYTES AND 114 BYTES OF COMPRESSED SOURCE +* +* (THE LAST RECORD CAN BE LESS THAN 120 BYTES, ON THAT +* RECORD THE COMPRESSED SOURCE WILL BE FROM 4-114 BYTES). +* +* 6 CONTROL BYTES +* +* 1 BYTE- DATA TYPE CODE BF OR 9F (9F MEANS THIS IS LAST RECORD) +* 1 BYTE- SIZE OF COMPRESSED RECORD (- 6 FOR CONTROL BYTES) +* (USUALLY 114 (72(X)) IS THE SIZE EXCEPT LAST RECORD) +* 2 BYTE- CHECKSUM +* 2 BYTE- RECORD SEQUENCE NUMBER (STARTING FROM ZERO) +* +* 4-114 BYTES OF ONE OR MORE GROUPS OF COMPRESSED SOURCE AS FOLLOWS: +* +* A COMPRESSED GROUP CONSISTS OF: +* A BLANK COUNT BYTE, A DATA COUNT BYTE, DATA +* +* COMPRESSED GROUPS ARE REPEATED AND TERMINATED BY AN FF CHAR. +* COMPRESSED GROUPS ARE USUALLY TERMINATED AT 114 CHARS BY +* THE FF CHAR UNLESS THIS IS THE LAST RECORD IN THE FILE +* +* A LINE OF TEXT USUALLY IS COMPRESSED AS FOLLOWS: +* A BLANK COUNT BYTE, A DATA COUNT BYTE, COMPRESSED DATA +* (ONE OR MORE OF THESE COMPRESSED GROUPS FOR UP TO 72 CHARS OF SOURCE) +* FOLLOWED BY A BLANK COUNT BYTE,A DATA COUNT BYTE (OF 8), +* DATA (8 CHAR SEQUENCE NUMBER), TERMINATED BY A FF CHAR +* +* A WORKFILE LOGICAL COMPRESSED LINE IS SIMILIAR TO THE O.S. +* LOGICAL COMPRESSED LINE EXCEPT THAT AN 8 CHAR SEQUENCE NUMBER +* ALWAYS EXISTS IN THE WORKFILE FORMAT AND IT IS ALWAYS FIRST +* RATHER THAN AT THE END OF THE RECORD (IF SEQUENCE NUMBERS DID +* NOT EXIST IN COLUMNS 73-80 IN THE O.S. ORIGINAL COMPRESSED +* RECORDS THAN THE EDITOR GENERATES THEM). PRECEDING THE WORKFILE +* COMPRESSED RECORD IS A 2 BYTE PREVIOUS RECORD IN THE PAGE POINTER. +* ALSO NOTE THAT WORKFILES ARE NOT BLOCKED BY THE O.S., BUT HAVE +* THEIR OWN STRUCTURE OF HEADERS, DATA SPACE, AND FREE SPACE. +* +* IF THE SEQUENCE NUMBER DOES NOT EXIST OR THE PERIOD IS NOT IN +* THE PROPER PLACE (NNNN.NNN) OR THE SEQUENCE NUMBER CONTAINS +* ANYTHING OTHER THAN NUMBERS, THEN THE EDITOR WILL GENERATE +* ITS OWN SEQUENCE NUMBER +* +* THE FIRST BLANK COUNT CAN RANGE FROM 0-80 BLANK CHARS +* SUBSEQUENT BLANK COUNTS CAN RANGE FROM 3-79 MAX. THAT IS +* SINCE IT TAKES 2 BYTES TO DO BLANK COMPRESSION (A BLANK COUNT +* AND A DATA COUNT), ONLY 3 OR MORE BLANK CHARS AFTER THE FIRST +* NON-BLANK CHAR IN A LINE ARE COMPRESSED. +* RECORDS TO BE COMPRESSED ARE ASSUMED TO BE 80 CHARS OR LESS +* (INCLUDING AN 8 CHAR SEQUENCE NUMBER). +* +* THE CHECKSUM IS SIMPLY THE ADDITION OF ALL THE 120 CHARS IN THE +* COMPRESSED RECORD EXCEPT FOR THE 6 CONTROL BYTES +* +* THE SMALLEST COMPRESSED LINE CONSISTS OF 14 CHARS : +* A BLANK COUNT BYTE (OF 71), A DATA COUNT BYTE (OF 8), +* DATA (AN 8 CHAR SEQUENCE NUMBER, A BLANK COUNT BYTE (OF ZERO), +* A DATA COUNT BYTE (OF 1), DATA (ONE CHAR), AND AN FF TERMINATOR +* COMPRESSED RECORD FORMAT CAN BE PROCESSED ONLY BY THE FOLLOWING: +* +* ASSEMBLER,P4,SOURCE UPDATE,EDITOR AND SOME FUNCTIONS OF MEDIA +* AND OF COURSE SOME UTILITY PROGRAMS LIKE FLIP. +* +* NOTE THAT A TEXT LINE CAN BE SPREAD ACROSS SEVERAL COMPRESSED +* RECORDS. +*/ + +#include +#include +#include + +#define BLKSIZE 768 /* MPX block file sector size */ +extern int rbl(); +extern int getloi(); /* right from my mind */ +extern int putloi(); /* write line */ + +/* read file and output to stdout */ +int main(argc, argv) +int argc; +char *argv[]; +{ + FILE *fp, *fopen(); + unsigned char s[BUFSIZ]; + + if(argc == 1) /* no args; copy std in */ + { + while (1) { + if (rbl(stdin, s, BUFSIZ) <= 0) /* read til EOF */ + exit(0); + putloi(s); + } + } else { + while (--argc > 0) + if ((fp = fopen(*++argv, "r")) == NULL) { + fprintf(stderr, "list: can't open %s\n", *argv); + exit(1); + } else { + while (1) { + if (rbl(fp, s, BUFSIZ) <= 0) /* read til EOF */ + exit(0); + putloi(s); + } + fclose(fp); + } + } + exit(0); +} + +/* + * This function computes and checks the checksum of a compressed file + */ +int checksum(buf) +char *buf; +{ + int i = 0; +// unsigned int ccs = 0; /*zero checksum */ + short int ccs = 0; /*zero checksum */ + unsigned int rcs = (((buf[2] << 8) & 0xff00) | (buf[3] & 0xff)); /* get checksum */ + int cnt = buf[1]; /* record count */ +// fprintf(stderr, "checksum data %x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); + + while (cnt > 0) { +// unsigned int v = buf[i+6]; + short v = buf[i+6] & 0xff; + ccs += v; /* add the byte */ +// fprintf(stderr, "checksum cnt %x val %x sum %x\n", i, v, ccs); + i++; /* bump address */ + cnt--; /* reduce count */ + } +// fprintf(stderr, "checksum size %x read %x calc %x\n", buf[1], rcs, ccs); + if (ccs == rcs) + return 0; /* return OK */ + return 1; /* return error */ +} + +int bin = 0; +unsigned char si[BLKSIZE]; +unsigned char bi[BLKSIZE]; +int ubdp = 0; /* unblocked data pointer */ +int ubdc = 0; /* unblocked data count */ +int bdp = 0; /* blocked data pointer */ +int bdc = 0; /* blocked data count */ +short filetype = 0; + +#define unknown 0x00 +#define blocked 0x01 +#define compress 0x02 +#define ascii 0x04 + +/* + * This function reads MPX blocked files + */ +int readbb(fp, ip, cnt) +FILE *fp; +char *ip; +int cnt; +{ + int c; + int i = 0; + + if (bin == 0) { +//fprintf(stderr, "read sector a\n"); + if (fread(si, 1, BLKSIZE, fp) <= 0) + return (0); /* this means eof */ + bin = 6; + } + /* check for EOF */ + if (si[bin] & 0x80) { + bin = 0; + return(0); /* we have EOF */ + } + /* check for EOB in last record */ + if (si[bin - 2] & 0x20) { +//fprintf(stderr, "read sector b\n"); + if (fread(si, 1, BLKSIZE, fp) <= 0) + return (0); /* this means eof */ + bin = 6; + } +//fprintf(stderr, "copy block from sector @ bin %x\n", bin); + /* copy the block into users buffer */ + if ((c = si[bin+1]) > 0) { + for (i = 0; i < c; i++) { + ip[i] = si[bin + 2 + i]; + if (i >= cnt) + break; + } + bin += (c + 4); + ip[i] = '\0'; + return (i); + } + bin = 0; + return (i); +} + +/* function to read a byte from an unblocked file */ +int getb(fp) +FILE *fp; +{ + int c; + + /* file is unblocked, get next record */ + if (ubdp >= ubdc) { /* is count exhausted */ + /* need to read next block, if not first time */ + /* we need a new buffer */ + /* read in 768 byte block of the file */ + if ((ubdc = fread(si, 1, BLKSIZE, fp)) <= 0) + return (-1); /* this means eof */ +//fprintf(stderr, "getb - read unblocked file ubdc=%x\n", ubdc); + ubdp = 0; + } + c = si[ubdp++] & 0xff; /* copy char */ + return (c); +} + +/* get a line of input */ +int getloi(fp, s, lim) /* right from my mind */ +FILE *fp; +unsigned char s[]; +int lim; +{ + int c, i, cc, rc = 0; + + /* see how we are to process data */ + if (filetype & blocked) { + /* file is blocked, get next record */ + if (bdp == 0) { + /* we need a new buffer */ +newbuf: + if ((bdc = readbb(fp, bi, lim)) <= 0) + return (0); /* this means eof */ +//fprintf(stderr, "getloi read blocked file %x\n", bdc); + bdp = 0; + } + /* check for compressed data */ + if (filetype & compress) { + if ((bi[bdp] & 0x9f) != 0x9f) { + fprintf(stderr, "blocked compressed file read error %x\n", bi[bdp]); + return (0); /* this means error */ + } + /* checksum the record */ + if (checksum(&bi[bdp])) { + fprintf(stderr, "blocked compressed file checksum error\n"); + return (0); /* this means error */ + } +//fprintf(stderr, "getloi blocked compressed file checksum OK @ %x cnt %x\n", bdp, bdc); + /* copy in the next record */ + /* get chars until EOF or limit reached */ + cc = bi[bdp+1]+6; /* get count */ + for (i = 0; (--lim > 0) && (i < cc); i++) { + s[rc++] = bi[bdp++]; /* copy char */ + } + if ((bdp >= bdc) || (i == cc)) { + bdp = 0; /* read new buffer next time */ +//fprintf(stderr, "getloi blocked compressed read return %x bdc %x bdp %x\n", rc, bdc, bdp); + } + return (rc); /* return data count */ + } + /* file is uncompressed, so copy MPX records */ +//fprintf(stderr, "getloi blocked data rc=%x bdc=%x\n", rc, bdc); + for (i=0; i 0) && ((c = getchar()) != EOF)) { + if ((i >= 6) && ((c == 0xbf) || (c == 0x9f))) + { + ungetc(c, stdin); + return (i); + } + s[i++] = c; + if ((*s != 0xbf) && (*s != 0x9f)) + { + if (c == '\n') + { + if ((s[i - 1] == '\n') && (i > 1)) + { + while ((s[i - 2] == ' ') && (i > 1)) + --i; + s[i - 1] = '\n'; + } + s[i] = '\0'; + return (i); + } + } + } +#ifdef JUNK + for (i = 0; --lim > 0 && (c = getchar()) != EOF && (s[i++] = c) != '\n';); + if ((s[i - 1] == '\n') && (i > 1)) + { + while ((s[i - 2] == ' ') && (i > 1)) + --i; + s[i - 1] = '\n'; + } + s[i] = '\0'; +#endif + return (i); +#endif +} + +/* + ** output line of text from the source + */ +int putloi(s) +unsigned char *s; +{ + printf("%s", s); +} + +unsigned char line[BUFSIZ]; +int cmpop = 0; +int cmpflg = 0; +int bcnt = 0; +unsigned char *bptr = 0; +int binary = 1; +int recl = 0; +int ubin = 0; + +/* read lines of data from the source file */ +/* files can be blocked w/wo compression */ +/* files can be blocked ascii */ +/* files can be byte strings, newline terminated */ +int rbl(fp, buf, n) +FILE *fp; +unsigned char *buf; +int n; +{ + register int count = 0; + register unsigned char *cp; + int i; + unsigned char *linadrs = line; + + if (filetype == unknown) /* see if we know type of file to read */ + { + bin = 0; + ubin = 0; + bdp = 0; + bdc = 0; + ubdp = 0; + ubdc = 0; + /* read in 1st 768 Byte block of the file */ + if ((ubdc = fread(si, 1, BLKSIZE, fp)) <= 0) + return (0); /* this means eof */ + /* test 1st byte for 0x06 and bytes 2, 3, and 4 zero */ + if ((si[0] == 0x06) && (si[1] == 0) && (si[2] == 0) && (si[3] == 0)) { + /* we have a library file, giver error and abort */ + fprintf(stderr, "deblk - Cannot list library file, aborting\n"); + return (0); /* this means error exit */ + } + /* test for a directory file, 8 ascii char then 4 zeros */ + if ((si[8] == 0) && (si[9] == 0) && (si[10] == 0) && (si[11] == 0)) { + for (i=0; i<8; i++) { + if (!isprint(si[i])) { + /* unknown file type, abort */ + fprintf(stderr, "deblk - Unknown binary file type, aborting\n"); + return (0); /* this means error exit */ + } + } + /* must be directory, abort */ + fprintf(stderr, "deblk - Cannot list directory file, aborting\n"); + return (0); /* this means error exit */ + } + i = ((si[2] << 8) & 0xff00) | (si[3] & 0xff); /* get file offset pointer, bytes 2 & 3 */ + /* test 1st 2 byte of file for zero */ + if ((si[0] == 0) && (si[1] == 0) && (i < BLKSIZE)) { + /* most likely blocked file if 1st 2 bytes 0 and next 2 bytes are less than 768 */ + filetype |= blocked; /* we have blocked file */ + bin = 6; /* where we start for data block */ + + /* see if we have compressed data */ + if ((si[bin + 2] == 0xbf) || (si[bin + 2] == 0x9f)) + { + filetype |= compress; /* data is compressed */ + bcnt = 0; /* no data in buffer */ + } + else + { + /* data is not compressed, just ascii without newlines */ + filetype |= ascii; /* blocked ascii data */ + } + } + else + { + /* data is unblocked, see if compressed or not */ + if ((si[ubin] == 0xbf) || (si[ubin] == 0x9f)) + { + filetype |= compress; /* data is compressed */ + bcnt = 0; /* no data in buffer */ + } + else + if ((si[ubin] == 0xef) || (si[ubin] == 0xcf)) + { + /* file is an macro library, so abort */ + fprintf(stderr, "deblk - Cannot list macro library file, aborting\n"); + return (0); /* this means error exit */ + } + else + { + /* data is not compressed or blocked, just ascii with newlines */ + filetype |= ascii; /* blocked ascii data */ + } + } + } + if ((filetype & compress) && !cmpop) { /* see if we tested for compressed */ + cmpop = 1; /* set comp tested flag */ + /* read in the first record */ + if ((recl = getloi(fp, line, BUFSIZ)) == 0) + return (0); /* this means eof */ + linadrs = line; + if (*linadrs == 0xbf) + { /* is this file compressed */ + cmpflg = 1; /* set comp data flag */ + bcnt = linadrs[1]; /* set record count */ + bptr = &linadrs[6]; /* set data address */ +//fprintf(stderr, "rbl - read 1st compressed record cnt %x %x\n", bcnt, linadrs[0]); + } + else + goto re00; + } + + if (cmpflg) { /* reading compressed data? */ + if (bcnt == 0) { /* any data left in buffer */ + re18: + /* read in a data record */ + if ((recl = getloi(fp, line, BUFSIZ)) == 0) + return (0); /* this means eof */ + linadrs = line; +//fprintf(stderr, "rbl re18 - read compressed record cnt %x %x\n", bcnt, linadrs[0]); + if ((*linadrs & 0x9f) != 0x9f) /* is this valid rec */ + return (EOF); /* error if not */ + bcnt = linadrs[1]; /* set record count */ + bptr = &linadrs[6]; /* set data address */ +//fprintf(stderr, "rbl - read nth compressed record cnt %x %x\n", bcnt, linadrs[0]); + } + re20: + /* see if any blanks */ + if (i = *bptr++) { /* next buffer pointer */ + if (i == 0xff) + goto re60; /* if eol, get out */ + while (i--) { + if (count < n) { + *buf++ = ' '; /* put blank in buffer */ + count++; + } + } + } + if (--bcnt <= 0) + goto re18; /* read next record */ + + /* get character count */ + if (i = *bptr++) { /* next buffer pointer */ + while (i--) { + if (count < n) + *buf++ = *bptr; /* put char in buffer */ + bcnt--; /* decr count */ + bptr++; /* next buffer pointer */ + count++; + } + } + if (--bcnt <= 0) + goto re18; /* read next record */ + goto re20; + + re60: + bcnt--; /* decr count */ + if ((*--buf == ' ') && (count == 1)) { + *buf = '\n'; /* put new line at eol */ + } + else { + *++buf = '\n'; /* put new line at eol */ + count++; + } + } + else { + /* non compressed read here */ + /* read the next record */ + if ((recl = getloi(fp, line, BUFSIZ)) == 0) + return (0); /* this means eof */ + linadrs = line; /* reset line pointer */ + + re00: +//fprintf(stderr, "rbl - read nth uncompressed record cnt %x %s\n", recl, line); +#if 0 + /* here we need to strip off blank put in during write */ + /* this is because mpx does not support zero length blocks */ + if ((recl == 1) && (*linadrs == ' ')) { + recl = 0; + /* now append new line to end of buffer */ + if (!binary) + line[recl] = '\n'; + } +#endif + count = 0; + /* copy this layer buffer to upper caller's buffer */ + while ((count < n) && (count < recl)) { + buf[count] = line[count]; + count++; + } + /* if no newline, add one and null terminate */ + if (line[count-1] != '\n') + buf[count++] = '\n'; + buf[count] = '\0'; + } +//fprintf(stderr, "rbl - read return cnt %x %s\n", count, line); + return (count); +} diff --git a/SEL32/taptools/diskload.c b/SEL32/taptools/diskload.c new file mode 100644 index 0000000..560f321 --- /dev/null +++ b/SEL32/taptools/diskload.c @@ -0,0 +1,357 @@ +/* + * diskload.c + * + * This program reads an MPX load module and stores it into the + * sumulated diskfile. The SMD entry is changed to reflect the + * new file entry. + * input - filename + * - simulated diskfile + * output - modified diskfile with SMD entry modified + * 08/11/2018 + */ + +#include +#include +#include + +#define BLKSIZE 768 /* MPX file sector size */ +unsigned char os[BLKSIZE * 100]; /* O/S code */ + +/* read program file and output to simulated mpx1.x diskfile using filemgr format */ +/* dload file diskfile */ +int main(argc, argv) +int argc; +char *argv[]; +{ + FILE *fp, *dp, *fopen(); + unsigned char si[BUFSIZ]; + char *p; + int i, j; +#define DOLIST 1 +#define DOADD 2 + unsigned int option = DOLIST; /* what to do */ + unsigned char *fnp; /* file name pointer */ + unsigned int size; /* size in 768 byte sectors */ + unsigned int word,tmp; /* just a temp word variable */ + unsigned char name[9]; /* LM name */ + unsigned int lmname[2], passwd[2]; + unsigned int smds; /* size of smd */ + unsigned int smdd[2]; /* SMD space definition */ + unsigned char *smd; + unsigned int hash1; /* SMD hash value for name */ + unsigned int udtp; /* UDT pointer */ + unsigned int *mptr; /* word ptr for SMD entries */ + unsigned int boff; + unsigned int rem; + unsigned int blk; + unsigned int lmblk; /* sector addess of load module on disk */ + unsigned int smdudt; /* smd udt index */ + unsigned int spau; /* sectors per allocation unit */ + unsigned int fileau; /* file size in allocation units */ + unsigned int auptr; /* pointer to allocation unit on disk */ + unsigned int lsblk; /* lowest block address of SMD entries */ + + if (argc <= 1) { /* see if correct # args */ +// fprintf(stderr, "Error: incorrect number of parameters\n"); + fprintf(stderr, "Usage: %s -la program diskfile\n", *argv); + exit(1); + } + if (--argc > 0) { + p = *++argv; +// printf("argv %s\n", p); + if (*p++ == '-') { + while (*p != '\0') { + switch (*p++) { + case 'l': + case 'L': + option |= DOLIST; + break; + case 'A': + case 'a': + option |= DOADD; + break; + default: +// fprintf(stderr, "Error: incorrect option %c specified\n", *--p); + fprintf(stderr, "Usage: %s -la program diskfile\n", *--argv); + exit(1); + break; + } + } + if (*--p == '-') { + fprintf(stderr, "Error: no option specified\n"); + fprintf(stderr, "Usage: %s -la program diskfile\n", *--argv); + exit(1); + } + } + else { + argc++; + argv--; + } + if (--argc > 0) { + p = *++argv; +// printf("argv2 %s\n", p); + if ((fp = fopen(*argv, "r")) == NULL) { + fprintf(stderr, "error: can't open load module %s\n", *argv); + exit(1); + } + fnp = *argv; /* get file name pointer */ + fseek(fp, 0, SEEK_END); /* seek to end */ + word = ftell(fp); /* get filesize in bytes */ + fseek(fp, 0, SEEK_SET); /* rewind file */ + } + } + if (--argc <= 0) { + fprintf(stderr, "Error: incorrect number of parameters\n"); + fprintf(stderr, "Usage: %s -la program diskfile\n", *argv); + exit(1); + } + /* open diskfile */ + if ((dp = fopen(*++argv, "r+")) == NULL) { + fprintf(stderr, "error: can't open disk file %s\n", *argv); + exit(1); + } + + /* determine size of file */ + size = word/BLKSIZE; /* get sector count */ + if ((word % BLKSIZE) != 0) + size++; /* add in 1 for partial sector */ + /* size now has load module size in sectors */ + /* we need the file name and password for entry */ + for (i=0; i<8; i++) + name[i] = 0x20; /* pre blank name */ + name[8] = '\0'; /* NULL terminate */ + for (i=0; (i<8) && (fnp[i] != 0); i++) + name[i] = toupper(fnp[i]); /* upper case name */ +// fprintf(stderr, "file %s is size %d sectors\n", name, size); + lmname[0] = (name[0] << 24) | (name[1] << 16) | (name[2] << 8) | (name[3]); + lmname[1] = (name[4] << 24) | (name[5] << 16) | (name[6] << 8) | (name[7]); + passwd[0] = passwd[1] = 0; /* no password */ + /* the disk data has the O/S starting at 0x780 in the file */ + /* add 0x780 to any O/S location you want to load */ + /* C.SMDS (#smd entries) is at 0xb00 + 0x780 = 0x1280 */ + /* read the O/S diskfile into buffer, 7680 bytes */ +// fprintf(stderr, "reading 100*BLKSIZE bytes from disk\n", 100*BLKSIZE); + if (fread(os, 1, BLKSIZE*100, dp) <= 0) + return (0); /* this means bad read */ + smds = (os[0x780+0xb00] << 24) | (os[0x780+0xb01] << 16) | (os[0x780+0xb02] << 8) | (os[0x780+0xb03]); + + /* get udt index for SMD location */ + smdudt = (os[0x780+0xc2c] << 8) | (os[0x780+0xc2d]); + /* udt size id 0x40, C.UDTA is at 0xb40 */ + word = (os[0x780+0xb40] << 24) | (os[0x780+0xb41] << 16) | (os[0x780+0xb42] << 8) | (os[0x780+0xb43]); + udtp = (smdudt * 0x40 + word); /* get udt address */ + /* spau is in byte 0x0f of udt */ + spau = os[0x780+udtp+0x0f] & 0xff; /* get word with spau */ + + /* get file size in au's */ + fileau = size / spau; /* get number of au's required for file */ + if ((size % spau) != 0) + fileau++; /* round up to next au of overflow */ + fprintf(stderr, "file %s is size %d sectors (%d au) requiring %d sectors on disk\n", + name, size, fileau, fileau*spau); +// fprintf(stderr, "UDTP 0x%x SPAU 0x%x\n", udtp, spau); /* display udtp & spau */ + fprintf(stderr, "C.SMDS(0xB00) - SMD size is 0x%x %d entries C.SMDUDT is %x\n", smds, smds, smdudt); + + /* get SMD space definition */ + smdd[0] = (os[0x780+0x840] << 24) | (os[0x780+0x841] << 16) | (os[0x780+0x842] << 8) | (os[0x780+0x843]); + smdd[1] = (os[0x780+0x844] << 24) | (os[0x780+0x845] << 16) | (os[0x780+0x846] << 8) | (os[0x780+0x847]); + fprintf(stderr, "C.SMDD(0x840) - SMD space definition wd0 0x%x wd1 0x%x wd0 %d wd1 %d entries %d\n", + smdd[0], smdd[1], smdd[0] ,smdd[1], smdd[1] * 24); + fprintf(stderr, "SMD space def: blk 0x%x seek 0x%x size 0x%x (%d)\n", + smdd[0], smdd[0]*BLKSIZE, smdd[1], smdd[1]); + + /* rewind the disk */ + fseek(dp, 0, 0); /* seek home */ + /* seek to the smd */ + fseek(dp, smdd[0]*BLKSIZE, 0); /* seek smd */ + if ((smd = (unsigned char *)malloc(smdd[1] * BLKSIZE)) < 0) + return (0); /* this means bad read */ + /* read the SMD into memory */ + if (fread(smd, 1, smdd[1]*BLKSIZE, dp) <= 0) + return (0); /* this means bad read */ + /* use lowest space definition from SMD entries */ + lsblk = smdd[0]; /* set lowest to start of SMD */ + /* loop through the SMD looking for a match to the load module name */ + for (i=0; i<(smds*32); i+=32) { + unsigned int sblk, len, udt, pw; + int yep = 0; + for (j=0; j<8; j++) { + if (smd[i+j] != 0) { + fprintf(stderr, "%c", smd[i+j]); + yep = 1; + } + } + if (yep) { + int bit; + unsigned int lmn[2]; /* load module name */ + + sblk = (smd[i+8] << 24) | (smd[i+9] << 16) | (smd[i+10] << 8) | (smd[i+11]); + if ((sblk & 0xffffff) < lsblk) + lsblk = sblk & 0xffffff;/* save the new lowest address */ + len = (smd[i+12] << 24) | (smd[i+13] << 16) | (smd[i+14] << 8) | (smd[i+15]); + pw = (smd[i+24] << 8) | (smd[i+25]); + udt = (smd[i+26] << 8) | (smd[i+27]); + + /* hash the name to see if pointer is to current SMD entry */ + mptr = (unsigned int *)smd; /* get word pointer for SMD data */ + j = i/32; /* offset in SMD file (entry #) */ + lmn[0] = mptr[j*8]; /* get filename first 4 chars to R5 and shift right circular by 1 */ + word = ((lmn[0] & 0xff) << 24) | ((lmn[0] & 0xff00) << 8) | + ((lmn[0] & 0xff0000) >> 8) | ((lmn[0] & 0xff000000) >> 24); + bit = word & 1; /* save bit 31 */ + word = word >> 1; /* shift right 1 */ + if (bit) + word |= 0x80000000; /* copy old bit 31 to bit 0 */ + lmn[1] = mptr[j*8+1]; /* get 2nd 4 chars of filename */ + rem = ((lmn[1] & 0xff) << 24) | ((lmn[1] & 0xff00) << 8) | + ((lmn[1] & 0xff0000) >> 8) | ((lmn[1] & 0xff000000) >> 24); + word = word ^ rem; /* EOR with 2nd half of load module name */ + rem = word % smds; /* get remainder as relative entry number */ + fprintf(stderr, " entry %d (calc %d) off 0x%x typ 0x%x blk 0x%x len 0x%x, pw 0x%x udt 0x%x\n", + j, rem, (sblk & 0xffffff)*BLKSIZE, sblk>>24, sblk, len, pw, udt); +// fprintf(stderr, "offset index %d calc %d\n", i/32, rem); /* display entry # */ + } + } + + /* see if user want list only */ + if ((option & DOLIST) && !(option & DOADD)) + goto doexit; // getout + +#if 0 + /* get file size in au's */ + fileau = size / spau; /* get number of au's required for file */ + if ((size % spau) != 0) + fileau++; /* round up to next au of overflow */ +#endif + + /* lsblk has the lowest space definition from SMD entries */ + lmblk = lsblk - fileau * spau; /* get sector address of where to store lm */ + fprintf(stderr, "lmblk 0x%x lsblk 0x%x fileau 0x%x spau 0x%x\n", lmblk, lsblk, fileau, spau); + + /* hash filename into SMD entry number */ + fprintf(stderr, "1 hashing lmname[0] %x lmname[1] %x\n", lmname[0], lmname[1]); + word = lmname[0]; /* get filename first 4 chars to R5 and shift right circular by 1 */ + i = word & 1; /* save bit 31 */ + word = word >> 1; /* shift right 1 */ + if (i) + word |= 0x80000000; /* copy old bit 31 to bit 0 */ + word = word ^ lmname[1]; /* EOR with 2nd half of load module name */ + hash1 = word / smds; /* calc SMD hash number and save */ + rem = word % smds; /* get remainder as relative entry number */ + + /* get relative 192W block in SMD */ + blk = rem/24; /* divide entry # by # entries/block */ + boff = (rem%24) * 32; /* get byte offset in block of entry */ + tmp = (blk * 24 + (boff/32)); /* make word offset in smd array */ + fprintf(stderr, "hash1 %x rem %x blk 0x%x %d boff %x index %d\n", hash1, rem, blk, blk, boff, tmp); + /* populate the 32 byte SMD entry */ + /* smd has entire SMD in memory */ + tmp = (blk * BLKSIZE + boff) >> 2; /* make word offset in smd array */ + mptr = (unsigned int *)smd; /* get word pointer for smd data */ + /* word 1 and 2 has filename */ + blk = lmname[0]; /* 1st 4 char of lmname */ + word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); + mptr[tmp] = word; /* set 1st 4 char of name */ + + blk = lmname[1]; /* set 2nd 4 char of name */ + word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); + mptr[tmp+1] = word; /* set 2nd 4 char of name */ + +// blk = 0xca000000 | lmblk; /* type ca and blk address */ + blk = 0xee000000 | lmblk; /* type ca and blk address */ + word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); + mptr[tmp+2] = word; /* set type and blk addr */ + /* size now has load module size in sectors */ + blk = 0x80000000 | size; /* file flags and size */ + word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); + mptr[tmp+3] = word; /* set flags and size */ + mptr[tmp+4] = 0; /* no username */ + mptr[tmp+5] = 0; /* no username */ + blk = 0x00000000 | smdudt; /* no password and smd udt */ + word = ((blk & 0xff) << 24) | ((blk & 0xff00) << 8) | ((blk & 0xff0000) >> 8) | ((blk & 0xff000000) >> 24); + mptr[tmp+6] = word; /* set password and udt index */ + mptr[tmp+7] = 0; /* not used */ + + /* loop through the SMD looking for a match to the load module name */ + for (i=0; i<(smds*32); i+=32) { + unsigned int sblk, len, udt, pw; + int yep = 0; + for (j=0; j<8; j++) { + if (smd[i+j] != 0) { + fprintf(stderr, "%c", smd[i+j]); + yep = 1; + } + } + if (yep) { + int bit; + unsigned int lmn[2]; /* load module name */ + sblk = (smd[i+8] << 24) | (smd[i+9] << 16) | (smd[i+10] << 8) | (smd[i+11]); + len = (smd[i+12] << 24) | (smd[i+13] << 16) | (smd[i+14] << 8) | (smd[i+15]); + pw = (smd[i+24] << 8) | (smd[i+25]); + udt = (smd[i+26] << 8) | (smd[i+27]); +#if 0 + fprintf(stderr, " entry %d blk # 0x%x off 0x%x len 0x%x, pw 0x%x udt 0x%x\n", + i/32, sblk, (sblk & 0xffffff) * BLKSIZE, len, pw, udt); + /* udt size id 0x40, C.UDTA is at 0xb40 */ + word = (os[0x780+0xb40] << 24) | (os[0x780+0xb41] << 16) | (os[0x780+0xb42] << 8) | (os[0x780+0xb43]); + udtp = (udt * 0x40 + word); /* get udt address */ + fprintf(stderr, "UDTP 0x%x\n", udtp); /* display word */ + /* spau is in byte 0x0f */ + spau = os[0x780+udtp+0x0f] & 0xff; /* get word with spau */ + fprintf(stderr, "SPAU 0x%x\n", spau); /* display spau */ +#endif + + /* hash the name to see if pointer is to current SMD entry */ + mptr = (unsigned int *)smd; /* get word pointer for SMD data */ + j = i/32; /* offset in SMD file (entry #) */ + lmn[0] = mptr[j*8]; /* get filename first 4 chars to R5 and shift right circular by 1 */ + word = ((lmn[0] & 0xff) << 24) | ((lmn[0] & 0xff00) << 8) | + ((lmn[0] & 0xff0000) >> 8) | ((lmn[0] & 0xff000000) >> 24); + bit = word & 1; /* save bit 31 */ + word = word >> 1; /* shift right 1 */ + if (bit) + word |= 0x80000000; /* copy old bit 31 to bit 0 */ + lmn[1] = mptr[j*8+1]; /* get 2nd 4 chars of filename */ + rem = ((lmn[1] & 0xff) << 24) | ((lmn[1] & 0xff00) << 8) | + ((lmn[1] & 0xff0000) >> 8) | ((lmn[1] & 0xff000000) >> 24); + word = word ^ rem; /* EOR with 2nd half of load module name */ + rem = word % smds; /* get remainder as relative entry number */ + fprintf(stderr, " entry %d (calc %d) off 0x%x typ 0x%x blk 0x%x len 0x%x, pw 0x%x udt 0x%x\n", + j, rem, (sblk & 0xffffff)*BLKSIZE, sblk>>24, sblk, len, pw, udt); +// fprintf(stderr, "offset index %d calc %d\n", i/32, rem); /* display entry # */ + } + } + + fprintf(stderr, "file space def: blk 0x%x seek 0x%x size 0x%x %d\n", lmblk, lmblk*BLKSIZE, size, size); + if (option & DOADD) { /* see if user wants file written to disk */ + /* write the load module to disk */ + /* rewind the disk */ + fseek(dp, 0, 0); /* seek home */ + /* seek to where the load module is to be stored */ + fseek(dp, lmblk*BLKSIZE, 0); /* seek sector for saving load module */ + /* rewind the load module */ + fseek(fp, 0, 0); /* seek home */ + /* copy all of the sectors */ + for (i=0; i +#include +#include +#include +#include +#include + +int filen = 1; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int oldsize, newsize; +FILE *outfp; +int inp; +int ln; + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int32_t n1, n2, hc, tc, n; + + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)4); + if (n1 <= 0) { + hc = -1; /* at EOM on disk file */ + return hc; /* return EOM */ + } + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) { /* check for garbage, assume EOF */ + hc = -1; /* at EOM on disk file */ + return hc; /* return EOM */ + } + + /* check for EOF & EOM on tape data */ + if (hc == 0) { + /* we are at tape EOF */ + if (++EOFcnt < 2) /* if 1st EOF, print file info */ + { + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + fprintf(stderr, "file %d: EOF after %d records: %d bytes\n\n", filen, count, size); + filen++; /* set next file number */ + } + else + { + fprintf(stderr, "second EOF after %d files: %d bytes\n", filen-1, tsize+size); + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + return 0; /* return EOF on tape data */ + } + + /* check for EOM */ + if (hc == -1) { + return -1; /* at EOM on disk file */ + } + + /* read the data */ + n = read(inp, s, (size_t)hc); + if (n <= 0) + return -1; /* at EOM on disk file */ + + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)4); + if (n2 <= 0) + return -1; /* at EOM on disk file */ + + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) + { + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +void putrec(int cnt, char *buf) +{ + int32_t n1, n2, nw; + int32_t hc = (cnt + 1) & ~1; /* make byte count even */ + +//printf("writing %d chars\n", cnt); + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&hc), (size_t)1, (size_t)4, outfp); + /* write the data mod 2 */ + nw = fwrite((char *)buf, (size_t)1, (size_t)hc, outfp); + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&hc), (size_t)1, (size_t)4, outfp); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "write (%d) failure\n", nw); + fprintf(stderr, "Operation aborted\n"); + fclose(outfp); + close(inp); + free(buf); + exit(1); + } +} + +int main (int argc, char *argv[]) +{ + char *buf; + size_t buf_size = 256 * 1024; + int ll, gotboth = 0; + int32_t zero = 0; + + if (argc != 3) { + fprintf(stderr, "usage: %s infile outfile\n", argv[0]); + exit(1); + } + + /* open input file */ + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + + close(inp); /* close input */ + outfp = fopen(argv[1],"r"); /* reopen */ + fseek(outfp, 0, SEEK_END); /* seek to end */ + oldsize = ftell(outfp); /* get filesize in bytes */ + fclose(outfp); /* now close it */ + + /* open input file */ + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + + /* open output file */ + outfp = fopen(argv[2],"w"); + if (outfp == NULL) { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[2]); + exit(1); + } + + /* init counts */ + ln = -2; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + + /* get a 256k buffer */ + if ((buf = malloc(buf_size)) == NULL) { + fprintf(stderr, "Can't allocate memory for %s\n", argv[0]); + return (4); + } + + /* get buffers until eof */ +domore: + while ((ll=getloi(buf, buf_size)) > 0) { +//printf("got %d char\n", ll); + /* we have data to write */ + putrec(ll, buf); /* write the buffer */ + gotboth = 0; + } +//printf("we have EOF %d\n", gotboth+1); + /* we have an EOF or an EOM */ + if (ll == 0) { + /* we have EOF, write a zero */ + fwrite((char *)(&zero), (size_t)1, (size_t)4, outfp); + gotboth++; /* one more EOF */ + if (gotboth == 2) { + /* we have written both EOF's, now write EOM */ + ll = -1; + } else { + goto domore; /* get more data */ + } + } + +//printf("we have EOM, DONE\n"); + /* We have EOM, see if EOF's needed */ + switch (gotboth) { + case 0: /* we have written no EOFs, so write two */ + fwrite((char *)(&zero), (size_t)1, (size_t)4, outfp); + /* drop through */ + case 1: /* we have written 1 EOF, so write one more */ + fwrite((char *)(&zero), (size_t)1, (size_t)4, outfp); + /* drop through */ + default: + case 2: /* we have written 2 EOFs, now do EOM */ + zero = -1; + fwrite((char *)(&zero), (size_t)1, (size_t)4, outfp); + } + fprintf(stderr, "EOM after 2 EOFs %d files: %d bytes\n", filen-1, tsize); + + newsize = ftell(outfp); /* get filesize in bytes */ + fprintf(stderr, "Size of file changed from %d to %d\n", oldsize, newsize); + + /* we done */ + fclose(outfp); + close(inp); + free(buf); + exit(0); +} diff --git a/SEL32/taptools/filelist.c b/SEL32/taptools/filelist.c new file mode 100644 index 0000000..59f638b --- /dev/null +++ b/SEL32/taptools/filelist.c @@ -0,0 +1,348 @@ +/* + * filelist.c + * + * This program scans a metatape file and prints file count and sizes. + * input - stdin or specified filename + * output - stdout + */ +#define NOTDUMP + +#include +#include +#include +#include +#include +#include +#include + +int filen = 1; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int size_512K = 512 * 1024; +int ln; +#ifdef USE_READ +FILE *infp; +#else +int inp; +#endif +#define PRINTABLE(x) ((x < 32) || (x > 126)) ? '.' : x + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int n1, n2, hc, tc, n; + + errno = 0; + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 <= 0) + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) /* check for garbage, assume EOM */ + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc == 0) + { + /* we are at tape EOF */ + if (++EOFcnt < 2) /* if 1st EOF, print file info */ + { +#ifdef NOTDUMP + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + fprintf(stderr, "file %d: eof after %d records: %d bytes\n", filen, count, size); +#endif + filen++; /* set next file number */ + } + else + { +#ifdef NOTDUMP + fprintf(stderr, "second eof after %d files: %d bytes\n", filen, size); +#endif + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + + /* we have EOF */ + return 0; /* return EOF on tape data */ + } + if (hc == -1) + { +#ifdef NOTDUMP + /* we have EOM */ + fprintf(stderr, "mpx eot\n"); + /* print out total tape size in bytes */ + fprintf(stderr, "total length: %ld bytes\n", tsize); +#endif + return -1; /* at EOM on disk file */ + } + /* read the data */ + n = read(inp, s, (size_t)hc); + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)sizeof(tc)); + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) + { +#ifdef NOTDUMP + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } +#endif + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +int main (int argc, char *argv[]) +{ +// char in[BUFSIZ], out[BUFSIZ]; + char *buf; + size_t size_512K = 512 * 1024; + size_t buf_size = 512 * 1024; + char *cp, *np; + int ll, gotboth = 0; + int lfilen = filen; + unsigned int fileaddr, file_byte_count=0, curchar, buffptr, bufflen; + int skipfile = 0; + + if (argc != 2) + { + fprintf(stderr, "usage: %s infile\n", argv[0]); + exit(1); + } /* end of if */ + + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) + { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + + /* get a 512k buffer */ + if ((buf = malloc(buf_size)) == NULL) + { + fprintf(stderr, "Can't allocate memory for %s\n", argv[0]); + return (4); + } + /* init counts */ + ln = -2; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + filen = 1; + lfilen = filen; + buffptr = 0; + bufflen = 16; + fileaddr = 0; + file_byte_count = 0; + printf("\nfile %d:\n", filen); + + /* get lines until eof */ + while ((ll=getloi(buf, buf_size)) != EOF) + { + if (ll == 0) + { + /* eof found, process new file */ + skipfile = 0; + file_byte_count = 0; + fileaddr = 0; + printf("\nfile %d:\n", filen); + } + else + { + int cc = 0; + buffptr = 0; + char buff[257]; + int ans; + +{ + /* dump first 2 words */ + int w1, w2, i, j; + char path[64], command[128]; + w1 = (buf[0] & 0xff) << 24 | buf[1] << 16 | buf[2] << 8 | (buf[3] & 0xff); + w2 = (buf[4] & 0xff) << 24 | buf[5] << 16 | buf[6] << 8 | (buf[7] & 0xff); + if (filen > 480) + printf("w1 = %x, w2 = %d count = %d\n", w1, w2, count); + if (count == 1 && w1 == 1) + { + char file[20], dir[20], vol[20]; + int off = 8; + int l = 0; + /* we have directory entries */ + for (j=0; j (6144-48-off)) + { + ll=getloi(buf, buf_size); + off = 0; + l = 0; + k = 0; + printf("reread: got ll= %d\n", ll); + for (i=0; i<16; i++) + { + file[i] = tolower(buf[k+off+i]); + if (file[i] == ' ') + file[i] = '\0'; + } + file[16] = '\0'; + printf("file %s\n", file); + } + for (i=0; i<16; i++) + { + file[i] = tolower(buf[k+off+i]); + if (file[i] == ' ') + file[i] = '\0'; + } + file[16] = '\0'; + for (i=0; i<16; i++) + { + dir[i] = tolower(buf[k+off+16+i]); + if (dir[i] == ' ') + dir[i] = '\0'; + } + dir[16] = '\0'; + for (i=0; i<16; i++) + { + vol[i] = tolower(buf[k+off+32+i]); + if (vol[i] == ' ') + vol[i] = '\0'; + } + vol[16] = '\0'; + sprintf(path, "./%s/%s", vol, dir); + /* create the directory/file */ +// sprintf(command, "mkdir -p %s", path); +// system(command); + sprintf(path, "./%s/%s/%s", vol, dir, file); + printf("path %s\n", path); + sprintf(command, "touch %s", path); +// system(command); + } + } else + if (count == 1 && w1 == 2 && w2 == 0) + { + char file[20], dir[20], vol[20]; + /* process file definition */ + /* we have a file definition entry */ + for (i=0; i<16; i++) + { + file[i] = tolower(buf[8+i]); + if (file[i] == ' ') + file[i] = '\0'; + } + file[16] = '\0'; + for (i=0; i<16; i++) + { + dir[i] = tolower(buf[24+i]); + if (dir[i] == ' ') + dir[i] = '\0'; + } + dir[16] = '\0'; + for (i=0; i<16; i++) + { + vol[i] = tolower(buf[40+i]); + if (vol[i] == ' ') + vol[i] = '\0'; + } + vol[16] = '\0'; + sprintf(path, "./%s/%s/%s", vol, dir, file); + printf("path2 = %s\n", path); + } +} + /* see if skipping to next file */ + if (skipfile == 1) + { + continue; + } + +#ifdef NODUMP + /* process the returned buffer */ + while (cc < ll) + { + curchar = (unsigned int)buf[cc++] & 0xff; + file_byte_count++; + if (!buffptr) + printf(" %06x : ",fileaddr); + printf("%02x", curchar & 0xff); + buff[buffptr++] = PRINTABLE(curchar); + if (!(buffptr % 4)) + printf(" "); + if (buffptr >= bufflen) + { + buff[buffptr] = 0; + printf(" |%s|\n",buff); + buffptr = 0; + fileaddr += bufflen; + if (!(file_byte_count % 256)) + { + printf("\n - continue, q = quit, s = skip > "); + ans = getchar(); + if (ans == 'q') + { + close(inp); + free(buf); + exit(1); + } + if (ans == 's') + skipfile = 1; + if (ans != '\n') + while ((ans=getchar()) != '\n' ) + ; + } /* end of if */ + if (skipfile == 1) + break; + } /* end of if */ + } /* end of while */ +#endif + +#ifdef NODUMP + if (buffptr && !skipfile) + { + buff[buffptr] = 0; + while (buffptr++ < bufflen) + { + printf(" "); + if (!(buffptr % 4)) + printf(" "); + } /* end of while */ + printf(" |%s|\n",buff); + + /* see what user wants to do */ + printf("\n - continue, q = quit > "); + ans = getchar(); + if (ans == 'q') + { + close(inp); + free(buf); + exit(1); + } + if (ans != '\n') + while ((ans=getchar()) != '\n' ) + ; + } /* end of if */ +#endif + } + } + close(inp); + free(buf); + exit(0); +} diff --git a/SEL32/taptools/fmgrcopy.c b/SEL32/taptools/fmgrcopy.c new file mode 100644 index 0000000..6db7aa4 --- /dev/null +++ b/SEL32/taptools/fmgrcopy.c @@ -0,0 +1,288 @@ +/* + * fmgrcopy.c + * + * This program scans a metatape file and prints file count and sizes. + * In addition, it creats a director for each username specified in + * the filemanager tape and then creates a file containing the file + * contents. The file must be an filemgr save tape and not an SDT + * tape. + * input - stdin or specified filename + * output - stdout + */ + +#include +#include +#include +#include +#include +#include +#include + +int lfilen, filen = 1; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int size_512K = 512 * 1024; +int ln; +#ifdef USE_READ +FILE *infp; +#else +int inp, outp; +#endif +#define PRINTABLE(x) ((x < 32) || (x > 126)) ? '.' : x + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int32_t n1, n2, hc, tc, n; + + errno = 0; + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 <= 0) + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) /* check for garbage, assume EOM */ + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc == 0) { + /* we are at tape EOF */ + if (++EOFcnt < 2) { /* if 1st EOF, print file info */ + lfilen = filen; + filen++; /* set next file number */ + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + + /* we have EOF */ + return 0; /* return EOF on tape data */ + } + if (hc == -1) + return -1; /* at EOM on disk file */ + + /* read the data */ + n = read(inp, s, (size_t)hc); + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)sizeof(tc)); + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) { + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +int main (int argc, char *argv[]) +{ + char *buf; + size_t size_512K = 512 * 1024; + size_t buf_size = 512 * 1024; + char *cp, *np; + int ll; + char path[64], command[128]; + + if (argc != 2) { + //fprintf(stderr, "usage: %s infile\n", argv[0]); + printf("usage: %s infile\n", argv[0]); + exit(1); + } /* end of if */ + + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) { + //fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + printf("%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + outp = -1; + + /* get a 512k buffer */ + if ((buf = malloc(buf_size)) == NULL) { + //fprintf(stderr, "Can't allocate memory for tscan\n"); + printf("Can't allocate memory for tscan\n"); + return (4); + } + /* init counts */ + ln = -2; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + filen = 1; + lfilen = 0; + printf("\nfile %d:\n", filen); + + /* get lines until eof */ + while ((ll=getloi(buf, buf_size)) != EOF) { + if (ll == 0) { + /* eof found, process new file */ + printf("\nfile %d:\n", filen); + } else { + int cc = 0; + unsigned int curchar; + + /* filemgr smd entries are 8 words, and are in 1152 words (4608 bytes) + * (6 sector) blocks. Saved data files are modulo 1152 words also */ + /* 8 wds per SMD entry, 24 entries per sector, 144 entries per 6 sector + * block. */ + int i, j, m; +// if (filen == 1) + { + /* read smd entry */ + char file[20], dir[20]; + int l = 0; + int smddone = 0; + int totent = 0; + char *buf2 = buf; + printf("\nfile %d:\n", filen); + /* see how man entries here */ + while(!smddone) { + /* process entries in this record */ + for (j=0; j<144; j++) { + int k = l++ * 32; + int w1 = (buf[k+13] & 0xff) << 16 | (buf[k+14] & 0xff) << 8 | (buf[k+15] & 0xff); + /* stop processing on first zero smd entry */ + if (w1 <= 0) { + smddone = 1; + break; + } + totent++; + /* get file/dir name */ + for (i=0; i<8; i++) { + file[i] = tolower(buf[k+0+i]); + if (file[i] == ' ') + file[i] = '\0'; + } + file[8] = '\0'; + for (i=0; i<8; i++) { + dir[i] = tolower(buf[k+0+16+i]); + if (dir[i] == ' ') + dir[i] = '\0'; + } + dir[8] = '\0'; + if (dir[0] == '\0') + sprintf(dir, "%s", "system"); + sprintf(path, "./%s/%s", dir, file); + // see if active file + if ((buf[k+12] & 0x80) == 0) + // not active goon + printf("inactive file: w1 = %d path = %s\n", w1, path); + else + printf("active file: w1 = %d path = %s\n", w1, path); + } + if (smddone) + break; + buf2 += 4608; /* next buffer */ + ll=getloi(buf2, 4608); + } + printf("%d smd entries found\n", totent); + /* we have directory entries */ + for (j=0; j= 0) + close(outp); + outp = -1; + +#ifndef DO_LATER + /* open output file, create it if necessary */ + if ((outp = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { + //fprintf(stderr, "Can't open %s\n", path); + printf("Can't open %s\n", path); + close(inp); + free(buf); + return (3); + } +#endif + /* get the file data */ + for (m=0; m<((w1+5)/6); m++) { + char data[5000]; /* data buffer */ + ll=getloi(data, 4608); + + /* process file data for file */ + if (ll == 4608) { +#ifndef DO_LATER + /* blks/w1 have number of blocks to write */ + int bcnt, no; /* block count */ + if (blks >= 6) { + blks -= 6; /* enough for 6 block, write them */ + bcnt = 6*768; /* write all 6 blocks */ + } else { + bcnt = blks*768;/* just write what we need */ + blks = 0; + } + /* only write number of sectors on save tape, not all 4608 */ + /* if zero, just reading excess blocks */ + if (bcnt != 0) { + no = write(outp, data, bcnt); + if (no != bcnt) + // fprintf(stderr, "write (%d) != read (%d) on file %s\n", no, bcnt, path); + printf("write (%d) != read (%d) on file %s\n", no, bcnt, path); + } +#else + printf("read (%d) on file %s\n", ll, path); +#endif + } else { + printf("Bad file size read! %d instead of 4608\n", ll); +/// if (ll == -1) break; + if (ll == -1) + goto dostop; + } + } /* end writing file */ + } /* end of smd scan */ + } /* read smd entries 4608 byte records */ + } /* process read of smd or sdt */ + } /* end of getloi read */ +dostop: + close(inp); + free(buf); + if (outp >= 0) + close(outp); + exit(0); +} diff --git a/SEL32/taptools/makefile b/SEL32/taptools/makefile new file mode 100644 index 0000000..e40be52 --- /dev/null +++ b/SEL32/taptools/makefile @@ -0,0 +1,178 @@ +# Makefile for taptools +SHELL = /bin/sh + +# Adapt the flags in the following paragraph to your system +# for Linux +ROOT = . +OPTC = -O #-m32 + +#B = $(ROOT) +#B = $(ROOT)/bin +B = /system/bin +#I = $(ROOT)/include +I = +#L = $(ROOT)/lib +#D = $L/mylib.a +D = + +##CFLAGS= $(OPTC) -I$I +CFLAGS= $(OPTC) -I$I -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE + +# For Linux +#LFLAGS= -L$L +LFLAGS= + +PROGS = \ + $(ROOT)/diskload \ + $(ROOT)/filelist \ + $(ROOT)/fmgrcopy \ + $(ROOT)/mkfmtape \ + $(ROOT)/sdtfmgrcopy \ + $(ROOT)/tapdump \ + $(ROOT)/tape2disk \ + $(ROOT)/tapscan \ + $(ROOT)/eomtap \ + $(ROOT)/volmcopy \ + $(ROOT)/ddump \ + $(ROOT)/deblk \ + $(ROOT)/mpxblk \ + $(ROOT)/renum \ + $(ROOT)/cutostap \ + $(ROOT)/small + +all: $(PROGS) + +#install :$(PROGS) +# @cp $(@F) $B +# @echo $(@F) installed in $B +# @echo +## @chmod 755 $(@F) + +##$(PROGS): $D $$(@F).c +## @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ +##$(PROGS): $D $$(@F).c +## @chmod 755 $@ +## @cp $(@F) $B +## @echo $(@F) installed in $B +## @echo + +$B/diskload: $D diskload.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/filelist: $D filelist.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/fmgrcopy: $D fmgrcopy.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/mkfmtape: $D mkfmtape.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/sdtfmgrcopy: $D sdtfmgrcopy.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/tapdump: $D tapdump.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/tape2disk: $D tape2disk.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/tapsca: $D tapscan.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/eomtap: $D eomtap.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/volmcopy: $D volmcopy.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/ddump: $D ddump.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/deblk: $D deblk.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/mpxblk: $D mpxblk.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/renum: $D renum.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/cutostap: $D cutostap.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +$B/small: $D small.c + @-$(CC) $(CFLAGS) $(@F).c $(LFLAGS) -o $@ + @chmod 755 $@ + @cp $(@F) $B + @echo $(@F) installed in $B + +# Some makes don't understand the $$ notation above. In this case +# you have to type out the compile paragraph for each PROG. Sigh. +# Here's a start, good luck. +# +#$B/abshw: abshw.c +# $(CC) $(CFLAGS) $? $(LFLAGS) -o $@ +# @chmod 751 $@ +# @echo $(@F) installed in $B + +remake : clobber + @make ROOT=$(ROOT) OPTC=$(OPTC) + +clean : + @-rm -f a.out junk* JUNK* core + @-rm -f *.o + +clobber : clean + @-rm -f $(PROGS) + +install : $(PROGS) + @cp $(PROGS) $B + @echo $(PROGS) installed in $B + @echo +# @chmod 755 $(@F) diff --git a/SEL32/taptools/mkfmtape.c b/SEL32/taptools/mkfmtape.c new file mode 100644 index 0000000..c5b9a4e --- /dev/null +++ b/SEL32/taptools/mkfmtape.c @@ -0,0 +1,389 @@ +/* + * mkfmtape.c + * + * This program reads MPX files and stores it into a simulated + * filemgr save tape. The tape may then be restored to a MPX + * running system using the filemgr. + * new file entry. + * intput - simulated fmgrtape filename, filename, etc. + * output - simulated fmgrtape, file list to stdout + * options - -p = file type 0xca for programs + * - -t = ascii text file 0xee + * - -l = library/directory file 0xff + * - -o = other 0x00 + * - -a = append entries to current file + * - -u = username (directory) + * 11/26/2018 + */ + +#include +#include +#include +#include + +#define BLKSIZE 768 /* MPX file sector size */ +u_int32_t dir[1152]; /* room for 144 8w smd entries */ +unsigned char data[4608]; /* room for 6*768=(4608) 768 byte sectors per 4608 byte block */ +unsigned char bigdata[19200]; /* room for 6*768=(4608) 768 byte sectors per 4608 byte block */ + +/* read program file and output to a simulated mpx1.x filemgr savetape */ +/* mkfmtape -ltoa fmgrtape, filename, filename, ... */ +int main(argc, argv) +int argc; +char *argv[]; +{ + FILE *fp, *dp, *fopen(); + int targc; + char **targv; + unsigned char username[8]; + char *p; + int i; +#define DOPROG 1 +#define DOADD 2 +#define DOOTHER 4 +#define DOTEXT 8 +#define DOLIB 16 +#define DOUSER 32 + unsigned int option = DOTEXT; /* what to do */ + unsigned char *fnp; /* file name pointer */ + unsigned int size; /* size in 768 byte sectors */ + unsigned int word; /* just a temp word variable */ + unsigned char name[9]; /* LM name */ + unsigned int typ; /* file type requested by user */ + char *userp = username; /* pointer to username */ + int ofd; /* output file number */ + int32_t filen; /* file number */ + u_int32_t *dirp; /* directory entry pointer */ + int32_t totent; /* total smd entries */ + + memset((char *)dir, 0, 4608); /* zero smd storage */ + memset((char *)data, 0, 4608); /* zero data storage */ + for (i=0; i<8; i++) + username[i] = 0; /* use zero for system username */ + typ = 0xee000000; /* set type */ + if (argc <= 1) { /* see if correct # args */ + fprintf(stderr, "Usage: %s [-ptloa] [-uusername] fmgrtape file1 file2 ...\n", *argv); + exit(1); + } + while(--argc > 0) { +// printf("argc %d argv %s\n", argc, *argv); + p = *++argv; + if (*p++ == '-') { + if (*p == '\0') { + fprintf(stderr, "Error: no option specified\n"); + fprintf(stderr, "Usage: %s [-ptloa] [-uusername] fmgrtape file1 file2 ...\n", *argv); + exit(1); + } +// printf("doing options %s\n", p); + while (*p != '\0') { + switch (*p++) { + case 'p': + case 'P': + option |= DOPROG; /* save program modules */ + typ = 0xca; /* set type */ + break; + case 'A': + case 'a': + option |= DOADD; /* append to save tape */ + break; + case 'O': + case 'o': + option |= DOOTHER; /* other type files */ + typ = 0x00; /* set type */ + break; + case 'T': + case 't': + option |= DOTEXT; /* save text files */ + typ = 0xee; /* set type */ + break; + case 'L': + case 'l': + option |= DOLIB; /* save library files */ + typ = 0xff; /* set type */ + break; + case 'U': + case 'u': + option |= DOUSER; /* save username for files */ + userp = p; + while (*p != '\0') + p++; + break; + default: + fprintf(stderr, "Error: no option specified\n"); + fprintf(stderr, "Usage: %s [-ptloa] [-uusername] fmgrtape file1 file2 ...\n", *argv); + exit(1); + break; + } /* end switch */ + continue; + } /* end while */ + } + else { +// printf("option set to %x\n", option); + if (option & DOADD) { + long bytes; + /* open read/write */ + if ((dp = fopen(*argv, "r+")) == NULL) { + /* file not there, create one by opening w+ */ + if ((dp = fopen(*argv, "w")) == NULL) { + fprintf(stderr, "error: can't create/open simulated tape disk file %s\n", *argv); + exit(1); + } +// printf("1 opened output in w mode, write at start\n"); + } +// else +// printf("2 opened output in r+ mode write at end\n"); + + fseek(dp, 0, SEEK_END); /* seek to end */ + bytes = ftell(dp); /* get filesize in bytes */ + printf("file length %ld bytes\n", bytes); + printf("start writing at %ld bytes offset\n", bytes-8); + fseek(dp, 0, SEEK_SET); /* rewind file to beginning */ + if (bytes > 8) { /* see if file written to already */ + /* we need to find the EOT */ + int32_t n1, n2, hc, tc, n; + int EOFcnt = 0; +readmore: + n1 = fread((char *)(&hc), 1, (size_t)4, dp); /* read 4 byte record size */ + if (n1 <=0) /* check for read error */ + goto doabort; /* bad tape format */ + + if (hc & 0xffff0000) /* check for garbage */ + hc = 0; /* assume EOF on disk */ + + if (hc == 0) { /* check for EOF on file */ + /* EOF found */ + if (++EOFcnt == 2) { + /* we have second EOF, we need to backup 4 bytes */ +backup4: + bytes = ftell(dp); /* get file position in bytes */ + fseek(dp, bytes-4, SEEK_SET); /* backspace over 2nd EOF */ + goto getout; /* start our processing */ + } + /* we have first EOF, keep reading */ + goto readmore; /* read more records */ + } else + if (hc == -1) { /* check for EOM */ + if (EOFcnt == 1) + /* see if one EOF followed by EOM (-1) */ + goto backup4; /* start write over the EOM */ + /* we have an EOM without any EOF, so bad tape */ + goto doabort; /* bad tape format */ + } + + /* we have data, so no EOF */ + EOFcnt = 0; /* reset EOF count */ + + /* read the data */ + tc = hc; /* save record size */ + n = fread(bigdata, 1, (size_t)hc, dp); /* read in record size */ + if (n <= 0) { /* check for read error */ + goto doabort; /* bad tape format */ + } + n2 = fread((char *)(&hc), 1, (size_t)4, dp); /* read 4 byte record size */ + if (n2 <= 0) { /* check for read error */ +doabort: + /* error, abort the operation */ + fprintf(stderr, "error: formatting error on simulated tape disk file %s\n", *argv); + exit(1); + } + /* verify counts & sizes */ + if ((tc != hc) || (hc != n)) + goto doabort; /* bad tape format */ + goto readmore; /* read more records */ + } + } + else { + if ((dp = fopen(*argv, "w")) == NULL) { + fprintf(stderr, "error: can't create/open simulated tape disk file %s\n", *argv); + exit(1); + } +// printf("3 opened output in w mode, write at start\n"); + } +getout: +// printf("opening %s file for tape\n", *argv); + *++argv; + break; /* go handle files now */ + } + continue; + } + /* end while --argc */ + if ((argc-1) <= 0) { + fprintf(stderr, "Error: incorrect number of parameters\n"); + fprintf(stderr, "Usage: %s [-ptloa] [-uusername] fmgrtape, file1 file2 ...\n", *argv); + exit(1); + } + /* got tapefile and options, handle files now */ + targc = argc; /* save argc to reread list */ + targv = argv; /* save argv to reread list */ +// printf("AT 3 argc %d argv %s\n", argc, *argv); + filen = 0; /* no files yet */ + totent = 0; /* no files yet */ + /* populate the 32 byte SMD entry */ + dirp = (u_int32_t *)dir; /* get word pointer for smd data */ + while (--argc > 0) { + u_int32_t smd[8]; /* smd entry data */ + int blks; + + for (i=0; i<8; i++) /* zero smd entry */ + smd[i] = 0; + p = *argv++; + i = strlen(p); /* filename size */ + if (i == 0 || i > 8) { + fprintf(stderr, "error: Filename too long (%d>8) %s, Aborting\n", i, p); + exit(1); + } +// printf("argc %d argv3 %s\n", argc, p); + if ((fp = fopen(p, "r")) == NULL) { + fprintf(stderr, "error: can't open user file %s\n", p); + exit(1); + } + fnp = p; /* get file name pointer */ + fseek(fp, 0, SEEK_END); /* seek to end */ + word = ftell(fp); /* get filesize in bytes */ + fseek(fp, 0, SEEK_SET); /* rewind file */ + size = (word/768); /* filesize in sectors */ + if (word%768 != 0) /* see if byte left over */ + size += 1; /* partial sector, add 1 */ + blks = (word/4608); /* blocks */ + if ((word%4608) != 0) + blks++; + printf("handle file %s user %s size %d bytes %d sect %d blocks\n", + fnp, userp, word, size, blks); + fclose(fp); + /* create smd entry for this file */ + memset(name, ' ', 8); /* blank filename */ + for (i=0; i<8; i++) { + if (p[i] == '\0') /* check for null termination char */ + break; + name[i] = toupper(p[i]); /* uppercase filename */ + } + /* populate the 32 byte SMD entry */ + /* word 1 and 2 has filename */ + smd[0] = name[3] << 24 | name[2] << 16 | name[1] << 8 | name[0]; + smd[1] = name[7] << 24 | name[6] << 16 | name[5] << 8 | name[4]; + /* type and smd loc in wd 2 */ + smd[2] = typ; /* save the type of file */ + /* size now has load module size in sectors */ + size = 0x80000000 | (blks * 6); /* file flags and size */ + smd[3] = (size & 0xff) << 24 | (size & 0xff00) << 8 | + (size & 0xff0000) >> 8 | (size & 0xff000000) >> 24; + memset(name, ' ', 8); /* blank username */ + for (i=0; i<8; i++) { + if (userp[i] == '\0') /* check for null termination char */ + break; + name[i] = toupper(userp[i]); /* uppercase username */ + } + /* set username */ + smd[4] = name[3] << 24 | name[2] << 16 | name[1] << 8 | name[0]; + smd[5] = name[7] << 24 | name[6] << 16 | name[5] << 8 | name[4]; + if ((smd[4] == 0x20202020 && smd[5] == 0x20202020) || + (smd[4] == 0 & smd[5] == 0)) { + smd[4] = smd[5] = 0; /* use null for system */ + } + smd[6] = 0x00080000; /* no password or udt index */ + smd[7] = 0x00000080; /* fmgr has 0x80000000 in it so I will too */ + for (i=0; i<8; i++) + *dirp++ = smd[i]; /* save smd entry */ + filen++; /* bump the file count */ + totent++; /* bump total count */ + if (filen == 144) { /* see if entry is full */ + /* we need to write out the directory entries */ + int32_t n1, n2, nw; + /* we have data to write */ + int32_t hc = (4608 + 1) & ~1; /* make byte count even */ + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + /* write the data mod 2 */ + nw = fwrite((unsigned char *)dir, 1, (size_t)hc, dp); + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "write (%d) failure\n", nw); + fprintf(stderr, "Operation aborted\n"); + exit(1); + } + memset((char *)dir, 0, 4608); /* zero smd storage */ + filen = 0; /* restart count */ + } + } + /* write out the directory entries for the files to save */ + if (filen != 0) { + /* we need to write out the directory entries */ + int32_t n1, n2, nw; + /* we have data to write */ + int32_t hc = (4608 + 1) & ~1; /* make byte count even */ + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + /* write the data mod 2 */ + nw = fwrite((unsigned char *)dir, 1, (size_t)hc, dp); + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "write (%d) failure\n", nw); + fprintf(stderr, "Operation aborted\n"); + exit(1); + } + memset(dir, 0, 4608); /* zero smd storage */ + filen = 0; /* restart count */ + } + /* totcnt has total number of files to output */ + memset((char *)data, 0, 4608); /* zero data storage */ + argc = targc; /* restore argc for reread */ + argv = targv; /* restore argv for reread */ + /* read each file and output to save tape file in 6 sector blocks */ + while (--argc > 0) { + int blks; + + p = *argv++; +// printf("argc %d argv3 %s\n", argc, p); + if ((fp = fopen(p, "r")) == NULL) { + fprintf(stderr, "error: can't open user file %s\n", p); + exit(1); + } + fnp = p; /* get file name pointer */ + fseek(fp, 0, SEEK_END); /* seek to end */ + word = ftell(fp); /* get filesize in bytes */ + fseek(fp, 0, SEEK_SET); /* rewind file */ + size = (word/768); /* filesize in sectors */ + if (word%768 != 0) /* see if byte left over */ + size += 1; /* partial sector, add 1 */ + blks = (word/4608); /* blocks */ + if ((word%4608) != 0) + blks++; +// rewind(fp); /* back to beginning */ + while (fread((char *)data, 1, 4608, fp) > 0) { + int32_t n1, n2, nw; + /* we have data to write */ + int32_t hc = (4608 + 1) & ~1; /* make byte count even */ + /* write actual byte count to 32 bit word as header */ + n1 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + /* write the data mod 2 */ + nw = fwrite((unsigned char *)data, 1, (size_t)hc, dp); + /* write the byte count in 32 bit word as footer */ + n2 = fwrite((char *)(&hc), 1, (size_t)sizeof(hc), dp); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "write (%d) failure\n", nw); + fprintf(stderr, "Operation aborted\n"); + exit(1); + } + memset((char *)data, 0, 4608); /* zero data storage */ + } + printf("handle file %s user %s (size %d bytes) (%d sect) (%d blocks)\n", + fnp, userp, word, size, blks); + fclose(fp); + } + /* write EOF (zero) to file */ + filen = 0; /* zero count */ + fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); + /* do second EOF */ + fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); + filen = -1; /* make in -1 for EOM */ + /* do EOM */ + fwrite((char *)(&filen), 1, (size_t)sizeof(filen), dp); +// printf("setting at %ld bytes in file after EOM\n", ftell(dp)); + fclose(dp); + exit(0); +} diff --git a/SEL32/taptools/mpxblk.c b/SEL32/taptools/mpxblk.c new file mode 100644 index 0000000..db60527 --- /dev/null +++ b/SEL32/taptools/mpxblk.c @@ -0,0 +1,174 @@ +/* + * mpxblk.c + * + * This program converts a unix/dos ascii file to an mpx blocked file + * trailing blanks are not deleted from the source file + * input - stdin + * output - stdout + */ + +#include +#include +#include +#include +#define MPXMAX 254 +int mpxbb(); +int getloi(); +#define BLKSIZE 768 + +int main (argc, argv) +int argc; +char *argv[]; +{ + char s[MPXMAX]; + int i; + int fn = fileno(stdout); + + while (1) { + if ((i = getloi(s, MPXMAX)) == 0) { + mpxbb(fn, s, 0, 1); /* last write to output */ + exit(0); + } + if (i == 1 && s[0] == '\n') + s[0] = ' '; /* replace single n/l with blank */ + if (s[i-1] == '\n') + i--; /* remove trailing n/l */ + if (mpxbb(fn, s, i, 0) < 0) { /* last data record out */ + fprintf(stderr, "output file error\n"); + exit(1); + } + } +} + +/* get a line of input. */ +/* terminate line on \n or \r\n */ +/* allow max of 254 chars in a line */ + +int getloi(s, lim) +char s[]; +int lim; +{ + int c, i; + + for(i = 0; --lim > 0; ) { + c = getchar(); + switch (c) { + case '\n': + /* terminate on \n */ + s[i++] = c; + goto linedone; + case '\r': + c = getchar(); + /* terminate on \r\n */ + if (c == '\n') { + s[i++] = c; + goto linedone; + } + /* put back the character */ + ungetc(c, stdin); + /* output the \r to the stream */ + c = '\r'; + /* drop through */ + default: + s[i++] = c; + break; + case EOF: + return (0); + break; + } + } +linedone: + return (i); +} + +/* + ** output line of text from the source + */ + +static unsigned char bb[BLKSIZE]; /* blocking buffer */ +static char first = 0; /* 1st time thru flag */ + +/* + * mpxbb - make up mpx block file output + * input - buffer address + * - byte count + * - last write flag + */ + +int +mpxbb(fd, buf, cnt, last) +int fd; +unsigned char *buf; +int cnt; +int last; +{ + int boff; /* next write address offset */ + + if (!first) { /* is this 1st time thru */ + first = 1; /* set the flag */ + memset (bb, '\0', BLKSIZE); /* zero the buffer */ + bb[3] = 4; /* next write byte offset */ + bb[4] = 0x60; /* set beg/end of block */ + bb[5] = 0; /* 1st block count is 0 bytes */ + } + boff = (bb[2] << 8) | (bb[3]); /* get next write address offset */ + if (last) + goto alldone; /* close out the file */ + + /* see if enough room in buffer for this record */ + /* add current offset + 2 (for last record info) plus new */ + /* record size plus 4 (2 for this rec, 2 for last) */ + if ((boff + 2 + cnt + 4) >= BLKSIZE) { + /* not enough space, write out this record */ + if (write(fd, bb, BLKSIZE) < 0) + return(-1); + memset (bb, '\0', BLKSIZE); /* zero the buffer */ + bb[4] = 0x60; /* set beg/end of block */ + bb[5] = 0; /* 1st block count is 0 bytes */ + /* after 1st write */ + boff = 4; /* init count at 4 bytes */ + } + /* we have enough room, move in the record */ + /* clear last record end of block flag, set up this record */ + /* info and last rec info at end of data, and update cnt */ + bb[boff] &= ~0x20; /* clear end of block flag */ + bb[boff+2] = 0x00; /* clear this blocks flags */ + bb[boff+3] = cnt; /* set this record count */ + memcpy(&bb[boff+4], buf, cnt); /* copy in the data */ + boff += (cnt+4); /* update count */ + bb[boff] = 0x20; /* set eob status flag */ + bb[boff+1] = cnt; /* set last rec byte count */ + bb[2] = (boff & 0xff00) >> 8; /* set hi byte of count */ + bb[3] = (boff & 0xff); /* set lo byte of count */ + return(cnt); /* done */ + +alldone: + /* that was the last record, set eof flag in bb, write it and exit */ + /* see if enough room in buffer for EOM record */ + /* add current offset + 2 (for last record info) plus new */ + /* EOF record size of 4 (2 for this rec, 2 for last) */ + if ((boff + 2 + 4) >= BLKSIZE) { + /* not enough space, write out this record */ + if (write(fd, bb, BLKSIZE) < 0) + return(-1); + memset (bb, '\0', BLKSIZE); /* zero the buffer */ + bb[4] = 0x60; /* set beg/end of block */ + bb[5] = 0; /* 1st block count is 0 bytes */ + /* after 1st write */ + boff = 4; /* init count at 4 bytes */ + } + bb[boff] &= ~0x20; /* clear end of block flag */ +/* bb[boff+2] = 0xa0; /* clear this blocks flags */ + bb[boff+2] = 0x80; /* clear this blocks flags */ + bb[boff+3] = 0; /* set record count of 0 */ + bb[boff+4] = 0xa0; /* set EOF/EOB flags */ + boff += 4; /* 4 more bytes */ + bb[2] = (boff & 0xff00) >> 8; /* set hi byte of count */ + bb[3] = (boff & 0xff); /* set lo byte of count */ + /* write out EOF record */ + if (write(fd, bb, BLKSIZE) < 0) + return(-1); + first = 0; /* reset 1st time flag */ + return(cnt); /* get out, done */ +} + diff --git a/SEL32/taptools/renum.c b/SEL32/taptools/renum.c new file mode 100644 index 0000000..593a3c3 --- /dev/null +++ b/SEL32/taptools/renum.c @@ -0,0 +1,58 @@ +/* + * renum.c + * + * This program truncates a line or expands a line with blanks to + * have a line length of 72 chars. A 7 digit line number is then + * append to the line. Numbers are in the form XXXX.000. + * input - stdin + * output - stdout + */ + +#include +#include + +/* get a line of input. */ +int ln = 1; +int getloi(s, lim) /* right from the book. */ +char s[]; +int lim; +{ + int c, i, j; + char line[12]; + + for (i=0; --lim > 0;) + { + if ((c = getchar()) == EOF) + return 0; + if (c == '\r') + continue; + if (c == '\n') + break; + s[i++] = c; + } + if (i > 72) /* truncate at char 72 */ + i = 72; + for (; i<72; i++) + s[i] = ' '; + sprintf(line, "%04d.000", ln++); + for (j=0; j<8; j++) + s[72+j] = line[j]; + s[80] = '\n'; + s[81] = '\0'; + return (i); +} + +int main (argc, argv) +int argc; +char *argv[]; +{ + char s[BUFSIZ]; + + while (1) { + if (getloi(s, BUFSIZ) == 0) + exit(0); + /* output line of text from the source */ + printf("%s", s); + } +} + diff --git a/SEL32/taptools/sdtfmgrcopy.c b/SEL32/taptools/sdtfmgrcopy.c new file mode 100644 index 0000000..9267a65 --- /dev/null +++ b/SEL32/taptools/sdtfmgrcopy.c @@ -0,0 +1,357 @@ +/* + * sdtfmgrcopy.c + * + * This program scans a metatape file and prints file count * and sizes. + * input - stdin or specified filename + * output - stdout + */ + +#include +#include +#include +#include +#include +#include +#include + +int lfilen, filen = 1; +int smd = 0; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int size_512K = 512 * 1024; +int ln; +#ifdef USE_READ +FILE *infp; +#else +int inp, outp; +#endif +#define PRINTABLE(x) ((x < 32) || (x > 126)) ? '.' : x + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int32_t n1, n2, hc, tc, n; + + errno = 0; + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 <= 0) + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) /* check for garbage, assume EOM */ + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc == 0) { + /* we are at tape EOF */ + if (++EOFcnt < 2) { /* if 1st EOF, print file info */ +// printf("EOF found after file %d\n", filen); + lfilen = filen; + filen++; /* set next file number */ + smd = 1; /* look for smd again */ + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + + /* we have EOF */ + return 0; /* return EOF on tape data */ + } + if (hc == -1) { + printf("EOM found after file %d\n", filen); + return -1; /* at EOM on disk file */ + } + + /* read the data */ + n = read(inp, s, (size_t)hc); + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)sizeof(tc)); + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) { + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +int main (int argc, char *argv[]) +{ + char *buf; + size_t size_512K = 512 * 1024; + size_t buf_size = 512 * 1024; + char *cp, *np; + int ll; + char path[64], command[128]; +// int sdt = 1; + int sdt = 0; + + smd = 1; + + if (argc != 2) { + //fprintf(stderr, "usage: %s infile\n", argv[0]); + printf("usage: %s infile\n", argv[0]); + exit(1); + } /* end of if */ + + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) { + //fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + printf("%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + outp = -1; + + /* get a 512k buffer */ + if ((buf = malloc(buf_size)) == NULL) { + //fprintf(stderr, "Can't allocate memory for tscan\n"); + printf("Can't allocate memory for tscan\n"); + return (4); + } + /* init counts */ + ln = -2; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + filen = 1; + lfilen = 0; + printf("\nfile %d:\n", filen); + + /* get lines until eof */ + while ((ll=getloi(buf, buf_size)) != EOF) { + printf("got ll = %d filen %d\n", ll, filen); + if (ll == 1920) { + sdt = 1; /* process SDT tape */ + smd = 0; + printf("process sdt ll = %d\n", ll); + } + if (ll == 4608) { + sdt = 0; /* process SMD tape */ + smd = 1; + printf("process smd ll = %d\n", ll); + } + + if (ll == 0) { + /* eof found, process new file */ + printf("\nfile %d:\n", filen); + smd = 1; + sdt = 0; + continue; /* go look for another SDT bootfile or SMD entry */ + } else + if (ll != 1920 && ll != 4608) { + printf("File is not in MPX filemgr format and can not be processed!\n"); + break; + } else { + int cc = 0; + unsigned int curchar; + char filename[16]; + int i, j, m; + + /* SDT entries have 1920 bytes as first record. This is */ + /* followed by multiple 768 byte records to finish the SDT image */ + /* read the boot data from the sdt tape */ + /* check for SDT entry instead of SMD entry */ +// if (ll == 1920) +// if (sdt == 1 && filen == 1) + if (sdt == 1) { + int no, ct = 0;; + /* get more sdt data */ + /* open output file, create it if necessary */ + if (outp == -1) { + sprintf(filename, "bootfile%d\0", filen); +// if ((outp = open("bootfile", O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + if ((outp = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { + printf("Can't open bootfile\n"); + close(inp); + free(buf); + return (3); + } + } + printf("got2 ll = %d writing to bootfile -> %s\n", ll, filename); + no = write(outp, buf, ll); + if (no != ll) + // fprintf(stderr, "write (%d) != read (%d) on file %s\n", no, ll, path); + printf("write (%d) != read (%d) on file bootfile\n", no, ll); + /* get lines until eof */ + while ((ll=getloi(buf, buf_size)) > 0) { + ct++; + no = write(outp, buf, ll); + if (no != ll) + // fprintf(stderr, "write (%d) != read (%d) on file %s\n", no, ll, path); + printf("write (%d) != read (%d) on file bootfile\n", no, ll); + } + sdt = 0; + smd = 1; + close(outp); + outp = -1; + printf("wrote %d records to bootfile %s\n", ct, filename); + continue; /* go look for another SDT bootfile or SMD entry */ + } else + + /* filemgr smd entries are 8 words, and are in 1152 words (4608 bytes) + * (6 sector) blocks. Saved data files are modulo 1152 words also */ + /* 8 wds per SMD entry, 24 entries per sector, 144 entries per 6 sector + * block. */ +// printf("gotx ll = %d filen %d\n", ll, filen); +// if (filen == 1) + if (smd == 1) { + /* check for SMD entry instead of SDT entry */ + /* read smd entry */ + char file[20], dir[20]; + int l = 0; + int smddone = 0; + int totent = 0; + char *buf2 = buf; +// printf("\nfile %d: %d\n", filen, ll); + /* see how many entries here */ + while(!smddone) { + /* process entries in this record */ + for (j=0; j<144; j++) { + int k = l++ * 32; + int w1 = (buf[k+13] & 0xff) << 16 | (buf[k+14] & 0xff) << 8 | (buf[k+15] & 0xff); + /* stop processing on first zero smd entry */ + if (w1 <= 0) { + smddone = 1; + break; + } + totent++; + /* get file/dir name */ + for (i=0; i<8; i++) { + file[i] = tolower(buf[k+0+i]); + if (file[i] == ' ') + file[i] = '\0'; + } + file[8] = '\0'; + for (i=0; i<8; i++) { + dir[i] = tolower(buf[k+0+16+i]); + if (dir[i] == ' ') + dir[i] = '\0'; + } + dir[8] = '\0'; + if (dir[0] == '\0') + sprintf(dir, "%s", "system"); + sprintf(path, "./%s/%s", dir, file); + // see if active file + if ((buf[k+12] & 0x80) == 0) + // not active goon + printf("inactive file: w1 = %d path = %s\n", w1, path); + else + printf("active file: w1 = %d path = %s\n", w1, path); + } + if (smddone) + break; + buf2 += 4608; /* next buffer */ + ll=getloi(buf2, 4608); + } + printf("%d smd entries found\n", totent); + /* we have directory entries */ + for (j=0; j= 0) + close(outp); + outp = -1; + +#ifndef DO_LATER + /* open output file, create it if necessary */ + if ((outp = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { + //fprintf(stderr, "Can't open %s\n", path); + printf("Can't open %s\n", path); + close(inp); + free(buf); + return (3); + } +#endif + /* get the file data */ + for (m=0; m<((w1+5)/6); m++) { + char data[5000]; /* data buffer */ + ll=getloi(data, 4608); + + /* process file data for file */ + if (ll == 4608) { +#ifndef DO_LATER + /* blks/w1 have number of blocks to write */ + int bcnt, no; /* block count */ + if (blks >= 6) { + blks -= 6; /* enough for 6 block, write them */ + bcnt = 6*768; /* write all 6 blocks */ + } else { + bcnt = blks*768;/* just write what we need */ + blks = 0; + } + /* only write number of sectors on save tape, not all 4608 */ + /* if zero, just reading excess blocks */ + if (bcnt != 0) { + no = write(outp, data, bcnt); + if (no != bcnt) + // fprintf(stderr, "write (%d) != read (%d) on file %s\n", no, bcnt, path); + printf("write (%d) != read (%d) on file %s\n", no, bcnt, path); + } +#else + if (m == 0) + printf("reading file %s\n", path); +#endif + } else { + printf("Bad file size read! %d instead of 4608\n", ll); +/// if (ll == -1) break; + if (ll == -1) + goto dostop; + } + } /* end writing file */ + } /* end of smd scan */ + } /* read smd entries 4608 byte records */ + } /* process read of smd or sdt */ + } /* end of getloi read */ +dostop: + close(inp); + free(buf); + if (outp >= 0) + close(outp); + exit(0); +} diff --git a/SEL32/taptools/small.c b/SEL32/taptools/small.c new file mode 100644 index 0000000..44172e3 --- /dev/null +++ b/SEL32/taptools/small.c @@ -0,0 +1,63 @@ +/* + * small.c + * + * This program deletes trailing blanks from a source file + * input - stdin + * output - stdout + */ + +#include +#include + +int getloi(); +int putloi(); + +int main(argc, argv) +int argc; +char *argv[]; +{ + char s[BUFSIZ]; + + while(1) { + if (getloi(s, BUFSIZ) == 0) + exit(0); + putloi(s); + } +} + +/* get a line of input. */ +int getloi(s, lim) /* right from the book. */ +char s[]; +int lim; +{ + int c, i; + + for (i = 0; --lim > 0 && (c = getchar()) != EOF && (s[i++] = c) != '\n'; ) + { + ; + } +#define STRIP_LINE +#ifdef STRIP_LINE + if (i > 73) + i = 73; + s[72] = '\n'; + s[73] = '\0'; +#endif + if ((s[i-1] == '\n') && (i > 1)) + { + while (((s[i-2] == ' ') || (s[i-2] == '\r')) && (i > 1)) + --i; + s[i-1] = '\n'; + } + s[i] = '\0'; + return (i); +} + +/* + ** output line of text from the source + */ +int putloi(s) +char *s; +{ + printf("%s", s); +} diff --git a/SEL32/taptools/tapdump.c b/SEL32/taptools/tapdump.c new file mode 100644 index 0000000..913c00a --- /dev/null +++ b/SEL32/taptools/tapdump.c @@ -0,0 +1,245 @@ +/* + * tapdump.c + * + * This program scans a metatape file and displays the file content as + * a side by side hex dump of the contents. + * input - stdin or specified filename + * output - stdout + */ + +#include +#include +#include +#include +#include +#include + +int filen = 1; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int size_512K = 512 * 1024; +int ln; +int inp; +#define PRINTABLE(x) ((x < 32) || (x > 126)) ? '.' : x + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int32_t n1, n2, hc, tc, n; + + errno = 0; + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 <= 0) + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) /* check for garbage, assume EOM */ + hc = -1; /* at EOM on disk file */ + + if (hc == 0) + { + /* we are at tape EOF */ + if (++EOFcnt < 2) /* if 1st EOF, print file info */ + { +#ifndef NOTDUMP + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + fprintf(stderr, "file %d: eof after %d records: %d bytes\n", filen, count, size); +#endif + filen++; /* set next file number */ + } + else + { +#ifndef NOTDUMP + fprintf(stderr, "second eof after %d files: %d bytes\n", filen, size); +#endif + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + + /* we have EOF */ + return 0; /* return EOF on tape data */ + } + if (hc == -1) + { +#ifndef NOTDUMP + /* we have EOM */ + fprintf(stderr, "mpx eot\n"); + /* print out total tape size in bytes */ + fprintf(stderr, "total length: %ld bytes\n", tsize); +#endif + return -1; /* at EOM on disk file */ + } + /* read the data */ + n = read(inp, s, (size_t)hc); + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)sizeof(tc)); + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) + { +#ifndef NOTDUMP + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } +#endif + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +int main (int argc, char *argv[]) +{ +// char in[BUFSIZ], out[BUFSIZ]; + char *buf; + size_t size_512K = 512 * 1024; + size_t buf_size = 512 * 1024; + char *cp, *np; + int ll, gotboth = 0; + int lfilen = filen; + unsigned int fileaddr, file_byte_count=0, curchar, buffptr, bufflen; + int skipfile = 0; + + if (argc != 2) + { + fprintf(stderr, "usage: %s infile\n", argv[0]); + exit(1); + } /* end of if */ + + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) + { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + + /* get a 512k buffer */ + if ((buf = malloc(buf_size)) == NULL) + { + fprintf(stderr, "Can't allocate memory for %s\n", argv[0]); + return (4); + } + /* init counts */ + ln = -2; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + filen = 1; + lfilen = filen; + buffptr = 0; + bufflen = 16; + fileaddr = 0; + file_byte_count = 0; + printf("\nfile %d:\n", filen); + + /* get lines until eof */ + while ((ll=getloi(buf, buf_size)) != EOF) + { + if (ll == 0) + { + /* eof found, process new file */ + skipfile = 0; + file_byte_count = 0; + fileaddr = 0; + printf("\nfile %d:\n", filen); + } + else + { + int cc = 0; + buffptr = 0; + char buff[257]; + int ans; + + /* see if skipping to next file */ + if (skipfile == 1) + { + continue; + } + + /* process the returned buffer */ + while (cc < ll) + { + curchar = (unsigned int)buf[cc++] & 0xff; + file_byte_count++; + if (!buffptr) + printf(" %06x : ",fileaddr); + printf("%02x", curchar & 0xff); + buff[buffptr++] = PRINTABLE(curchar); + if (!(buffptr % 4)) + printf(" "); + if (buffptr >= bufflen) + { + buff[buffptr] = 0; + printf(" |%s|\n",buff); + buffptr = 0; + fileaddr += bufflen; + if (!(file_byte_count % 256)) +// if (!(file_byte_count % 768)) + { + printf("\n - continue, q = quit, s = skip > "); + ans = getchar(); + if (ans == 'q') + { + close(inp); + free(buf); + exit(1); + } + if (ans == 's') + skipfile = 1; + if (ans != '\n') + while ((ans=getchar()) != '\n' ) + ; + } /* end of if */ + if (skipfile == 1) + break; + } /* end of if */ + } /* end of while */ + + if (buffptr && !skipfile) + { + buff[buffptr] = 0; + while (buffptr++ < bufflen) + { + printf(" "); + if (!(buffptr % 4)) + printf(" "); + } /* end of while */ + printf(" |%s|\n",buff); + + /* see what user wants to do */ + printf("\n - continue, q = quit > "); + ans = getchar(); + if (ans == 'q') + { + close(inp); + free(buf); + exit(1); + } + if (ans != '\n') + while ((ans=getchar()) != '\n' ) + ; + } /* end of if */ + } + } + close(inp); + free(buf); + exit(0); +} diff --git a/SEL32/taptools/tape2disk.c b/SEL32/taptools/tape2disk.c new file mode 100644 index 0000000..f86e032 --- /dev/null +++ b/SEL32/taptools/tape2disk.c @@ -0,0 +1,244 @@ +/* + * MPX uses 2 EOF in a row to separate sections of MPX3.x master SDT tapes. + * It uses 3 EOF in a row to indicate the EOT on MPX 3.X tapes. So we + * cannot assume EOT is at the 1st or 2nd EOF in a row. Keep looking + * for a third one. Comment out the #define FMGRTAPE below to read an + * MPX 3.x master SDT. For user SDT tapes or MPX 1.X master SDT tapes + * leave the #define FMGRTAPE uncommented so it will be defined. The + * program will stop on two EOFs. For non MPX tapes, the 2nd EOF means + * EOT. Some tapes have only one EOT and will termonate on EOT detected. + * Leave off the output file name to just scan the tape and output record + * sizes and counts. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define FMGRTAPE /* defined for filemgr tapes, undefined for volmgr tape */ + +char *buff; /* buffer for read/write */ +int filen = 1; /* file number being processed */ +long count=0, lcount=0; /* number of blocks for file */ +extern void RUBOUT(); /* handle user DELETE key signal */ +off_t size=0, tsize=0; /* number of bytes in file, total */ +int ln; +char *inf, *outf; +int copy; +size_t size_128K = 128 * 1024; +size_t size_256K = 256 * 1024; + +int main(argc, argv) +int argc; +char **argv; +{ + int n, nw, inp, outp; + struct mtop op; + size_t buf_size = size_256K; + int EOFcnt = 0; /* count the number of EOFs in a row. */ + + if (argc <= 1 || argc > 3) + { + (void)fprintf(stderr, "Usage: tape2disk src [dest]\n"); + return (1); + } + inf = argv[1]; + if (argc == 3) + { + outf = argv[2]; + copy = 1; + } + if ((inp = open(inf, O_RDONLY, 0666)) < 0) + { + (void)fprintf(stderr, "Can't open %s\n", inf); + return (1); + } + if (copy) + { + /* open output file, create it if necessary */ + if ((outp = open(outf, O_WRONLY|O_CREAT, 0666)) < 0) + { + (void)fprintf(stderr, "Can't open %s\n", outf); + return (3); + } + } + /* get a 128k buffer */ + if ((buff = malloc(buf_size)) == NULL) + { + (void)fprintf(stderr, "Can't allocate memory for tapecopy\n"); + return (4); + } + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + (void)signal(SIGINT, RUBOUT); + + ln = -2; + for (;;) + { + count++; + errno = 0; + /* read first record to get size for buffer, doubling each time unsuccessful */ + while ((n = read(inp, buff, buf_size)) < 0) + { + if (errno == ENOMEM) + { + if (buf_size < size_256K) + buf_size = size_256K; + else + buf_size *= 2; + free(buff); + if ((buff = malloc(buf_size)) == NULL) + { + (void)fprintf(stderr, "Can't allocate memory for tapecopy\n"); + return (4); + } + op.mt_op = MTFSF; /* Rewind to start of file */ + op.mt_count = (daddr_t) 0; + if (ioctl(inp, MTIOCTOP, (char *)&op) < 0) + { + perror("Read buffer size error"); + return (6); + } + errno = 0; + continue; + } + perror("Unknown read error"); + errno = 0; +// return (6); /* abort on error, comment out to ignore taoe errors */ + } + if (n > 0) + { + /* we read some data, see if scanning or writing */ + EOFcnt = 0; /* not at EOF anymore */ + if (copy) + { + int n1, n2; + /* we have data to write */ + int hc = (n + 1) & ~1; /* make byte count even */ + /* write actual byte count to 32 bit word as header */ + n1 = write(outp, (char *)(&hc), (size_t)sizeof(hc)); + /* write the data mod 2 */ + nw = write(outp, buff, (size_t)hc); + /* write the byte count in 32 bit word as footer */ + n2 = write(outp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 != sizeof(hc) || nw != hc || n2 != sizeof(hc)) + { + fprintf(stderr, "write (%d) !=" " read (%d)\n", nw, n); + fprintf(stderr, "COPY " "Aborted\n"); + return (5); + } + } + size += n; /* update bytes read */ + if (n != ln) /* must be last record of file if different */ + { + if (ln > 0) + { + /* we read something */ + if ((count - lcount) > 1) + (void)printf("file %d: records %ld to %ld: size %d\n", filen, lcount, count - 1, ln); + else + (void)printf("file %d: record %ld: size %d\n", filen, lcount, ln); + } + ln = n; /* save last record size */ + lcount = count; /* also record count */ + } + } + else + { + /* we did not read data, it must be an EOF */ + /* if ln is -1, last operation was EOF, now we have a second */ +#ifdef FMGRTAPE + /* filemgr has 2 EOF's at end of tape */ + if (++EOFcnt > 1) + { + /* two EOFs mean we are at EOT */ + (void)printf("fmgr eot\n"); + break; + } +#else + /* volmgr has 3 EOF's at end of tape */ + if (++EOFcnt > 2) + { + /* three EOFs mean we are at EOT on MPX */ + (void)printf("volm eot\n"); + break; + } +#endif + if (ln > 0) + { + if (count - lcount > 1) + (void)printf("file %d: records %ld to %ld: size %d\n", filen, lcount, count - 1, ln); + else + (void)printf("file %d: record %ld: size %d\n", filen, lcount, ln); + } +#ifdef FMGRTAPE + (void)printf("file %d: eof after %ld records: %ld bytes\n", filen, count - 1, size); +#else + if (EOFcnt == 2) /* if 2nd EOF, print file info */ + (void)printf("second eof after %d files: %ld bytes\n", filen, size); +#endif + if (copy) + { + /* write a sudo EOF to disk file as a zero 4 byte record */ + int n1, hc = 0; + /* write the EOF */ + /* write a zero as the byte count in 32 bit word as EOF */ + n1 = write(outp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 != sizeof(hc)) + { + perror("Write EOF"); + return (6); + } + } +#ifdef FMGRTAPE + filen++; /* advance number of files */ +#else + if (EOFcnt < 2) /* not really a file if 2nd EOF */ + filen++; /* advance number of files */ +#endif + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = n; /* set ln to -1 showing we are at EOF */ + } + } + if (copy) + { + /* write a sudo EOM to disk file as a -1 4 byte record */ + int n1, hc = 0xffffffff; + /* write the EOM to disk */ + /* write a -1 as the byte count in 32 bit word as EOM */ + n1 = write(outp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 != sizeof(hc)) + { + perror("Write EOM"); + return (6); + } + (void)close(outp); + } + /* print out total tape size in bytes */ + (void)printf("total length: %ld bytes\n", tsize); + return (0); +} + +/* entered when user hit the DELETE key */ +void RUBOUT() +{ + if (count > lcount) + --count; + if (count) + if (count > lcount) + (void)printf("file %d: records %ld to %ld: size" " %d\n", filen, lcount, count, ln); + else + (void)printf("file %d: record %ld: size %d\n", filen, lcount, ln); + (void)printf("interrupted at file %d: record %ld\n", filen, count); + (void)printf("total length: %ld bytes\n", tsize + size); + exit(1); +} diff --git a/SEL32/taptools/tapscan.c b/SEL32/taptools/tapscan.c new file mode 100644 index 0000000..7f5b464 --- /dev/null +++ b/SEL32/taptools/tapscan.c @@ -0,0 +1,155 @@ +/* + * tapscan.c + * + * This program scans a metatape file and prints file count and sizes. + * input - stdin or specified filename + * output - stdout + */ + +#include +#include +#include +#include +#include +#include + +int filen = 1; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int size_512K = 512 * 1024; +int ln; +#ifdef USE_READ +FILE *infp; +#else +int inp; +#endif + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int32_t n1, n2, hc, tc, n; + + errno = 0; + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 <= 0) + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) /* check for garbage, assume EOM */ + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc == 0) + { + /* we are at tape EOF */ + if (++EOFcnt < 2) /* if 1st EOF, print file info */ + { + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + fprintf(stderr, "file %d: eof after %d records: %d bytes\n", filen, count, size); + filen++; /* set next file number */ + } + else + { + fprintf(stderr, "second eof after %d files: %d bytes\n", filen-1, size); + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + + /* we have EOF */ + return 0; /* return EOF on tape data */ + } + if (hc == -1) + { + /* we have EOM */ + fprintf(stderr, "mpx eot\n"); + /* print out total tape size in bytes */ + fprintf(stderr, "total length: %ld bytes\n", tsize); + return -1; /* at EOM on disk file */ + } + /* read the data */ + n = read(inp, s, (size_t)hc); + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)sizeof(tc)); + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) + { + if (ln > 0) + { + if (count - lcount > 1) + fprintf(stderr, "file %d: records %d to %d: size %d\n", filen, lcount, count - 1, ln); + else + fprintf(stderr, "file %d: record %d: size %d\n", filen, lcount, ln); + } + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +int main (int argc, char *argv[]) +{ +// char in[BUFSIZ], out[BUFSIZ]; + char *buf; + size_t size_512K = 512 * 1024; + size_t buf_size = 512 * 1024; + char *cp, *np; + int ll, gotboth = 0; + + if (argc != 2) + { + fprintf(stderr, "usage: %s infile\n", argv[0]); + exit(1); + } /* end of if */ + +#ifdef USE_READ + /* open input file */ + infp = fopen(argv[1],"r"); + if (infp == NULL) { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + exit(1); + } /* end of if */ +#else + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) + { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } +#endif + + /* get a 512k buffer */ + if ((buf = malloc(buf_size)) == NULL) + { + fprintf(stderr, "Can't allocate memory for %s\n", argv[0]); + return (4); + } + + /* init counts */ + ln = -2; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + + /* get lines until eof */ + while (((ll=getloi(buf, buf_size)) != EOF)) + { + } + close(inp); + free(buf); + exit(0); +} diff --git a/SEL32/taptools/volmcopy.c b/SEL32/taptools/volmcopy.c new file mode 100644 index 0000000..b06b3bf --- /dev/null +++ b/SEL32/taptools/volmcopy.c @@ -0,0 +1,261 @@ +/* + * volmcopy.c + * + * This program scans a metatape file and prints file count and sizes. + * It is only for volmgr save images. Save images have the following format: + * One or more 6144 byte records containing a list of files saved 16 char file + * name followed my 16 char directory name followed by 16 char volume name. + * A 1536 byte file definition entry will be followed by 1 to 8 768 byte + * file data records followed by an EOF for each file. If the file size is + * greater than 6144 bytes, 1 or more 6144 byte records are output followed + * by last record modulo 768 bytes. Two EOFs in a row define the EOT. + * input - stdin or specified filename + * output - stdout + */ + +#include +#include +#include +#include +#include +#include +#include + +int filen = 1; +int EOFcnt = 0; +int count=0, lcount=0; +int size=0, tsize=0; +int size_512K = 512 * 1024; +int ln; +#ifdef USE_READ +FILE *infp; +#else +int inp, outp; +#endif +#define PRINTABLE(x) ((x < 32) || (x > 126)) ? '.' : x + +/* get a line of input. */ +int getloi(char *s, int lim) +{ + int c, i; + int n1, n2, hc, tc, n; + + errno = 0; + /* read the byte count in 32 bit word as header */ + n1 = read(inp, (char *)(&hc), (size_t)sizeof(hc)); + if (n1 <= 0) + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc & 0xffff0000) /* check for garbage, assume EOM */ + hc = -1; /* at EOM on disk file */ + + /* check for EOF & EOM on tape data */ + if (hc == 0) + { + /* we are at tape EOF */ + if (++EOFcnt < 2) /* if 1st EOF, print file info */ + { + filen++; /* set next file number */ + } + count = 0; /* file record count back to zero */ + lcount = 0; /* last record count back to zero */ + tsize += size; /* add to total tape size */ + size = 0; /* file size back to zero */ + ln = -1; /* set ln to -1 showing we are at EOF */ + + /* we have EOF */ + return 0; /* return EOF on tape data */ + } + if (hc == -1) + return -1; /* at EOM on disk file */ + + /* read the data */ + n = read(inp, s, (size_t)hc); + /* read the byte count in 32 bit word as trailer */ + n2 = read(inp, (char *)(&tc), (size_t)sizeof(tc)); + count++; /* bump record count */ + size += n; /* update bytes read */ + EOFcnt = 0; /* not an EOF */ + if (n != ln) + { + ln = n; + lcount = count; + } + /* return bytes in buffer */ + return n; +} + +int main (int argc, char *argv[]) +{ + char *buf; + size_t size_512K = 512 * 1024; + size_t buf_size = 512 * 1024; + char *cp, *np; + int ll; + int lfilen = filen; + char path[64], command[128]; + + if (argc != 2) + { + fprintf(stderr, "usage: %s infile\n", argv[0]); + exit(1); + } /* end of if */ + + if ((inp = open(argv[1], O_RDONLY, 0666)) < 0) + { + fprintf(stderr,"%s: fopen: unable to open input file %s\n", argv[0], argv[1]); + return (1); + } + outp = -1; + + /* get a 512k buffer */ + if ((buf = malloc(buf_size)) == NULL) + { + fprintf(stderr, "Can't allocate memory for tscan\n"); + return (4); + } + /* init counts */ + ln = -2; /* look for 2 eof */ + count = 0; + size = 0; + tsize = 0; + lcount = 0; + filen = 1; + lfilen = filen; + printf("\nfile %d:\n", filen); + + /* get lines until eof */ + while ((ll=getloi(buf, buf_size)) != EOF) + { + if (ll == 0) + { + /* eof found, process new file */ + printf("\nfile %d:\n", filen); + } + else + { + int cc = 0; + unsigned int curchar; + + /* dump first 2 words */ + int w1, w2, i, j; + w1 = (buf[0] & 0xff) << 24 | buf[1] << 16 | buf[2] << 8 | (buf[3] & 0xff); + w2 = (buf[4] & 0xff) << 24 | buf[5] << 16 | buf[6] << 8 | (buf[7] & 0xff); +// printf("w1 = %x, w2 = %d count = %d\n", w1, w2, count); + if (count == 1 && w1 == 1) + { + char file[20], dir[20], vol[20]; + int off = 8; + int l = 0; + /* we have directory entries */ + for (j=0; j (6144-48-off)) + { + ll=getloi(buf, buf_size); + off = 0; + l = 0; + k = 0; + printf("reread: got ll= %d\n", ll); + } + for (i=0; i<16; i++) + { + file[i] = tolower(buf[k+off+i]); + if (file[i] == ' ') + file[i] = '\0'; + } + file[16] = '\0'; + for (i=0; i<16; i++) + { + dir[i] = tolower(buf[k+off+16+i]); + if (dir[i] == ' ') + dir[i] = '\0'; + } + dir[16] = '\0'; + for (i=0; i<16; i++) + { + vol[i] = tolower(buf[k+off+32+i]); + if (vol[i] == ' ') + vol[i] = '\0'; + } + vol[16] = '\0'; + sprintf(path, "./%s/%s", vol, dir); + /* create the directory/file */ + sprintf(command, "mkdir -p %s", path); + system(command); + sprintf(path, "./%s/%s/%s", vol, dir, file); + sprintf(command, "touch %s", path); + system(command); + } + } else + if (count == 1 && w1 == 2 && w2 == 0) + { + char file[20], dir[20], vol[20]; + if (outp >= 0) + close(outp); + outp = -1; + /* process file definition */ + /* we have a file definition entry */ + for (i=0; i<16; i++) + { + file[i] = tolower(buf[8+i]); + if (file[i] == ' ') + file[i] = '\0'; + } + file[16] = '\0'; + for (i=0; i<16; i++) + { + dir[i] = tolower(buf[24+i]); + if (dir[i] == ' ') + dir[i] = '\0'; + } + dir[16] = '\0'; + for (i=0; i<16; i++) + { + vol[i] = tolower(buf[40+i]); + if (vol[i] == ' ') + vol[i] = '\0'; + } + vol[16] = '\0'; + sprintf(path, "./%s/%s/%s", vol, dir, file); + printf("path = %s\n", path); + + /* open output file, create it if necessary */ + if ((outp = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + { + (void)fprintf(stderr, "Can't open %s\n", path); + close(inp); + free(buf); + return (3); + } + /* process file data for file */ + if (ll > 1536) + { + int no = write(outp, buf+1536, ll-1536); + if (no != ll) + fprintf(stderr, "write (%d) != read (%d) on file %s\n", no, ll, path); + } + } else + if (count > 1) + { + /* process file data for file */ + int no = write(outp, buf, ll); + if (no != ll) + fprintf(stderr, "write (%d) != read (%d) on file %s\n", no, ll, path); + } + + /* process the returned buffer */ +// while (cc < ll) +// { +// curchar = (unsigned int)buf[cc++] & 0xff; +// } /* end of while */ + } + } + close(inp); + free(buf); + if (outp >= 0) + close(outp); + exit(0); +}