/* iffar - IFF CAT archiver table of contents functions By Karl Lehenbauer, version 1.2, release date 5/9/88. This code is released to the public domain. See the README file for more information. */ #include #include #include #include #include "assert.h" #include "iff.h" #define ID_NAME MakeID('N','A','M','E') #define ID_AUTH MakeID('A','U','T','H') #define ID_ANNO MakeID('A','N','N','O') #define ID_Copyright MakeID('(','c',')',' ') extern long lseek(); extern ULONG nextchunk(); int table_of_contents(fname) char *fname; { int fd; ULONG cat_type, chunkid, innerchunkid, subtype; long chunksize, innerchunksize, filesize; char namebuf[256]; extern int verbose; if ((fd = OpenCAT(fname,&cat_type,&filesize)) == -1) { fprintf(stderr,"Can't open archive '%s'\n",fname); return(0); } if (verbose) { fprintf(stderr,"CAT subtype is "); PutID(cat_type); fprintf(stderr,"\n"); } while ((chunkid = nextCATchunk(fd,&subtype,&namebuf[0],&chunksize,&filesize)) != 0L) { /* if the chunk type isn't FORM, CAT or LIST, skip it */ if (chunkid != ID_FORM && chunkid != ID_CAT && chunkid != ID_LIST) { if (verbose) { PutID(chunkid); fprintf(stderr," chunk is being skipped\n"); } skipchunk(fd,chunksize,&filesize); goto bigchunkdone; } if (namebuf[0] == '\0') { fprintf(stderr,"CAT entry didn't contain a FNAM chunk - skipping\n"); skipchunk(fd,chunksize,&filesize); goto bigchunkdone; } PutID(chunkid); fprintf(stderr," "); /* print out the chunk length */ PutID(subtype); fprintf(stderr," %6ld %s\n",chunksize, namebuf); /* if verbose isn't selected, skip the rest of the chunks in the * embedded FORM, CAT or LIST */ if (!verbose) { skipchunk(fd,chunksize,&filesize); goto bigchunkdone; } /* else verbose is selected, dive down into the embedded FORM, * CAT or LIST and print chunks found there and their contents * when they're known to be text. */ /* follow a good neighbor policy by reducing our (the parent's) * chunk size by the size we've found - since we'll be moving * through the embedded FORM effectively recursively; that is, * we'll be using the same nextchunk, skipchunk, readchunk * routines on the chunk nextchunk got for us, we'll * decrease parent chunk size by the size we've found, * as, when calling nextchunk, skipchunk and readchunk below, * we'll be concerned with keeping track of the form's chunk length * as a virtual EOF, rather than the whole CAT's as above */ filesize -= chunksize; if (chunksize & 1) filesize--; while (chunksize != 0) { /* get the type and size of the inner chunk */ innerchunkid = nextchunk(fd,&innerchunksize,&chunksize); if (chunksize == 0) break; /* print some presumably useful information */ fprintf(stderr," "); PutID(innerchunkid); switch(innerchunkid) { case ID_FNAM: panic("more than one FNAM chunk in an embedded FORM"); case ID_NAME: case ID_AUTH: case ID_ANNO: case ID_Copyright: if (innerchunksize >= sizeof(namebuf)) { fprintf(stderr,"[too long]\n"); skipchunk(fd,innerchunksize,&chunksize); } else { if (!readchunk(fd,namebuf,innerchunksize,&chunksize)) { fprintf(stderr,"got into trouble reading chunk text\n"); return(0); } namebuf[innerchunksize] = '\0'; fprintf(stderr,", %s\n",namebuf); } break; default: fprintf(stderr,", size %ld\n",innerchunksize); /* skip the body of the subchunk */ skipchunk(fd,innerchunksize,&chunksize); } } /* we make it to here if the length of all the subchunks equalled * the length of their superchunk */ bigchunkdone: ; } close(fd); } /* end of toc.c */