Admin Panel

/* XZ client for xadmaster.library
 * chris@unsatisfactorysoftware.co.uk
 */

#ifndef XADMASTER_XZ_C
#define XADMASTER_XZ_C

#include <proto/exec.h>

#ifdef __amigaos4__
struct ExecIFace *IExec;
struct Library *newlibbase;
struct Interface *INewlib;

#include "sys/types.h"
#elif defined(__AROS__)
struct Library *aroscbase = NULL;
#else
#include <exec/types.h>
#endif

#include <proto/xadmaster.h>
#ifdef __AROS__
#include <lzma.h>
#else
#include <proto/lzma.h>
#endif
#include <dos/dos.h>
#ifdef __AROS__
#include <SDI/SDI_compiler.h>
#undef ASM
#define ASM(x) x
#else
#include "SDI_compiler.h"
#endif
#include "xz.h"
#include "XZ_rev.h"

#ifndef XADMASTERFILE
#define sz_Client		FirstClient
#define NEXTCLIENT		0
#ifdef __amigaos4__
#define XADMASTERVERSION	13
#else
#define XADMASTERVERSION	12
#endif
UBYTE *version = VERSTAG;
#endif
#define SZ_VERSION	VERSION
#define SZ_REVISION	REVISION

#ifdef __AROS__
void close_lzma(void)
{
	CloseLibrary(aroscbase);
	aroscbase = NULL;
}

BOOL open_lzma(void) 
{
	if(!aroscbase && !(aroscbase = OpenLibrary("arosc.library", 41)))
		return FALSE;

	return TRUE;
}
#else
struct Library *lzmaBase;
#ifdef __amigaos4__
struct lzmaIFace *Ilzma;
struct ExecIFace *IExec;
#endif

void close_lzma(void)
{
#ifdef __amigaos4__
	if(Ilzma)
	{
		DropInterface((struct Interface *)Ilzma);
		Ilzma=NULL;
	}
#endif
	if(lzmaBase)
	{
		CloseLibrary(lzmaBase);
		lzmaBase=NULL;
	}

#ifdef __amigaos4__
/*
    DropInterface(INewlib);
    CloseLibrary(newlibbase);
	INewlib = NULL;
	newlibbase = NULL;
*/
#endif
}

BOOL open_lzma(void)
{
#ifdef __amigaos4__
    IExec = (struct ExecIFace *)(*(struct ExecBase **)4)->MainInterface;

    newlibbase = OpenLibrary("newlib.library", 52);
    if(newlibbase)
        INewlib = GetInterface(newlibbase, "main", 1, NULL);
#endif

	if(lzmaBase = OpenLibrary("lzma.library",5))
	{
#ifdef __amigaos4__
		if(Ilzma = (struct lzmaIFace *)GetInterface(lzmaBase,"main",1,NULL))
		{
#endif
			return TRUE;
#ifdef __amigaos4__
		}
#endif
	}
	close_lzma();
	return FALSE;
}
#endif

#ifdef __amigaos4__
BOOL sz_RecogData(ULONG size, STRPTR data,
struct xadMasterIFace *IxadMaster)
#else
ASM(BOOL) sz_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
REG(a6, struct xadMasterBase *xadMasterBase))
#endif
{
  if(data[0]==0xfd & data[1]=='7' & data[2]=='z' & data[3]=='X' & data[4]=='Z' & data[5]==0x00)
    return 1; /* known file */
  else
    return 0; /* unknown file */
}

