Пример #1
0
/**
 * @brief Loads a mod library.
 * #1 look in fs_homepath
 * #2 look in fs_basepath
 * #3 try to revert to the default mod library
 */
void *Sys_LoadGameDll(const char *name,
                      intptr_t(**entryPoint) (int, ...),
                      intptr_t (*systemcalls)(intptr_t, ...))
{
	void *libHandle;
	void (*dllEntry)(intptr_t (*syscallptr)(intptr_t, ...));
	char fname[MAX_OSPATH];
	char *basepath;
	char *homepath;
	char *gamedir;

	assert(name);

	Com_sprintf(fname, sizeof(fname), Sys_GetDLLName("%s"), name);

	// TODO: use fs_searchpaths from files.c
	basepath = Cvar_VariableString("fs_basepath");
	homepath = Cvar_VariableString("fs_homepath");
	gamedir  = Cvar_VariableString("fs_game");

#ifndef DEDICATED
	// if the server is pure, extract the dlls from the mod_bin.pk3 so
	// that they can be referenced
	if (Cvar_VariableValue("sv_pure") && Q_stricmp(name, "qagame"))
	{
		Com_Printf("Sys_LoadGameDll -> FS_CL_ExtractFromPakFile(%s, %s, %s)\n", homepath, gamedir, fname);
		FS_CL_ExtractFromPakFile(homepath, gamedir, fname);
	}
#endif

	libHandle = Sys_TryLibraryLoad(homepath, gamedir, fname);

	if (!libHandle && basepath)
	{
		libHandle = Sys_TryLibraryLoad(basepath, gamedir, fname);
	}

#ifndef DEDICATED
	// According to the code above, if the server is not pure, then the
	// lib must either already be in the homepath, or in the basepath,
	// without being in a pak. For a pure server, it always grabs the lib
	// from within a pak. This means there must be two copies of the lib!
	//
	// So now, if connecting to an impure server, and the lib was not
	// loaded from homepath or the basepath, let's pull it out of the pak.
	// This means we only *need* the copy that's in the pak, and will use
	// it if another copy isn't found first.
	if (!libHandle && !Cvar_VariableValue("sv_pure") && Q_stricmp(name, "qagame"))
	{
		Com_Printf("Sys_LoadGameDll -> FS_CL_ExtractFromPakFile(%s, %s, %s)\n", homepath, gamedir, fname);
		FS_CL_ExtractFromPakFile(homepath, gamedir, fname);
		libHandle = Sys_TryLibraryLoad(homepath, gamedir, fname);
	}
#endif

	// HACK: sometimes a library is loaded from the mod dir when it shouldn't. Why?
	if (!libHandle && strcmp(gamedir, DEFAULT_MODGAME))
	{
		Com_Printf("Sys_LoadDll: failed to load the mod library. Trying to revert to the default one.\n");
		libHandle = Sys_TryLibraryLoad(basepath, DEFAULT_MODGAME, fname);
	}

	if (!libHandle)
	{
		Com_Printf("Sys_LoadDll(%s) failed to load library\n", name);
		return NULL;
	}

	dllEntry    = (void (QDECL *)(intptr_t (QDECL *)(intptr_t, ...)))Sys_LoadFunction(libHandle, "dllEntry");
	*entryPoint = (intptr_t (QDECL *)(int, ...))Sys_LoadFunction(libHandle, "vmMain");

	if (!*entryPoint || !dllEntry)
	{
		Com_Printf("Sys_LoadDll(%s) failed to find vmMain function:\n\"%s\" !\n", name, Sys_LibraryError());
		Sys_UnloadLibrary(libHandle);

		return NULL;
	}

	Com_Printf("Sys_LoadDll(%s) found vmMain function at %p\n", name, *entryPoint);
	dllEntry(systemcalls);

	return libHandle;
}
Пример #2
0
/**
 * @brief Loads a mod library.
 * #1 look in fs_homepath
 * #2 look in fs_basepath
 * #3 try to revert to the default mod library
 */
