/* iffar - IFF CAT archiver, IFF support functions

   By Karl Lehenbauer, 4/25/88.
   This code is released to the public domain.
   See the README file for more information.

*/

/* culled general purpose IFF file cracking routines for Karl's 
 * IFF Stuff by Karl Lehenbauer, based originally on public domain IFF 
 * code from Electronic Arts, 2/24/88
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>

#include <hackercorp/assert.h>
#include <hackercorp/iff.h>

extern long lseek();

extern ULONG nextchunk();

/* print a chunkID to stderr */
PutID(id)
ID id;
{
    fprintf(stderr,"%c%c%c%c",
	   (char)((id>>24L) & 0x7f),
	   (char)((id>>16L) & 0x7f),
	   (char)((id>>8)   & 0x7f),
	   (char)(id        & 0x7f) );
}

/* write a chunk header, that's the 4-byte chunk ID and a 4-byte 
 * chunk length 
 */
WriteChunkHeader(fd,chunktype,length)
int fd;
ULONG chunktype;
long length;
{
	ChunkHeader chunkheader;

	chunkheader.ckID = chunktype;
	chunkheader.ckSize = length;

	if (write(fd,&chunkheader,sizeof(chunkheader)) == -1)
	{
		perror("WriteChunkHeader");
		return(0);
	}
	return(1);
}

/* write a chunk that has a four character subtype, like FORM, CAT or LIST
*/
WriteSuperChunkHeader(fd,chunktype,subtype,length)
int fd;
ULONG chunktype, subtype;
long length;
{
	if (!WriteChunkHeader(fd,chunktype,length+sizeof(subtype)))
		return(0);
	return(write(fd,&subtype,sizeof(subtype)) != -1);
}

/* write a chunk header and body, that's the 8-byte header and the data
 * to match the specified length
 */
WriteChunk(fd,chunktype,data,length)
int fd;
ULONG chunktype;
char *data;
long length;
{
	static char zero = '\0';

	if (!WriteChunkHeader(fd,chunktype,length))
		return(0);

	/* if there's a body, write it out */
	if (length != 0)
		if (write(fd,data,length) == -1)
		{
			perror("WriteChunk");
			return(0);
		}

	/* if the length is odd, write out an additional zero byte */
	if (length & 1)
		if (write(fd,&zero,1) == -1)
		{
			perror("WriteChunk");
			return(0);
		}
	return(1);
}

WriteTextChunk(fd,chunktype,text)
int fd;
ULONG chunktype;
char *text;
{
	int len = strlen(text);
	WriteChunk(fd,chunktype,text,len);
}

/* rewrite_IFF_header - write (filesize - sizeof(ChunkHeader)) into
 * IFF file's header, assumes file is open for write
 */
Rewrite_IFF_header(fd)
int fd;
{
	long filesize;

	/* get filesize by seeking to EOF */
	if ((filesize = lseek(fd,0,2)) == -1)
	{
		perror("rewrite_IFF_header");
		return(0);
	}

	/* go back to the beginning of the file */
	if (lseek(fd,0,0) == -1)
	{
		perror("rewrite_IFF_header");
		return(0);
	}

	if (!WriteChunkHeader(fd,ID_FORM,(filesize - sizeof(ChunkHeader))))
	{
		perror("rewrite_IFF_header: WriteChunkHeader");
		return(0);
	}

	return(1);
}

/* create an IFF file by opening it for write and writing the type and subtype
 */
int CreateIFF(filename,type,subtype)
char *filename;
ULONG type, subtype;
{
	int fd;

	if ((fd = creat(filename, 0664)) == -1)
	{
		perror(filename);
		return(-1);
	}

	if (!WriteSuperChunkHeader(fd,type,subtype,0L))
	{
		fprintf("create_archive: couldn't write CAT chunkheader of new archive\n");
		return(-1);
	}

	/* success, return the archive fd */
	return(fd);
}

/* end of iff.c */
