#include <libraries/xpk.h>           /* XCat - Unpack file to stdout */
#include <proto/exec.h>
#include <proto/dos.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

struct Library *XpkBase;
char errbuf[XPKERRMSGSIZE+1];
struct FileInfoBlock *Fib;
long   utot, ctot;

void exitem( char *name );
void exfile( struct FileInfoBlock *fib );

void end( char *text )
{
	if( text )    Write(Output(), text, strlen(text));
	if( XpkBase ) CloseLibrary( XpkBase );
	exit(text ? 10 : 0);
}

void main(int argc, char *argv[])
{
	int i, ratio=0;

	if( !(XpkBase=OpenLibrary(XPKNAME,0)))
		end("Cannot open "XPKNAME"\n");

	if( argc<2 )
		argv[1]="", argc=2;

	if( !(Fib=AllocMem(sizeof(*Fib),0)))
		end("Not enough memory\n");

	printf("Original  Packed  Ratio Type Protection Name\n");
	printf("-------- -------- ----- ---- ---------- ----\n");
	for( i=1; i<argc; i++ )
		exitem( argv[i] );
	if( utot ) ratio= 100-100*ctot/utot;
	printf("-------- -------- -----\n");
	printf("%8d %8d  %2d%%\n", utot, ctot, ratio );
 
	end( NULL );
}

void
exitem( char *name )
{
	BPTR lock, prev;

	if( !(lock=Lock( name, ACCESS_READ))) {
		printf("Error %d reading %s\n",IoErr(),name);
		return;
	}

	if( !Examine( lock, Fib )) {
		UnLock( lock );
		printf("Error %d reading %s\n",IoErr(),name);
		return;
	}

	if( Fib->fib_DirEntryType<0 ) {
		exfile( Fib );
		UnLock( lock );
	} else {
		prev=CurrentDir( lock );
		while( ExNext(lock,Fib))
			exfile( Fib );
		UnLock( CurrentDir(prev));
	}
}

struct TagItem tags[]={ XPK_InName, NULL, XPK_PassThru, TRUE, TAG_DONE };

void
exfile( struct FileInfoBlock *fib )
{
	struct XpkFib xfib;
	char prot[10];
	int  i, clen=0, ulen=0;

	prot[0]=fib->fib_DirEntryType<0 ? '-' : 'd';
	for( i=0; i<8; i++ )
		prot[8-i]= (Fib->fib_Protection^0x0f) & (1<<i) ? "dewrapsh"[i] : '-';
	prot[9]=0;

	if( XpkExamineTags(
		&xfib,
		XPK_InName,      (long) fib->fib_FileName,
		TAG_DONE
	) || xfib.Type!=XPKTYPE_PACKED ) {
		if( fib->fib_EntryType<0 )
			printf("%8d                      %9s %-20s\n",
				clen=ulen=fib->fib_Size,
				prot,
				fib->fib_FileName );
		else 
			printf("%8s                      %9s %-20s\n",
				"<Dir>",
				prot,
				fib->fib_FileName );
	} else 
		printf("%8d %8d  %2d%%  %4s  %9s %-20s\n",
			ulen=xfib.ULen,
			clen=xfib.CLen,
			xfib.Ratio,
			xfib.Packer,
			prot,
			fib->fib_FileName );

	utot+= ulen;
	ctot+= clen;
}