void *Sys_LoadGameDll(const char *name, qboolean extract,
                      intptr_t(**entryPoint) (int, ...),
                      intptr_t (*systemcalls)(intptr_t, ...))
{
	void *libHandle;
	void (*dllEntry)(intptr_t (*syscallptr)(intptr_t, ...));
	char fname[MAX_OSPATH];
	char *basepath;
	char *homepath;
	char *gamedir;

	assert(name);

	Com_sprintf(fname, sizeof(fname), Sys_GetDLLName("%s"), name);

	// TODO: use fs_searchpaths from files.c
	basepath = Cvar_VariableString("fs_basepath");
	homepath = Cvar_VariableString("fs_homepath");
	gamedir  = Cvar_VariableString("fs_game");

	// STORY TIME
	//
	//When doing an debug build just load the mod lib from the basepath as that will have the debug pointers
	//
	// Now the code always just unpacks new libraries from the packs on release builds.
	// So the libraryfiles in the homepath are always refreshed with latest from the packs.
	// This fixes many issues with clients loading old libraries from the mod paths.
	//
	// The way it used to work is described under (or in debug mode)..
	//
	// if the server is pure, extract the dlls from the mod_bin.pk3 so
	// that they can be referenced
	//
	// If the server is not pure, then the
	// lib must either already be in the homepath, or in the basepath,
	// without being in a pak. For a pure server, it always grabs the lib
	// from within a pak. This means there must be two copies of the lib!
	//
	// So now, if connecting to an impure server, and the lib was not
	// loaded from homepath or the basepath, let's pull it out of the pak.
	// This means we only *need* the copy that's in the pak, and will use
	// it if another copy isn't found first.
#ifdef LEGACY_DEBUG
#define SEARCHPATH1 basepath
#define SEARCHPATH2 homepath
#define LIB_DO_UNPACK Cvar_VariableIntegerValue("sv_pure")
#else
#define LIB_DO_UNPACK qtrue
#define SEARCHPATH1 homepath
#define SEARCHPATH2 basepath
#endif

#ifndef DEDICATED
	if (LIB_DO_UNPACK && extract)
	{
		Com_Printf("Sys_LoadGameDll -> FS_CL_ExtractFromPakFile(%s, %s, %s)\n", homepath, gamedir, fname);
		FS_CL_ExtractFromPakFile(homepath, gamedir, fname);
	}
#endif

	libHandle = Sys_TryLibraryLoad(SEARCHPATH1, gamedir, fname);

	if (!libHandle && SEARCHPATH2)
	{
		libHandle = Sys_TryLibraryLoad(SEARCHPATH2, gamedir, fname);
	}

#ifndef DEDICATED
	if (!libHandle && !LIB_DO_UNPACK && extract)
	{
		Com_Printf("Sys_LoadGameDll -> FS_CL_ExtractFromPakFile(%s, %s, %s)\n", homepath, gamedir, fname);
		FS_CL_ExtractFromPakFile(homepath, gamedir, fname);
		libHandle = Sys_TryLibraryLoad(homepath, gamedir, fname);
	}
#endif

	if (!libHandle)
	{
		Com_Printf("Sys_LoadDll(%s/%s) failed to load library\n", gamedir, name);
		return NULL;
	}

	dllEntry    = (void (QDECL *)(intptr_t (QDECL *)(intptr_t, ...)))Sys_LoadFunction(libHandle, "dllEntry");
	*entryPoint = (intptr_t (QDECL *)(int, ...))Sys_LoadFunction(libHandle, "vmMain");

	if (!*entryPoint || !dllEntry)
	{
		Com_Printf("Sys_LoadDll(%s/%s) failed to find vmMain function:\n\"%s\" !\n", gamedir, name, Sys_LibraryError());
		Sys_UnloadLibrary(libHandle);

		return NULL;
	}

	Com_Printf("Sys_LoadDll(%s/%s) found vmMain function at %p\n", gamedir, name, *entryPoint);
	dllEntry(systemcalls);

	return libHandle;
}
Пример #3
0
/*
=================
Sys_LoadDll

Used to load a development dll instead of a virtual machine
#1 look in fs_homepath
#2 look in fs_basepath
#4 look in fs_libpath under FreeBSD
=================
*/
void *QDECL Sys_LoadDll( const char *name, char *fqpath, intptr_t (QDECL  **entryPoint)(int, ...), intptr_t (QDECL *systemcalls)(intptr_t, ...) ) {
	void    *libHandle = NULL, (QDECL *dllEntry)( intptr_t (QDECL *syscallptr)(intptr_t, ...) );
	char    fname[MAX_QPATH], *basepath, *homepath, *gamedir, *libpath;

	assert( name );

	//Q_snprintf (fname, sizeof(fname), Sys_GetDLLName( "%s" ), name);
	Q_strncpyz(fname, Sys_GetDLLName(name), sizeof(fname));

    // TODO: use fs_searchpaths from files.c
    basepath = Cvar_VariableString( "fs_basepath" );
    homepath = Cvar_VariableString( "fs_homepath" );
    gamedir = Cvar_VariableString( "fs_game" );
	libpath = Cvar_VariableString( "fs_libpath" );

#ifndef DEDICATED
    // if the server is pure, extract the dlls from the mp_bin.pk3 so
    // that they can be referenced
    if ( Cvar_VariableValue( "sv_pure" ) && Q_stricmp( name, "qagame" ) ) {
		FS_CL_ExtractFromPakFile( homepath, gamedir, fname );
    }
#endif

	libHandle = Sys_TryLibraryLoad(homepath, gamedir, fname, fqpath);

	if (!libHandle && libpath && libpath[0]) {
		libHandle = Sys_TryLibraryLoad(libpath, gamedir, fname, fqpath);
	}

	if(!libHandle && basepath) {
		libHandle = Sys_TryLibraryLoad(basepath, gamedir, fname, fqpath);
	}

	if(!libHandle) {
		Com_Printf( "Sys_LoadDll(%s) could not find it\n", fname );
		return NULL;
	}

	if(!libHandle) {
		Com_Printf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", name, Sys_LibraryError() );
		return NULL;
	}

	// Try to load the dllEntry and vmMain function.
	dllEntry = ( void ( QDECL * )( intptr_t ( QDECL * )( intptr_t, ... ) ) )Sys_LoadFunction( libHandle, "dllEntry" );
	*entryPoint = ( intptr_t ( QDECL * )( int,... ) )Sys_LoadFunction( libHandle, "vmMain" );

	if ( !*entryPoint || !dllEntry ) {
#ifndef NDEBUG
		if (!dllEntry) {
			Com_Error ( ERR_FATAL, "Sys_LoadDll(%s) failed SDL_LoadFunction(dllEntry):\n\"%p\" !\n", name, Sys_LibraryError() );
		} else {
			Com_Error ( ERR_FATAL, "Sys_LoadDll(%s) failed SDL_LoadFunction(vmMain):\n\"%p\" !\n", name, Sys_LibraryError() );
		}
#else
		if (!dllEntry) {
			Com_Printf ( "Sys_LoadDll(%s) failed SDL_LoadFunction(dllEntry):\n\"%p\" !\n", name, Sys_LibraryError() );
		} else {
			Com_Printf ( "Sys_LoadDll(%s) failed SDL_LoadFunction(vmMain):\n\"%p\" !\n", name, Sys_LibraryError() );
		}
#endif
		Sys_UnloadLibrary(libHandle);
		return NULL;
	}

	Com_Printf ( "Sys_LoadDll(%s) found vmMain function at %p\n", name, *entryPoint );
	dllEntry( systemcalls );

	Com_Printf ( "Sys_LoadDll(%s) succeeded!\n", name );

	// Copy the fname to fqpath.
	Q_strncpyz ( fqpath , fname , MAX_QPATH ) ;

	return libHandle;
}
Пример #4
0
/**
 * @brief Loads a mod library.
 * #1 look in fs_homepath
 * #2 look in fs_basepath
 * #3 try to revert to the default mod library
 */
