XADMaster/libxad/unix/init.c

237 lines
7.2 KiB
C

/* $Id: init.c,v 1.20 2005/06/23 14:54:43 stoecker Exp $
Unix startup and shutdown code.
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
*/
#include "../config.h"
#undef VERSION
#include "../include/functions.h"
#include "../include/version.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//#include <dlfcn.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
//#include <pthread.h>
/* Lock this when you need to access globals! */
//static pthread_mutex_t GlobalMutex = PTHREAD_MUTEX_INITIALIZER;
static struct xadMasterBaseP *xadMasterBase = NULL;
/******************************************************************************
*
* Load external clients to memory. You must have a lock on GlobalMutex!
* Returns XADFALSE if it can't lock the directory, XADTRUE otherwise
*
******************************************************************************
*/
typedef const xadSTRING * (*XC_VERSION)();
typedef const struct xadClient * (*XC_CLIENT)();
#if 0
static xadBOOL LoadExtClients(struct xadMasterBaseP *xmb, xadSTRPTR directory)
{
DIR *dir;
struct dirent *dirEnt;
char fname[512];
unsigned int handles = xmb->xmb_NumExtClients;
if (!(dir = opendir(directory))) return XADFALSE;
while ((dirEnt = readdir(dir))) {
void *handle;
int keep = 0;
/* attempt to load directory entry as shared object */
snprintf(&fname[0], sizeof(fname), "%s/%s", directory, dirEnt->d_name);
/* only load files with the SO_EXT extension */
if (strcmp(&fname[strlen(&fname[0]) - strlen(SO_EXT)], SO_EXT) != 0)
continue;
if ((handle = dlopen((char *) &fname[0], RTLD_LAZY))) {
XC_VERSION gcv = (XC_VERSION) dlsym(handle, "xad_GetClientVersion");
XC_CLIENT gc = (XC_CLIENT) dlsym(handle, "xad_GetClient");
/* if directory has appropriate symbols */
if (gcv && gc) {
#ifdef DEBUG
DebugRunTime("Loaded external client: %s\n", gcv());
#endif
if (xadAddClients(xmb, gc(), XADCF_EXTERN)) keep = 1;
}
}
/* if we load a shared object and get clients from it, keep it */
if (keep) {
/* ensure space to store handle */
if (!xmb->xmb_ExtClients) {
handles = 16;
xmb->xmb_ExtClients = malloc(sizeof(void *) * handles);
}
else if (xmb->xmb_NumExtClients >= handles) {
handles *= 2; /* FIXME: memory is lost if realloc fails */
xmb->xmb_ExtClients = realloc(xmb->xmb_ExtClients,
sizeof(void *) * handles);
}
/* store shared object handle for later closure, don't free it */
if (xmb->xmb_ExtClients) {
xmb->xmb_ExtClients[xmb->xmb_NumExtClients++] = handle;
handle = NULL;
}
}
if (handle) dlclose(handle);
}
closedir(dir);
return XADTRUE;
}
/******************************************************************************
*
* Free clients in memory. You must have a lock on GlobalMutex!
* WARNING: The external clients are not removed from the central client list!
* Remove them before calling this function.
*
******************************************************************************
*/
static void UnloadExtClients( struct xadMasterBaseP *xmb )
{
unsigned int i;
if (xmb == NULL)
return;
/* close the loaded libraries */
for (i = 0; i < xmb->xmb_NumExtClients; i++) {
dlclose(xmb->xmb_ExtClients[i]);
}
/* free the list of loaded clients */
free(xmb->xmb_ExtClients);
xmb->xmb_ExtClients = NULL;
xmb->xmb_NumExtClients = 0;
}
#endif
/******************************************************************************
*
* Init the private xadMasterBase structure.
*
******************************************************************************
*/
static struct xadMasterBaseP *InitXADMasterBaseP( struct xadMasterBaseP *xmb )
{
const struct xadClient *client;
unsigned long minsize = 0;
if (xmb == NULL)
return NULL;
xmb->xmb_DefaultName = (xadSTRPTR)"unnamed.dat";
xmb->xmb_FirstClient = NULL;
xmb->xmb_ExtClients = NULL;
xmb->xmb_NumExtClients = 0;
xmb->xmb_InHookFH.h_Entry = (xadUINT32 (*)()) InHookFH;
xmb->xmb_OutHookFH.h_Entry = (xadUINT32 (*)()) OutHookFH;
xmb->xmb_InHookMem.h_Entry = (xadUINT32 (*)()) InHookMem;
xmb->xmb_OutHookMem.h_Entry = (xadUINT32 (*)()) OutHookMem;
xmb->xmb_InHookStream.h_Entry = (xadUINT32 (*)()) InHookStream;
xmb->xmb_OutHookStream.h_Entry = (xadUINT32 (*)()) OutHookStream;
xmb->xmb_InHookSplitted.h_Entry = (xadUINT32 (*)()) InHookSplitted;
xmb->xmb_InHookDiskArc.h_Entry = (xadUINT32 (*)()) InHookDiskArc;
/* add internal clients */
xadAddClients(xmb, RealFirstClient, 0);
/* load and add external clients */
//LoadExtClients(xmb, CLIENTDIR);
for (client = xmb->xmb_FirstClient; client; client = client->xc_Next)
if (client->xc_RecogSize > minsize)
minsize = (unsigned long)client->xc_RecogSize;
xmb->xmb_RecogSize = minsize;
MakeCRC16(xmb->xmb_CRCTable1, XADCRC16_ID1);
MakeCRC32(xmb->xmb_CRCTable2, XADCRC32_ID1);
return xmb;
}
/******************************************************************************
*
* This is the Unix version of LibInit() found in libinit.c
*
******************************************************************************
*/
struct xadMasterBase *xadOpenLibrary( xadINT32 version )
{
struct xadMasterBase *xmb;
if (XADMASTERVERSION < version)
return NULL;
// pthread_mutex_lock(&GlobalMutex);
/* Allocate and init the private xadMasterBase. I've kept allocation and
* initialisation separate, so that InitXADMasterBaseP() can eventually be
* reused in the Amiga build (and other builds) too, to reduce redundant code.
*/
if (xadMasterBase == NULL)
xadMasterBase = InitXADMasterBaseP(calloc(1, sizeof(struct xadMasterBaseP)));
if ((xmb = (struct xadMasterBase *) xadMasterBase))
xadMasterBase->xmb_Unix_AccessCount++;
// pthread_mutex_unlock(&GlobalMutex);
return xmb;
}
/******************************************************************************
*
* Shutdown
*
******************************************************************************
*/
void xadCloseLibrary( struct xadMasterBase *xmb )
{
if (xmb == NULL)
return;
// pthread_mutex_lock(&GlobalMutex);
if (--xadMasterBase->xmb_Unix_AccessCount <= 0)
{
xadFreeClients(xadMasterBase);
//UnloadExtClients(xadMasterBase);
free(xadMasterBase);
xadMasterBase = NULL;
}
// pthread_mutex_unlock(&GlobalMutex);
}