#ifdef __amigaos4__
LONG sz_GetInfo(struct xadArchiveInfo *ai,
struct xadMasterIFace *IxadMaster)
#else
ASM(LONG) sz_GetInfo(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
#endif
{
  struct xadFileInfo *fi;
	long err=XADERR_OK;
	if (!open_lzma()) return XADERR_RESOURCE;

	ai->xai_PrivateClient = xadAllocVec(sizeof(struct xad7zprivate),MEMF_PRIVATE | MEMF_CLEAR);
	struct xad7zprivate *xad7z = ai->xai_PrivateClient;

		    fi = (struct xadFileInfo *) xadAllocObjectA(XADOBJ_FILEINFO, NULL);
    		if (!fi) return(XADERR_NOMEMORY);

		fi->xfi_DataPos = 0;
	//	fi->xfi_Size = ; //TargetBufSaveLen;
		fi->xfi_FileName = xadGetDefaultName(XAD_ARCHIVEINFO, ai,
							XAD_EXTENSION, ".xz", TAG_DONE);

      fi->xfi_CrunchSize  = ai->xai_InSize;

	fi->xfi_Flags = XADFIF_NODATE | XADFIF_NOUNCRUNCHSIZE | XADFIF_NOFILENAME;

		 if ((err = xadAddFileEntryA(fi, ai, NULL))) return(XADERR_NOMEMORY);

return(err);
}

#ifdef __amigaos4__
LONG sz_UnArchive(struct xadArchiveInfo *ai,
struct xadMasterIFace *IxadMaster)
#else
ASM(LONG) sz_UnArchive(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
#endif
{
	struct xad7zprivate *xad7z = ai->xai_PrivateClient;
  struct xadFileInfo *fi = ai->xai_CurFile;
	UBYTE *inbuffer, *outbuffer;
	long err=XADERR_OK;
	lzma_ret ret;
	lzma_stream strm = LZMA_STREAM_INIT;

	if (!open_lzma()) return XADERR_RESOURCE;

	inbuffer = 	xadAllocVec(ai->xai_InSize, MEMF_CLEAR);
	outbuffer = xadAllocVec(1024, MEMF_CLEAR);

	xadHookAccess(XADAC_READ, ai->xai_InSize, inbuffer, ai);
	// need to get actual bytes read

	ret = lzma_stream_decoder(&strm, UINT64_MAX, 0);
	if(ret != LZMA_OK) return XADERR_UNKNOWN;


	strm.next_in = inbuffer;
	strm.avail_in = ai->xai_InSize;

	do
	{
		strm.next_out = outbuffer;
		strm.avail_out = 1024;

		ret = lzma_code(&strm, LZMA_RUN);

		if((ret != LZMA_OK) && (ret != LZMA_STREAM_END))
			err = XADERR_DECRUNCH;

		if((err == XADERR_OK) && (strm.avail_out != 1024))
			err = xadHookAccess(XADAC_WRITE, 1024 - strm.avail_out, outbuffer, ai);

		if(err) strm.avail_out = 1024;

	} while (strm.avail_out == 0);

	lzma_end(&strm);

	xadFreeObjectA(inbuffer, NULL);
	xadFreeObjectA(outbuffer, NULL);

	return err;
}

#ifdef __amigaos4__
void sz_Free(struct xadArchiveInfo *ai,
struct xadMasterIFace *IxadMaster)
#else
ASM(void) sz_Free(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
#endif
{
  /* This function needs to free all the stuff allocated in info or
  unarchive function. It may be called multiple times, so clear freed
  entries!
  */

//	struct xad7zprivate *xad7z = ai->xai_PrivateClient;
	xadFreeObjectA(ai->xai_PrivateClient, NULL);
	ai->xai_PrivateClient = NULL;
	close_lzma();
}

/* You need to complete following structure! */
const struct xadClient sz_Client = {
NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, SZ_VERSION, SZ_REVISION,
6, XADCF_FILEARCHIVER|XADCF_DATACRUNCHER|XADCF_FREEFILEINFO|XADCF_FREEXADSTRINGS,
0 /* Type identifier. Normally should be zero */, "XZ",
(BOOL (*)()) sz_RecogData, (LONG (*)()) sz_GetInfo,
(LONG (*)()) sz_UnArchive, (void (*)()) sz_Free };

#if !defined(__amigaos4__) && !defined(__AROS__)
void main(void)
{
}
#endif
#endif /* XADMASTER_7Z_C */