XADMaster/libxad/hook_splitted.c

281 lines
9.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef XADMASTER_HOOK_SPLITTED_C
#define XADMASTER_HOOK_SPLITTED_C
/* $Id: hook_splitted.c,v 1.8 2005/06/23 14:54:37 stoecker Exp $
splitted input file IO hook
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/utility.h>
#include <proto/xadmaster.h>
#endif
#include "include/functions.h"
#include "include/SDI_compiler.h"
static xadERROR callsplitthook(struct xadSplitData *sd, struct xadArchiveInfoP *ai,
xadUINT32 command, xadSignSize data, xadPTR bufptr, xadUINT32 bufsize)
{
xadERROR res;
xadSize insize;
xadSize *multivol;
#ifdef AMIGA
struct xadMasterBaseP *xadMasterBase = (struct xadMasterBaseP *) ai->xaip_MasterBase;
struct UtilityBase *UtilityBase;
UtilityBase = xadMasterBase->xmb_UtilityBase;
#endif
sd->xsd_HookParam.xhp_Command = command;
sd->xsd_HookParam.xhp_CommandData = data;
sd->xsd_HookParam.xhp_BufferPtr = bufptr;
sd->xsd_HookParam.xhp_BufferSize = bufsize;
insize = ai->xaip_InSize;
multivol = ai->xaip_ArchiveInfo.xai_MultiVolume;
#ifdef AMIGA
ai->xaip_InDevice = sd->xsd_InDevice;
#endif
ai->xaip_InFileHandle = sd->xsd_InFileHandle;
ai->xaip_InFileName = sd->xsd_InFileName;
ai->xaip_InMemory = sd->xsd_InMemory;
ai->xaip_InSize = sd->xsd_InSize;
ai->xaip_InSplitted = sd->xsd_InSplitted;
ai->xaip_InDiskArc = sd->xsd_InDiskArc;
ai->xaip_InArcInfo = sd->xsd_InArcInfo;
ai->xaip_ArchiveInfo.xai_MultiVolume = sd->xsd_MultiVolume;
#ifdef DEBUG
{
static const xadSTRPTR commands[] = {"XADHC_READ", "XADHC_WRITE",
"XADHC_SEEK", "XADHC_INIT", "XADHC_FREE", "XADHC_ABORT", "XADHC_FULLSIZE"};
DebugOther("callsplitthook(..., %s, %ld, $%08lx, %ld)", commands[command-XADHC_READ], data, bufptr, bufsize);
}
#endif
res = CallHookPkt(sd->xsd_Hook, ai, &sd->xsd_HookParam);
#ifdef AMIGA
sd->xsd_InDevice = ai->xaip_InDevice;
#endif
sd->xsd_InFileHandle = ai->xaip_InFileHandle;
sd->xsd_InFileName = ai->xaip_InFileName;
sd->xsd_InMemory = ai->xaip_InMemory;
sd->xsd_InSize = ai->xaip_InSize;
sd->xsd_InSplitted = ai->xaip_InSplitted;
sd->xsd_InDiskArc = ai->xaip_InDiskArc;
sd->xsd_InArcInfo = ai->xaip_InArcInfo;
sd->xsd_MultiVolume = ai->xaip_ArchiveInfo.xai_MultiVolume;
ai->xaip_InSize = insize;
ai->xaip_ArchiveInfo.xai_MultiVolume = multivol;
return res;
}
/******************** join-multiple-types hook **************************/
FUNCHOOK(InHookSplitted)
{
struct xadSplitData *sd;
struct xadMasterBaseP * xadMasterBase;
xadSignSize i;
xadMasterBase = ai->xaip_MasterBase;
sd = (struct xadSplitData *) param->xhp_PrivatePtr;
switch(param->xhp_Command)
{
case XADHC_READ:
if(param->xhp_DataPos + param->xhp_BufferSize > ai->xaip_InSize)
return XADERR_INPUT;
else
{
xadSignSize j;
xadERROR err;
xadUINT8 *buf;
i = param->xhp_BufferSize;
buf = (xadUINT8 *) param->xhp_BufferPtr;
while(sd->xsd_Offset+sd->xsd_InSize <= param->xhp_DataPos)
++sd;
while(i) /* do as long as we need to read */
{
/* correct part position */
if((j = param->xhp_DataPos-sd->xsd_Offset) != sd->xsd_HookParam.xhp_DataPos)
if((err = callsplitthook(sd, ai, XADHC_SEEK, j-sd->xsd_HookParam.xhp_DataPos, 0, 0)))
return err;
/* get read size of that part */
if((j = sd->xsd_Offset+sd->xsd_InSize-param->xhp_DataPos) > i)
j = i;
/* read that size */
if((err = callsplitthook(sd, ai, XADHC_READ, 0, buf, (xadUINT32)j)))
return err;
buf += j; /* next part or end of buffer */
param->xhp_DataPos += j; /* add already read offset */
i -= j; /* subtract already read size */
++sd; /* go to next part */
}
}
break;
case XADHC_SEEK:
/* we cannot do any seeks, only set the current position */
if(((xadSignSize)param->xhp_DataPos + param->xhp_CommandData < 0) ||
(param->xhp_DataPos + param->xhp_CommandData > ai->xaip_InSize))
return XADERR_INPUT;
param->xhp_DataPos += param->xhp_CommandData;
break;
case XADHC_FULLSIZE:
/* only last assignment is useful! */
while(sd->xsd_InSize)
{
param->xhp_CommandData = sd->xsd_Offset + sd->xsd_InSize;
++sd;
}
#ifdef DEBUG
DebugOther("InHookSplitted: XADHC_FULLSIZE is %ld", param->xhp_CommandData);
#endif
break;
case XADHC_INIT:
#ifdef DEBUG
DebugHook("InHookSplitted: XADHC_INIT");
#endif
{
const struct xadSplitFile *sf;
/* allocate xai_MultiVolume and xadSplitData array in one block */
param->xhp_DataPos = 0;
sf = ai->xaip_InSplitted;
for(i = 1; sf; ++i)
{
#ifdef AMIGA
if(sf->xsf_Type < XAD_INFILENAME || sf->xsf_Type > XAD_INDEVICE)
#else
if(sf->xsf_Type < XAD_INFILENAME || sf->xsf_Type > XAD_INXADSTREAM)
#endif
return XADERR_BADPARAMS;
#ifdef DEBUG
{
static const xadSTRPTR type[] = {"XAD_INFILEHANDLE", "XAD_INMEMORY",
"XAD_INHOOK", "XAD_INSPLITTED", "XAD_INDISKARCHIVE", "XAD_INXADSTREAM",
"XAD_INDEVICE"};
if(sf->xsf_Type == XAD_INFILENAME)
DebugOther("InHookSplitted: XAD_INFILENAME, \"%s\" ($%08lx), size %ld", sf->xsf_Data, sf->xsf_Data, sf->xsf_Size);
else
DebugOther("InHookSplitted: %s, $%08lx, size %ld", type[sf->xsf_Type-XAD_INFILEHANDLE], sf->xsf_Data, sf->xsf_Size);
}
#endif
sf = sf->xsf_Next;
}
sf = ai->xaip_InSplitted;
/* i is number of entries + 1 (last zero entry) */
if((sd = (struct xadSplitData *) xadAllocVec(XADM i*(4 +
sizeof(struct xadSplitData)), XADMEMF_PUBLIC|XADMEMF_CLEAR)))
{
xadERROR err;
xadSignSize ofs = 0;
param->xhp_PrivatePtr = sd;
ai->xaip_ArchiveInfo.xai_MultiVolume = (xadSize *) (sd+i);
for(i = 0; sf; ++i)
{
switch(sf->xsf_Type)
{
case XAD_INFILENAME:
sd[i].xsd_InFileName = (xadSTRPTR)(uintptr_t) sf->xsf_Data;
sd[i].xsd_Hook = &ai->xaip_MasterBase->xmb_InHookFH;
if(!sf->xsf_Data) return XADERR_BADPARAMS;
break;
case XAD_INFILEHANDLE:
sd[i].xsd_InFileHandle = /*(BPTR)*/ (xadFileHandle)sf->xsf_Data;
sd[i].xsd_Hook = &ai->xaip_MasterBase->xmb_InHookFH;
if(!sf->xsf_Data) return XADERR_BADPARAMS;
break;
case XAD_INMEMORY:
sd[i].xsd_InMemory = (xadPTR)(uintptr_t) sf->xsf_Data;
sd[i].xsd_Hook = &ai->xaip_MasterBase->xmb_InHookMem;
if(!sf->xsf_Size || !sf->xsf_Data) return XADERR_BADPARAMS;
break;
case XAD_INHOOK:
sd[i].xsd_Hook = (struct Hook *)(uintptr_t) sf->xsf_Data;
break;
case XAD_INSPLITTED:
sd[i].xsd_InSplitted = (struct xadSplitFile *)(uintptr_t) sf->xsf_Data;
sd[i].xsd_Hook = &ai->xaip_MasterBase->xmb_InHookSplitted;
if(!sf->xsf_Data) return XADERR_BADPARAMS;
break;
case XAD_INDISKARCHIVE:
sd[i].xsd_InDiskArc = (xadTAGPTR)(uintptr_t) sf->xsf_Data;
sd[i].xsd_Hook = &ai->xaip_MasterBase->xmb_InHookDiskArc;
if(!sf->xsf_Data) return XADERR_BADPARAMS;
break;
case XAD_INXADSTREAM:
sd[i].xsd_InArcInfo = (xadTAGPTR)(uintptr_t) sf->xsf_Data;
sd[i].xsd_Hook = &ai->xaip_MasterBase->xmb_InHookStream;
if(!sf->xsf_Data) return XADERR_BADPARAMS;
break;
#ifdef AMIGA
case XAD_INDEVICE:
sd[i].xsd_InDevice = (struct xadDeviceInfo *) sf->xsf_Data;
sd[i].xsd_Hook = &ai->xaip_MasterBase->xmb_InHookDisk;
if(!sf->xsf_Data) return XADERR_BADPARAMS;
break;
#endif
}
if((err = callsplitthook(sd+i, ai, XADHC_INIT, 0, 0, 0)))
return err;
if(sf->xsf_Size)
sd[i].xsd_InSize = sf->xsf_Size;
else if((err = callsplitthook(sd+i, ai, XADHC_FULLSIZE, 0, 0, 0)))
return err;
else
sd[i].xsd_InSize = sd[i].xsd_HookParam.xhp_CommandData;
sd[i].xsd_Offset = ai->xaip_ArchiveInfo.xai_MultiVolume[i] = ofs;
ofs += sd[i].xsd_InSize;
sf = sf->xsf_Next;
}
sd[i].xsd_Offset = ofs; /* to get all-time abort condition */
}
}
break;
case XADHC_FREE:
if(param->xhp_PrivatePtr)
{
while(sd->xsd_InSize)
callsplitthook(sd++, ai, XADHC_FREE, 0, 0, 0);
xadFreeObjectA(XADM_PRIV param->xhp_PrivatePtr, 0);
param->xhp_PrivatePtr = 0;
ai->xaip_ArchiveInfo.xai_MultiVolume = 0;
}
break;
case XADHC_ABORT:
if(param->xhp_PrivatePtr)
{
while(sd->xsd_InSize)
callsplitthook(sd++, ai, XADHC_ABORT, 0, 0, 0);
}
break;
default: return XADERR_NOTSUPPORTED;
}
return 0;
}
ENDFUNC
#endif /* XADMASTER_HOOK_SPLITTED_C */