Last active
August 29, 2015 13:55
-
-
Save swillits/8725895 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void *Sys_LoadDll( const char *name, char *fqpath, | |
int( **entryPoint ) ( int, ... ), | |
int ( *systemcalls )( int, ... ) ) { | |
void *libHandle; | |
void ( *dllEntry )( int ( *syscallptr )( int, ... ) ); | |
char fname[MAX_OSPATH]; | |
char *pwdpath; | |
char *homepath; | |
char *basepath; | |
char *gamedir; | |
char *fn; | |
const char* err = NULL; // bk001206 // rb0101023 - now const | |
#if !defined( DEDICATED ) | |
char *cvar_name = NULL; | |
#endif | |
*fqpath = 0 ; // added 2/15/02 by T.Ray | |
// bk001206 - let's have some paranoia | |
assert( name ); | |
Q_strncpyz( fname, Sys_GetDLLName( name ), sizeof( fname ) ); | |
// bk001129 - was RTLD_LAZY | |
#define Q_RTLD RTLD_NOW | |
pwdpath = Sys_Cwd(); | |
homepath = Cvar_VariableString( "fs_homepath" ); | |
basepath = Cvar_VariableString( "fs_basepath" ); | |
gamedir = Cvar_VariableString( "fs_game" ); | |
// this is relevant to client only | |
// this code is in for full client hosting a game, but it's not affected by it | |
#if !defined( DEDICATED ) | |
// do a first scan to identify what we are going to dlopen | |
// we need to pass this to FS_ExtractFromPakFile so that it checksums the right file | |
// NOTE: if something fails (not found, or file operation failed), we will ERR_FATAL (in the checksum itself, we only ERR_DROP) | |
#ifndef NDEBUG | |
fn = FS_BuildOSPath( pwdpath, gamedir, fname ); | |
if ( access( fn, R_OK ) == -1 ) { | |
#endif | |
fn = FS_BuildOSPath( homepath, gamedir, fname ); | |
if ( access( fn, R_OK ) == 0 ) { | |
// there is a .so in fs_homepath, but is it a valid one version-wise? | |
// we use a persistent variable in config.cfg to make sure | |
// this is set in FS_CL_ExtractFromPakFile when the file is extracted | |
cvar_t *lastVersion; | |
cvar_name = va( "cl_lastVersion%s", name ); | |
lastVersion = Cvar_Get( cvar_name, "(uninitialized)", CVAR_ARCHIVE ); | |
if ( Q_stricmp( Cvar_VariableString( "version" ), lastVersion->string ) ) { | |
Com_DPrintf( "clearing non matching version of %s .so: %s\n", name, fn ); | |
if ( remove( fn ) == -1 ) { | |
Com_Error( ERR_FATAL, "failed to remove outdated '%s' file:\n\"%s\"\n", fn, strerror( errno ) ); | |
} | |
// we cancelled fs_homepath, go work on basepath now | |
fn = FS_BuildOSPath( basepath, gamedir, fname ); | |
if ( access( fn, R_OK ) == -1 ) { | |
// we may be dealing with a media-only mod, check wether we can find 'reference' DLLs and copy them over | |
if ( !CopyDLLForMod( &fn, gamedir, pwdpath, homepath, basepath, fname ) ) { | |
Com_Error( ERR_FATAL, "Sys_LoadDll(%s) failed, no corresponding .so file found in fs_homepath or fs_basepath\n", name ); | |
} | |
} | |
} | |
// the .so in fs_homepath is valid version-wise .. FS_CL_ExtractFromPakFile will have to decide wether it's valid pk3-wise later | |
} else { | |
fn = FS_BuildOSPath( basepath, gamedir, fname ); | |
if ( access( fn, R_OK ) == -1 ) { | |
// we may be dealing with a media-only mod, check wether we can find 'reference' DLLs and copy them over | |
if ( !CopyDLLForMod( &fn, gamedir, pwdpath, homepath, basepath, fname ) ) { | |
Com_Error( ERR_FATAL, "Sys_LoadDll(%s) failed, no corresponding .so file found in fs_homepath or fs_basepath\n", name ); | |
} | |
} | |
} | |
#ifndef NDEBUG | |
} | |
#endif | |
// NERVE - SMF - extract dlls from pak file for security | |
// we have to handle the game dll a little differently | |
// NOTE #2: we may have found a file in fs_basepath, and if the checksum is wrong, FS_Extract will write in fs_homepath | |
// won't be a problem since we start a brand new scan next | |
if ( cl_connectedToPureServer && Q_strncmp( name, "qagame", 6 ) ) { | |
if ( !FS_CL_ExtractFromPakFile( fn, gamedir, fname, cvar_name ) ) { | |
Com_Error( ERR_DROP, "Game code(%s) failed Pure Server check", fname ); | |
} | |
} | |
#endif | |
#ifndef NDEBUG | |
// current directory | |
// NOTE: only for debug build, see Sys_LoadDll discussion | |
fn = FS_BuildOSPath( pwdpath, gamedir, fname ); | |
Com_Printf( "Sys_LoadDll(%s)... ", fn ); | |
libHandle = dlopen( fn, Q_RTLD ); | |
if ( !libHandle ) { | |
Com_Printf( "\nSys_LoadDll(%s) failed:\n\"%s\"\n", fn, dlerror() ); | |
#endif | |
// homepath | |
fn = FS_BuildOSPath( homepath, gamedir, fname ); | |
Com_Printf( "Sys_LoadDll(%s)... ", fn ); | |
libHandle = dlopen( fn, Q_RTLD ); | |
if ( !libHandle ) { | |
Com_Printf( "\nSys_LoadDll(%s) failed:\n\"%s\"\n", fn, dlerror() ); | |
// basepath | |
fn = FS_BuildOSPath( basepath, gamedir, fname ); | |
Com_Printf( "Sys_LoadDll(%s)... ", fn ); | |
libHandle = dlopen( fn, Q_RTLD ); | |
if ( !libHandle ) { | |
// report any problem | |
Com_Printf( "\nSys_LoadDll(%s) failed:\n\"%s\"\n", fn, dlerror() ); | |
} else { | |
Com_Printf( "ok\n" ); | |
} | |
// not found, bail | |
if ( !libHandle ) { | |
#ifndef NDEBUG // in debug abort on failure | |
Com_Error( ERR_FATAL, "Sys_LoadDll(%s) failed dlopen() completely!\n", name ); | |
#else | |
Com_Printf( "Sys_LoadDll(%s) failed dlopen() completely!\n", name ); | |
#endif | |
return NULL; | |
} | |
} else { | |
Com_Printf( "ok\n" ); | |
} | |
#ifndef NDEBUG | |
} else { | |
Com_Printf( "ok\n" ); | |
} | |
#endif | |
Q_strncpyz( fqpath, fn, MAX_QPATH ) ; // added 2/15/02 by T.Ray | |
dllEntry = dlsym( libHandle, "dllEntry" ); | |
*entryPoint = dlsym( libHandle, "vmMain" ); | |
if ( !*entryPoint || !dllEntry ) { | |
err = dlerror(); | |
#ifndef NDEBUG // in debug abort on failure | |
Com_Error( ERR_FATAL, "Sys_LoadDll(%s) failed dlsym(vmMain):\n\"%s\" !\n", name, err ); | |
#else | |
Com_Printf( "Sys_LoadDll(%s) failed dlsym(vmMain):\n\"%s\" !\n", name, err ); | |
#endif | |
dlclose( libHandle ); | |
err = dlerror(); | |
if ( err != NULL ) { | |
Com_Printf( "Sys_LoadDll(%s) failed dlcose:\n\"%s\"\n", name, err ); | |
} | |
return NULL; | |
} | |
Com_Printf( "Sys_LoadDll(%s) found **vmMain** at %p \n", name, *entryPoint ); | |
dllEntry( systemcalls ); | |
Com_Printf( "Sys_LoadDll(%s) succeeded!\n", name ); | |
return libHandle; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment