/* * A program to extract all files from a "Novosielski" archive (foo.LBR) * * Jeff Martin, 10/9/82 * * 11/24/89 - Increased library entries from 64 to 256. (BP) * * 07/28/84 - Fixed AZTEC conditional defines. (Tried it this * time, instead of guessing). Removed DESMET stuff, * as the Read() function dosen't always know how many * bytes it has read! That didn't work too well. * * 06/10/84 - Kludged up to work with a variety of unix-like compilers. * BUFFERING added. * * 04/07/84 - reworked to compile under DeSmet 'C' Compiler * for use under CP/M-86 Peter A. Polansky * * 01/01/83 - Bug in large LBR files removed. --JEC * * 11/12/83 - CP/M 68k version created. Jim Cathey * * 01/03/83 - BDS version reworked to provide the generally-useful * getldir() function --JCM * * 01/02/83 - BDS C version created --JCM * * 11/27/82 - Fixed bug that was causing one-sector files to * be rejected as invalid directory entries --JCM */ /* "#define" your compiler here to pick from following #define blocks */ /* DRC, C86, and AZTEC have all been tested */ #define AZTEC #ifdef DRC /* digital research */ #define VERSION "1.1 6-Jun-84 DRC" #include #define OPN openb /* open a file, binary mode */ #define FOPN fopenb /* open a buffered file, binary mode */ #define CRET creatb /* create a file, binary mode */ #define FO_BREAD "r" /* read mode for fopen() */ #define O_RDONLY 0 /* binary read for open() */ #define C_BWRITE 0 /* binary write for creat() */ /* doesn't matter, DRC ignores mode on creat */ #define FGETC fgetc #endif #ifdef CIC86 /* computer innovations */ #define VERSION "1.1 6-Jun-84 CI C86" #define OPN open #define FOPN fopen #define CRET creat #define FO_BREAD "rb" #define O_RDONLY 4 #define C_BWRITE 5 #define FGETC fgetc #endif #ifdef AZTEC /* aztec c ii v 1.05 */ #define VERSION "1.1 28-Jul-84 Aztec" #include #define OPN open #define FOPN fopen #define CRET creat #define FO_BREAD "r" #define C_BWRITE 0666 #define FGETC getc #endif #define NAMESIZE 13 /* Max chars in filename.typ, plus null */ #define MAXDIRENT 256 /* Increased from 64 (BP) */ #define TOOBIG 1024 /* Assume dir is bad if > this many sectors */ #define SECSIZ 128 #define BUFFSIZ 16384 /* be sure this is a multiple of 128 */ #define ERR (-1) #include main(argc, argv) int argc; char *argv[]; { int c, i; char *s, *buf; char filename[20]; int fdi, fdo; /* file descriptors */ int ndir, dirent; char names[MAXDIRENT][NAMESIZE]; long offsets[MAXDIRENT]; unsigned sizes[MAXDIRENT]; int temp, toRead, didRead; long lseek(), bytes; while (--argc > 0 && (*++argv)[0] == '-') { for (s = argv[0]+1; *s != '\0'; s++) { switch (*s) { default: printf("Illegal Option: '%c'\n", *s); argc = 0; break; } } } if (argc != 1) { printf("delbr v%s\n",VERSION); printf("Usage: delbr filename(.LBR assumed)\n"); printf("Strip all files from a \"Novosielski\" archive.\n"); exit(1); } if ((buf= malloc(BUFFSIZ)) == NULL) /* get memory for buffer */ { printf("Not enough memory. MALLOC returned NULL\n"); exit(0); } strcpy(filename,argv[0]); strcat(filename,".lbr"); upcase(filename); if ((ndir= getldir(filename,MAXDIRENT,names,offsets,sizes)) == ERR) { printf("Trouble getting directory from %s\n", filename); exit (2); } fdi = OPN(filename, O_RDONLY); if (fdi == ERR) { printf("Cannot open %s.\n", filename); exit(2); } for (dirent = 0; dirent < ndir; dirent++) { if ((fdo = CRET(names[dirent], C_BWRITE)) == ERR) { printf("Cannot create %s.\n", names[dirent]); exit(2); } printf("Extracting: %-12s\n", names[dirent]); if (lseek(fdi, offsets[dirent], 0) == ERR) { printf("\nError seeking this entry - aborting.\n"); exit(2); } bytes= (long) sizes[dirent] * 128L; while (bytes != 0L) { if (bytes > (long) BUFFSIZ) { toRead= BUFFSIZ; bytes-= BUFFSIZ; } else { toRead= bytes; bytes= 0L; } if ((didRead= read(fdi, buf, toRead)) != toRead) { printf("\nError reading this entry - aborting. Read %u bytes\n",didRead); exit (2); } if (write(fdo, buf, toRead) != toRead) { printf("\nError writing this entry - aborting.\n"); exit (2); } } close(fdo); } printf("\n"); close(fdi); } /* * Get .LBR directory -- names, offsets, and sizes of entries in an LBR file. * * The returned function value is the number of actual entries found, * or ERR (if couldn't open file). * * Input parameters: * * fname - pointer to the string containing the full pathname of the LBR * file. * maxent - maximum number of entries to get (i. e., usually the size of * the following arrays). * files - pointer to an array of filenames to be populated by this function. * This array must have a column dimension of NAMESIZE. * offsets - pointer to an array of file offsets, in units of bytes, to * be populated by this function. * sizes - pointer to an array of file sizes, in units of CPM sectors, to be * populated by this function. */ getldir(fname, maxent, files, offsets, sizes) char *fname; int maxent; char files[][NAMESIZE]; long offsets[]; unsigned sizes[]; { int c, i, j; char *s; char entryname[20]; FILE *dir, *FOPN(); int ndir, dirent, nentry; long ostart; unsigned osize; if ((dir = FOPN(fname, FO_BREAD)) == 0) return (ERR); fskip(dir, 14); /* Point to dir size */ ndir = FGETC(dir); ndir = (ndir + (FGETC(dir)<<8))*4; fskip(dir, 16); /* Skip unused dir bytes */ nentry = 0; /* Init count of live entries */ for (dirent = 1; (dirent < ndir) && (nentry < maxent); dirent++) { if (FGETC(dir) != 0) { /* Ignore defunct entries in dir */ fskip(dir, 31); continue; } /* Build the next entryname */ j = 0; for (i=1; i<=8; i++) { c = FGETC(dir) & 0x7f; c = tolower(c); if(c != ' ') entryname[j++] = c; } entryname[j++] = '.'; for (i=1; i<=3; i++) { c = FGETC(dir) & 0x7f; c = tolower(c); if(c != ' ') entryname[j++] = c; } entryname[j] = '\0'; upcase(entryname); /* Check for any no-no chars. */ for (s = entryname; *s != '\0'; s++) if (*s == ';' || *s == '*' || *s < ' ') *s = '.'; strcpy(files[nentry], entryname); /* Return the hacked name */ /* Determine where this file is in the archive */ ostart = FGETC(dir); ostart |= FGETC(dir) << 8; ostart *= SECSIZ; offsets[nentry] = ostart; /* Return the file's offset */ osize = FGETC(dir); osize |= FGETC(dir) << 8; sizes[nentry] = osize; /* ... and its size */ fskip(dir, 16); /* Skip unused dir bytes */ nentry++; } fclose(dir); return (nentry); } /* * Skip specified number of bytes in the specified file */ fskip(file, bytes) FILE *file; int bytes; { while (bytes-- > 0) FGETC(file); } /* * Uppercase a string */ upcase(str) char *str; { for ( ; *str; ++str) *str = toupper(*str); }