/* iffar - IFF CAT archiver extractor 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 <exec/types.h>
#include <exec/memory.h>
#include <stdio.h>
#include <fcntl.h>
#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 extract(archive_name,fnames,nfiles)
char *archive_name;
char *fnames[];
int nfiles;
{
	int archive_fd, outfd;
	ULONG cat_type, chunkid, innerchunkid, subtype;
	long chunksize, innerchunksize, filesize;
	char textbuf[256], *extract_name;
	long placeholder;
	int do_extract, i;

	extern int verbose;

	if ((archive_fd = OpenCAT(archive_name,&cat_type,&filesize)) == -1)
	{
		fprintf(stderr,"Can't open archive '%s'\n",archive_name);
		return(0);
	}

	while ((chunkid = nextCATchunk(archive_fd,&subtype,&textbuf[0],&chunksize,&filesize)) != 0L)
	{
		/* if the chunk type isn't FORM, CAT or LIST, skip it 'cuz it
		 * isn't anything we know how to extract */
		if (chunkid != ID_FORM && chunkid != ID_CAT && chunkid != ID_LIST)
		{
			if (!skipchunk(archive_fd,chunksize,&filesize))
			{
				perror(archive_fd);
				fprintf(stderr,"extract: skipchunk failed\n");
				return(0);
			}
			break;
		}

		/* if no extract names (nfiles == 0) were specified, extract all
		 * files, so extract this one, else search to see if this name
		 * is one specified in fnames, an array of pointers to char
		 * strings */
		do_extract = 0;
		if (nfiles == 0)
		{
			do_extract = 1;
			extract_name = textbuf;
		}
		else
		{
			for (i = 0; i < nfiles; i++)
			{
				if (!strnicmp(basename(fnames[i]),textbuf,128))
				{
					do_extract = 1;
					extract_name = fnames[i];
					break;
				}
			}
		}
		/* if we did decide to extract it, extract it */
		if (do_extract)
		{
			if (verbose)
				fprintf(stderr,"extracting %s\n",extract_name);

			/* create, open and truncate the extract file */
			if ((outfd = open(extract_name,O_RDWR|O_CREAT|O_TRUNC)) == -1)
			{
				perror(textbuf);
			}
			else
			{
				if (!WriteSuperChunkHeader(outfd,chunkid,subtype,chunksize))
					return(0);

				copychunkbytes(archive_fd,outfd,chunksize,&filesize);
				close(outfd);
			}

			/* if they specified files on the command line, null them
			 * out after we retrieve them, later we'll make a pass
			 * through and complain about any we don't find with
			 * their first bytes nulled out
			 */
			if (nfiles != 0)
				*fnames[i] = '\0';
		}
		/* else we don't want to extract it, so skip it */
		else if (!skipchunk(archive_fd,chunksize,&filesize))
		{
			perror(archive_fd);
			fprintf(stderr,"extract: skipchunk failed\n");
			return(0);
		}
	}

	/* complain about any files named that we didn't extract */
	for (i = 0; i < nfiles; i++)
	{
		if (*fnames[i] != '\0')
			fprintf(stderr,"%s: no such archive entry\n",fnames[i]);
	}

	/* close the archive file and return success */
	close(archive_fd);
	return(1);
}

/* end of extract.c */

