#ident "@(#)glib.c 1.5 91/04/01 XGRASP" /*- * glib.c - GRASP graphics librarian. * * Copyright (c) 1991 by Patrick J. Naughton * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * Comments and additions should be sent to the author: * * Patrick J. Naughton * Sun Microsystems * 2550 Garcia Ave, MS 10-20 * Mountain View, CA 94043 * (415) 336-1080 * */ #include #include char *pname; extern char *strrchr(); typedef struct { char fname[14]; long offset; long len; char *data; } FilenameStruct; void error(s1, s2, s3) char *s1, *s2, *s3; { fprintf(stderr, s1, pname, s2, s3); exit(1); } u_int GetWord(fp) FILE *fp; { u_char b1 = (u_char) getc(fp); u_char b2 = (u_char) getc(fp); return (u_int) (b1 + b2 * 256); } u_int GetLong(fp) FILE *fp; { u_char b1 = (u_char) getc(fp); u_char b2 = (u_char) getc(fp); u_char b3 = (u_char) getc(fp); u_char b4 = (u_char) getc(fp); return (u_int) (b1 + b2 * 256 + b3 * 256 * 256 + b4 * 256 * 256 * 256); } void PutWord(fp, w) FILE *fp; unsigned int w; { unsigned char b1 = w & 255; unsigned char b2 = (w >> 8) & 255; putc(b1, fp); putc(b2, fp); } void PutLong(fp, l) FILE *fp; unsigned int l; { unsigned char b1 = l & 255; unsigned char b2 = (l >> 8) & 255; unsigned char b3 = (l >> 16) & 255; unsigned char b4 = (l >> 24) & 255; putc(b1, fp); putc(b2, fp); putc(b3, fp); putc(b4, fp); } void extractfile(in, dir, i) FILE *in; FilenameStruct *dir; int i; { int len; char *data; FILE *out; fseek(in, dir[i].offset, 0); len = GetLong(in); len &= 0x00ffffff; data = (char *) malloc(len); if (!data) error("%s: not enough memory\n"); fread(data, len, 1, in); out = fopen(dir[i].fname, "w"); if (!out) error("%s: error writing: %s\n", dir[i].fname); fwrite(data, len, 1, out); fclose(out); free(data); } void writefile(fname, dir, nfiles) char *fname; FilenameStruct *dir; int nfiles; { FILE *out; int i; long offset = 2 + (nfiles + 1) * (13 + 4); out = fopen(fname, "w"); PutWord(out, (nfiles + 1) * (13 + 4)); for (i = 0; i < nfiles; i++) { PutLong(out, offset); offset += dir[i].len + 4; fwrite(dir[i].fname, 13, 1, out); } PutLong(out, 0); fwrite(" ", 13, 1, out); for (i = 0; i < nfiles; i++) { PutLong(out, dir[i].len); fwrite(dir[i].data, dir[i].len, 1, out); } fclose(out); } int findname(dir, nfiles, s) FilenameStruct *dir; int nfiles; char *s; { int i; if (dir) for (i = 0; i < nfiles; i++) if (!strcmp(dir[i].fname, s)) return i; return -1; } usage() { error("usage: %s [-dstuea] libname [files...]\n", NULL); } main(argc, argv) int argc; char *argv[]; { int i; FILE *in; FILE *out; char *libfname; char *opfname; int nfiles = 0; FilenameStruct *dir = 0; int thefile = -1; int c; int dflg = 0; int sflg = 0; int tflg = 0; int uflg = 0; int eflg = 0; int aflg = 0; extern char *optarg; extern int optind; pname = argv[0]; if (argc == 1) usage(); while ((c = getopt(argc, argv, "hd:s:t:u:e:a:")) != -1) switch (c) { case 'h': printf("\nusage: glib [-dstuea] libname [files...]\n"); printf("\n where the following commands are supported:\n\n"); printf("\t-d delete file from library\n"); printf("\t-s extended file list\n"); printf("\t-t quick file list\n"); printf("\t-u update (add) file to library\n"); printf("\t-e extract file from library\n"); printf("\t-a extract all files from library\n\n"); exit(0); case 'd': if (uflg || eflg || aflg) usage(); else dflg++; libfname = optarg; break; case 's': if (tflg) usage(); else sflg++; libfname = optarg; break; case 't': if (sflg) usage(); else tflg++; libfname = optarg; break; case 'u': if (dflg || eflg || aflg) usage(); else uflg++; libfname = optarg; break; case 'e': if (dflg || uflg || aflg) usage(); else eflg++; libfname = optarg; break; case 'a': if (dflg || uflg || eflg) usage(); else aflg++; libfname = optarg; break; default: usage(); } if (!libfname) usage(); in = fopen(libfname, "r"); if (!in && !uflg) error("%s: %s not found!\n", libfname); if (in) { nfiles = (GetWord(in) / 17) - 1; dir = (FilenameStruct *) malloc(nfiles * sizeof(FilenameStruct)); for (i = 0; i < nfiles; i++) { dir[i].offset = GetLong(in); fread(dir[i].fname, 13, 1, in); dir[i].fname[13] = 0; if (dflg || eflg) { if (!strcmp(dir[i].fname, argv[optind])) thefile = i; } } if ((dflg || eflg) && thefile == -1) error("%s: %s not found in %s.\n", argv[optind], libfname); if (sflg || tflg || dflg || uflg) { if (sflg) printf("## filename.ext\toffset\tsize\n%s", "-- ------------\t------\t----\n"); for (i = 0; i < nfiles; i++) { fseek(in, dir[i].offset, 0); dir[i].len = GetLong(in); dir[i].len &= 0x00ffffff; if (sflg) printf("%2d %s\t%d\t%d\n", i, dir[i].fname, dir[i].offset, dir[i].len); else if (tflg) printf("%s%c", dir[i].fname, (i + 1) % 4 && i + 1 < nfiles ? '\t' : '\n'); if (dflg || uflg) { dir[i].data = (char *) malloc(dir[i].len); if (!dir[i].data) error("%s: not enough memory\n"); fread(dir[i].data, dir[i].len, 1, in); } } } } if (eflg) { extractfile(in, dir, thefile); fclose(in); } else if (aflg) { for (i = 0; i < nfiles; i++) extractfile(in, dir, i); fclose(in); } else if (dflg) { fclose(in); nfiles--; for (i = thefile; i < nfiles; i++) memcpy(&dir[i], &dir[i + 1], sizeof(FilenameStruct)); writefile(libfname, dir, nfiles); } else if (uflg) { if (in) fclose(in); for (i = optind; i < argc; i++) { char *s = argv[i]; char *fn = strrchr(s, '/'); int n; int idx; fn = (fn == 0) ? s : fn + 1; n = strlen(fn); if (n > 13) error("%s: '%s' is too long, must be < 13 chars.\n", s); idx = findname(dir, nfiles, fn); if (idx == -1) { nfiles++; if (!dir) dir = (FilenameStruct *) malloc(sizeof(FilenameStruct)); else dir = (FilenameStruct *) realloc(dir, nfiles * sizeof(FilenameStruct)); idx = nfiles - 1; } else free(dir[idx].data); memset(dir[idx].fname, 0, 14); memcpy(dir[idx].fname, fn, n); in = fopen(s, "r"); if (!in) error("%s: %s not found!\n", s); fseek(in, 0L, 2); /* eof */ dir[idx].len = ftell(in); fseek(in, 0L, 0); /* bof */ dir[idx].data = (char *) malloc(dir[idx].len); if (!dir[idx].data) error("%s: not enough memory\n"); fread(dir[idx].data, dir[idx].len, 1, in); fclose(in); } writefile(libfname, dir, nfiles); } exit(0); }