XADMaster/libxad/hook_stream.c
2011-05-12 00:35:43 +03:00

231 lines
7.4 KiB
C

#ifndef XADMASTER_HOOK_STREAM_C
#define XADMASTER_HOOK_STREAM_C
/* $Id: hook_stream.c,v 1.6 2005/06/23 14:54:37 stoecker Exp $
XAD Stream IO hooks
XAD library system for archive handling
Copyright (C) 1998 and later by Dirk Stöcker <soft@dstoecker.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef AMIGA
#include <proto/xadmaster.h>
#include <proto/utility.h>
#endif
#include "include/functions.h"
#include "include/SDI_compiler.h"
/************************************************************************
* *
* In/OutHookStream private structure *
* *
************************************************************************/
struct StreamPrivate
{
struct xadArchiveInfo *ai;
struct TagItem ti[6];
/* XAD_USESKIPINFO, XAD_GETCRC16, XAD_GETCRC32, XAD_CRC16ID, XAD_CRC32ID, TAG_DONE */
};
/*************************** read-from-mem hook **************************/
FUNCHOOK(InHookStream)
{
xadERROR err = 0;
struct xadMasterBaseP *xadMasterBase;
struct StreamPrivate *sp;
xadMasterBase = ai->xaip_MasterBase;
sp = (struct StreamPrivate *) param->xhp_PrivatePtr;
switch(param->xhp_Command)
{
case XADHC_READ:
if(param->xhp_DataPos + param->xhp_BufferSize > ai->xaip_InSize)
err = XADERR_INPUT;
else if(param->xhp_BufferPtr)
{
err = xadHookTagAccessA(XADM_PRIV XADAC_READ, param->xhp_BufferSize,
param->xhp_BufferPtr, XADM_AI(sp->ai), sp->ti);
param->xhp_DataPos += param->xhp_BufferSize;
}
break;
case XADHC_SEEK:
if(((xadSignSize)param->xhp_DataPos + param->xhp_CommandData < 0)
|| (param->xhp_DataPos + param->xhp_CommandData > ai->xaip_InSize))
{
return XADERR_INPUT;
}
err = xadHookTagAccessA(XADM_PRIV XADAC_INPUTSEEK,
param->xhp_CommandData, 0, XADM_AI(sp->ai), sp->ti);
param->xhp_DataPos += param->xhp_CommandData;
break;
case XADHC_INIT:
#ifdef DEBUG
DebugOther("InHookStream: XADHC_INIT");
#endif
if((sp = xadAllocVec(XADM sizeof(struct StreamPrivate), XADMEMF_PUBLIC|XADMEMF_CLEAR)))
{
xadTAGPTR ti, ti2;
#ifdef AMIGA
struct UtilityBase *UtilityBase = xadMasterBase->xmb_UtilityBase;
#endif
xadINT32 i;
param->xhp_PrivatePtr = sp;
for(i = 0; i < 5; ++i)
sp->ti[i].ti_Tag = TAG_IGNORE;
sp->ti[5].ti_Tag = TAG_DONE;
ti = ti2 = ai->xaip_InArcInfo;
while((ti2 = NextTagItem(&ti)))
{
switch(ti2->ti_Tag)
{
case XAD_ARCHIVEINFO: sp->ai = (struct xadArchiveInfo *)(uintptr_t) ti2->ti_Data; break;
case XAD_USESKIPINFO: sp->ti[0].ti_Tag = ti2->ti_Tag; sp->ti[0].ti_Data = ti2->ti_Data; break;
case XAD_GETCRC32: sp->ti[1].ti_Tag = ti2->ti_Tag; sp->ti[1].ti_Data = ti2->ti_Data; break;
case XAD_GETCRC16: sp->ti[2].ti_Tag = ti2->ti_Tag; sp->ti[2].ti_Data = ti2->ti_Data; break;
case XAD_CRC32ID: sp->ti[3].ti_Tag = ti2->ti_Tag; sp->ti[3].ti_Data = ti2->ti_Data; break;
case XAD_CRC16ID: sp->ti[4].ti_Tag = ti2->ti_Tag; sp->ti[4].ti_Data = ti2->ti_Data; break;
}
}
for(i = 5; i >= 0 && sp->ti[i].ti_Tag == TAG_IGNORE; --i) /* reduce the number of TAG_IGNORE */
sp->ti[i].ti_Tag = TAG_DONE;
if(!sp->ai)
err = XADERR_BADPARAMS;
}
else
err = XADERR_NOMEMORY;
param->xhp_DataPos = 0;
break;
case XADHC_FREE:
if(param->xhp_PrivatePtr)
{
xadFreeObjectA(XADM param->xhp_PrivatePtr, 0);
param->xhp_PrivatePtr = 0;
}
break;
case XADHC_FULLSIZE:
param->xhp_CommandData = sp->ai->xai_InSize-sp->ai->xai_InPos;
if(sp->ti[0].ti_Data) /* use skipinfo */
{
param->xhp_CommandData += param->xhp_CommandData
- getskipsize(param->xhp_CommandData, (struct xadArchiveInfoP *) sp->ai);
}
#ifdef DEBUG
DebugOther("InHookStream: XADHC_FULLSIZE = %ld", param->xhp_CommandData);
#endif
break;
case XADHC_ABORT:
break;
default: return XADERR_NOTSUPPORTED;
}
return err;
}
ENDFUNC
/*************************** write-to-mem hook **************************/
FUNCHOOK(OutHookStream)
{
xadERROR err = 0;
struct xadMasterBaseP *xadMasterBase;
struct StreamPrivate *sp;
xadMasterBase = ai->xaip_MasterBase;
sp = (struct StreamPrivate *) param->xhp_PrivatePtr;
switch(param->xhp_Command)
{
case XADHC_WRITE:
err = xadHookTagAccessA(XADM_PRIV XADAC_WRITE, param->xhp_BufferSize,
param->xhp_BufferPtr, XADM_AI(sp->ai), sp->ti);
param->xhp_DataPos += param->xhp_BufferSize;
break;
case XADHC_SEEK:
if(((xadSignSize)param->xhp_DataPos + param->xhp_CommandData < 0) || (param->xhp_DataPos + param->xhp_CommandData > ai->xaip_OutSize))
return XADERR_OUTPUT;
err = xadHookTagAccessA(XADM XADAC_OUTPUTSEEK, param->xhp_CommandData,
0, XADM_AI(sp->ai), sp->ti);
param->xhp_DataPos += param->xhp_CommandData;
break;
case XADHC_INIT:
#ifdef DEBUG
DebugOther("OutHookStream: XADHC_INIT");
#endif
if((sp = xadAllocVec(XADM sizeof(struct StreamPrivate), XADMEMF_PUBLIC|XADMEMF_CLEAR)))
{
xadTAGPTR ti, ti2;
#ifdef AMIGA
struct UtilityBase *UtilityBase = xadMasterBase->xmb_UtilityBase;
#endif
xadINT32 i;
param->xhp_PrivatePtr = sp;
for(i = 0; i < 5; ++i)
sp->ti[i].ti_Tag = TAG_IGNORE;
sp->ti[5].ti_Tag = TAG_DONE;
ti = ti2 = ai->xaip_InArcInfo;
while((ti2 = NextTagItem(&ti)))
{
switch(ti2->ti_Tag)
{
case XAD_ARCHIVEINFO: sp->ai = (struct xadArchiveInfo *)(uintptr_t) ti2->ti_Data; break;
case XAD_USESKIPINFO: sp->ti[0].ti_Tag = ti2->ti_Tag; sp->ti[0].ti_Data = ti2->ti_Data; break;
case XAD_GETCRC32: sp->ti[1].ti_Tag = ti2->ti_Tag; sp->ti[1].ti_Data = ti2->ti_Data; break;
case XAD_GETCRC16: sp->ti[2].ti_Tag = ti2->ti_Tag; sp->ti[2].ti_Data = ti2->ti_Data; break;
case XAD_CRC32ID: sp->ti[3].ti_Tag = ti2->ti_Tag; sp->ti[3].ti_Data = ti2->ti_Data; break;
case XAD_CRC16ID: sp->ti[4].ti_Tag = ti2->ti_Tag; sp->ti[4].ti_Data = ti2->ti_Data; break;
}
}
for(i = 5; i >= 0 && sp->ti[i].ti_Tag == TAG_IGNORE; --i) /* reduce the number of TAG_IGNORE */
sp->ti[i].ti_Tag = TAG_DONE;
if(!sp->ai)
err = XADERR_BADPARAMS;
}
else
err = XADERR_NOMEMORY;
param->xhp_DataPos = 0;
break;
case XADHC_FREE:
if(param->xhp_PrivatePtr)
{
xadFreeObjectA(XADM_PRIV param->xhp_PrivatePtr, 0);
param->xhp_PrivatePtr = 0;
}
break;
case XADHC_ABORT:
break;
default: return XADERR_NOTSUPPORTED;
}
return err;
}
ENDFUNC
#endif /* XADMASTER_HOOK_STREAM_C */