void *Sys_LoadDll(const char *name,
                  intptr_t(**entryPoint) (int, ...),
                  intptr_t (*systemcalls)(intptr_t, ...))
{
	void *libHandle;
	void (*dllEntry)(intptr_t (*syscallptr)(intptr_t, ...));
	char fname[MAX_OSPATH];
	char *basepath;
	char *homepath;
	char *gamedir;

	assert(name);

	Com_sprintf(fname, sizeof(fname), Sys_GetDLLName("%s"), name);

	// TODO: use fs_searchpaths from files.c
	basepath = Cvar_VariableString("fs_basepath");
	homepath = Cvar_VariableString("fs_homepath");
	gamedir  = Cvar_VariableString("fs_game");

#ifndef DEDICATED
	// if the server is pure, extract the dlls from the mp_bin.pk3 so
	// that they can be referenced
	if (Cvar_VariableValue("sv_pure") && Q_stricmp(name, "qagame"))
	{
		FS_CL_ExtractFromPakFile(homepath, gamedir, fname);
	}
#endif

	libHandle = Sys_TryLibraryLoad(homepath, gamedir, fname);

	if (!libHandle && basepath)
	{
		libHandle = Sys_TryLibraryLoad(basepath, gamedir, fname);
	}

	// HACK: sometimes a library is loaded from the mod dir when it shouldn't. Why?
	if (!libHandle && strcmp(gamedir, DEFAULT_MODGAME))
	{
		Com_Printf("Sys_LoadDll: failed to load the mod library. Trying to revert to the default one.\n");
		libHandle = Sys_TryLibraryLoad(basepath, DEFAULT_MODGAME, fname);
	}

	if (!libHandle)
	{
		Com_Printf("Sys_LoadDll(%s) failed to load library\n", name);
		return NULL;
	}

	dllEntry    = (void (QDECL *)(intptr_t (QDECL *)(intptr_t, ...)))Sys_LoadFunction(libHandle, "dllEntry");
	*entryPoint = (intptr_t (QDECL *)(int, ...))Sys_LoadFunction(libHandle, "vmMain");

	if (!*entryPoint || !dllEntry)
	{
		Com_Printf("Sys_LoadDll(%s) failed to find vmMain function:\n\"%s\" !\n", name, Sys_LibraryError());
		Sys_UnloadLibrary(libHandle);

		return NULL;
	}

	Com_Printf("Sys_LoadDll(%s) found vmMain function at %p\n", name, *entryPoint);
	dllEntry(systemcalls);

	return libHandle;
}
Пример #5
0
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;
}