/** * @brief Used by Sys_LoadDll to get handle on a mod library * @return Handle to a mod library */ static void *Sys_TryLibraryLoad(const char *base, const char *gamedir, const char *fname) { void *libHandle; char *fn; fn = FS_BuildOSPath(base, gamedir, fname); #ifdef __APPLE__ if (FS_Unzip(fn, qtrue)) { char buffer[MAX_OSPATH]; Com_sprintf(buffer, sizeof(buffer), "%s.bundle/Contents/MacOS/%s", fname, fname); fn = FS_BuildOSPath(Cvar_VariableString("fs_homepath"), gamedir, buffer); } #endif // __APPLE__ Com_Printf("Sys_LoadDll(%s)... ", fn); libHandle = Sys_LoadLibrary(fn); if (!libHandle) { Com_Printf("failed: \"%s\"\n", Sys_LibraryError()); return NULL; } Com_Printf("succeeded\n"); return libHandle; }
/* =========== FS_FOpenFileAppend =========== */ fileHandle_t FS_FOpenFileAppend( const char *filename ) { char *ospath; fileHandle_t f; if ( !fs_searchpaths ) { Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" ); } f = FS_HandleForFile(); fsh[f].zipFile = qfalse; Q_strncpyz( fsh[f].name, filename, sizeof( fsh[f].name ) ); // don't let sound stutter S_ClearSoundBuffer(); #ifdef _XBOX ospath = FS_BuildOSPath( filename ); #else ospath = FS_BuildOSPath( fs_basepath->string, fs_gamedir, filename ); #endif if ( fs_debug->integer ) { Com_Printf( "FS_FOpenFileAppend: %s\n", ospath ); } FS_CreatePath( ospath ); fsh[f].handleFiles.file.o = fopen( ospath, "ab" ); fsh[f].handleSync = qfalse; if (!fsh[f].handleFiles.file.o) { f = 0; } return f; }
/** * @brief Displays an error message and writes the error into crashlog.txt * @param[in] error Error String */ void Sys_ErrorDialog(const char *error) { char buffer[1024]; unsigned int size; int f = -1; const char *homepath = Cvar_VariableString("fs_homepath"); const char *gamedir = Cvar_VariableString("fs_gamedir"); const char *fileName = "crashlog.txt"; char *dirpath = FS_BuildOSPath(homepath, gamedir, ""); char *ospath = FS_BuildOSPath(homepath, gamedir, fileName); Sys_Print(va("%s\n", error)); #ifndef DEDICATED // We may have grabbed input devices. Need to release. if (SDL_WasInit(SDL_INIT_VIDEO)) { SDL_WM_GrabInput(SDL_GRAB_OFF); } Sys_Dialog(DT_ERROR, va("%s\nSee \"%s\" for details.\n", error, ospath), "Error"); #endif // Make sure the write path for the crashlog exists... // check homepath if (!Sys_Mkdir(homepath)) { Com_Printf("ERROR: couldn't create path '%s' to write file '%s'.\n", homepath, ospath); return; } // check gamedir (inside homepath) if (!Sys_Mkdir(dirpath)) { Com_Printf("ERROR: couldn't create path '%s' to write file '%s'.\n", dirpath, ospath); return; } // We might be crashing because we maxed out the Quake MAX_FILE_HANDLES, // which will come through here, so we don't want to recurse forever by // calling FS_FOpenFileWrite()...use the Unix system APIs instead. f = open(ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640); if (f == -1) { Com_Printf("ERROR: couldn't open '%s'\n", fileName); return; } // We're crashing, so we don't care much if write() or close() fails. while ((size = CON_LogRead(buffer, sizeof(buffer))) > 0) { if (write(f, buffer, size) != size) { Com_Printf("ERROR: couldn't fully write to '%s'\n", fileName); break; } } close(f); }
//TODO: error handling? int VMBase::Create(const char* name, Type type) { if (module) { Com_Printf(S_ERROR "Attempting to re-create an already-loaded VM"); return -1; } // TODO: Proper interaction with FS code const char* gameDir = Cvar_VariableString("fs_game"); const char* libPath = Cvar_VariableString("fs_libpath"); bool debug = Cvar_Get("vm_debug", "0", CVAR_INIT)->integer; if (type == TYPE_NATIVE) { char exe[MAX_QPATH]; Com_sprintf(exe, sizeof(exe), "%s%s", name, EXE_EXT); const char* path = FS_BuildOSPath(libPath, gameDir, exe); Com_Printf("Trying to load native module %s\n", path); module = NaCl::LoadModule(path, nullptr, debug); } else if (type == TYPE_NACL) { char nexe[MAX_QPATH]; char sel_ldr[MAX_QPATH]; char irt[MAX_QPATH]; #ifdef __linux__ char bootstrap[MAX_QPATH]; Com_sprintf(bootstrap, sizeof(bootstrap), "%s/nacl_helper_bootstrap%s", libPath, EXE_EXT); #else const char* bootstrap = nullptr; #endif Com_sprintf(nexe, sizeof(nexe), "%s-%s.nexe", name, ARCH_STRING); Com_sprintf(sel_ldr, sizeof(sel_ldr), "%s/sel_ldr%s", libPath, EXE_EXT); Com_sprintf(irt, sizeof(irt), "%s/irt_core-%s.nexe", libPath, ARCH_STRING); NaCl::LoaderParams params = {sel_ldr, irt, bootstrap}; const char* path = FS_BuildOSPath(libPath, gameDir, nexe); Com_Printf("Trying to load NaCl module %s\n", path); module = NaCl::LoadModule(path, ¶ms, debug); } else { Com_Printf(S_ERROR "Invalid VM type"); return -1; } if (!module) { Com_Printf(S_ERROR "Couldn't load VM %s", name); return -1; } if (debug) Com_Printf("Waiting for GDB connection on localhost:4014\n"); // Read the ABI version from the root socket. // If this fails, we assume the remote process failed to start std::vector<char> buffer; if (!module.GetRootSocket().RecvMsg(buffer) || buffer.size() != sizeof(int)) { Com_Printf(S_ERROR "The '%s' VM did not start.", name); return -1; } Com_Printf("Loaded module with the NaCl ABI"); return *reinterpret_cast<int*>(buffer.data()); }
/* ================ FS_GetFileList Returns a uniqued list of files that match the given criteria from all search paths ================ */ int FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize ) { int nfiles = 0; int i; char *netpath; int numSysFiles; char **sysFiles; char *name; FS_CheckInit(); if ( !path ) { return 0; } if ( !extension ) { extension = ""; } // Prime the file list buffer listbuf[0] = '\0'; netpath = FS_BuildOSPath( path ); #ifdef _JK2MP sysFiles = Sys_ListFiles( netpath, extension, NULL, &numSysFiles, qfalse ); #else sysFiles = Sys_ListFiles( netpath, extension, &numSysFiles, qfalse ); #endif for ( i = 0 ; i < numSysFiles ; i++ ) { // unique the match name = sysFiles[i]; nfiles = FS_AddFileToListBuf( name, listbuf, bufsize, nfiles ); } Sys_FreeFileList( sysFiles ); return nfiles; }
/* =========== FS_FOpenDemoFileWrite =========== */ qboolean FS_FOpenDemoFileWrite( const char *filename, fileHandleData_t *fh ) { char *ospath; if ( !fs_searchpaths ) { Com_Error( ERR_FATAL, "Filesystem call made without initialization" ); } ospath = FS_BuildOSPath( fs_homepath->string, filename, "" ); ospath[strlen(ospath)-1] = '\0'; fh->zipFile = qfalse; if ( fs_debug->boolean ) { Com_Printf( "FS_SV_FOpenDemoFileWrite: %s\n", ospath ); } if( FS_CreatePath( ospath ) ) { return qfalse; } fh->handleFiles.file.o = fopen( ospath, "wb" ); Q_strncpyz( fh->name, filename, sizeof( fh->name ) ); fh->handleSync = qfalse; if (!fh->handleFiles.file.o) { return qfalse; } fh->writebuffer = Z_Malloc(FS_DEMOWRITEBUF_SIZE); fh->bufferSize = FS_DEMOWRITEBUF_SIZE; return qtrue; }
/* =========== FS_FOpenDemoFileWrite =========== */ fileHandle_t FS_FOpenDemoFileWrite( const char *filename ) { char *ospath; fileHandle_t f; if ( !fs_searchpaths ) { Com_Error( ERR_FATAL, "Filesystem call made without initialization" ); } ospath = FS_BuildOSPath( fs_homepath->string, filename, "" ); ospath[strlen(ospath)-1] = '\0'; f = FS_HandleForDemoFile(); demofsh[f].zipFile = qfalse; if ( fs_debug->boolean ) { Com_Printf( "FS_SV_FOpenDemoFileWrite: %s\n", ospath ); } if( FS_CreatePath( ospath ) ) { return 0; } demofsh[f].handleFiles.file.o = fopen( ospath, "wb" ); Q_strncpyz( demofsh[f].name, filename, sizeof( demofsh[f].name ) ); demofsh[f].handleSync = qfalse; if (!demofsh[f].handleFiles.file.o) { f = 0; } return f; }
/** * @brief saves memory db to disk * * @return */ int DB_SaveMemDB() { if (db_mode->integer == 1) { int result, msec; char *to_ospath; // FIXME: check for empty db_url to_ospath = FS_BuildOSPath(Cvar_VariableString("fs_homepath"), db_url->string, ""); to_ospath[strlen(to_ospath) - 1] = '\0'; msec = Sys_Milliseconds(); result = DB_LoadOrSaveDb(db, to_ospath, 1); if (result != SQLITE_OK) { Com_Printf("... WARNING can't save memory database file [%i]\n", result); return 1; } Com_Printf("SQLite3 in-memory tables saved to disk @[%s] in [%i] msec\n", to_ospath, (Sys_Milliseconds() - msec)); } else { Com_Printf("saveMemDB called for unknown database mode\n"); } return 0; }
/* =========== FS_SV_FOpenFileRead =========== */ int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp ) { char *ospath; fileHandle_t f; if ( !fs_searchpaths ) { Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" ); } f = FS_HandleForFile(); fsh[f].zipFile = qfalse; Q_strncpyz( fsh[f].name, filename, sizeof( fsh[f].name ) ); // don't let sound stutter S_ClearSoundBuffer(); #ifdef _XBOX ospath = FS_BuildOSPath( filename ); #else ospath = FS_BuildOSPath( fs_basepath->string, filename, "" ); #endif // remove trailing slash ospath[strlen(ospath)-1] = '\0'; if ( fs_debug->integer ) { Com_Printf( "FS_SV_FOpenFileRead: %s\n", ospath ); } fsh[f].handleFiles.file.o = fopen( ospath, "rb" ); fsh[f].handleSync = qfalse; if (!fsh[f].handleFiles.file.o) { f = 0; } *fp = f; if (f) { return FS_filelength(f); } return 0; }
/** * @brief DB_Create * * @return */ int DB_Create() { int result; if (db_mode->integer == 1) { //result = sqlite3_open(":memory:", &db); // memory table, not shared see https://www.sqlite.org/inmemorydb.html result = sqlite3_open("file::memory:?cache=shared", &db); // In-memory databases with shared cache if (result != SQLITE_OK) { Com_Printf("... failed to create memory database - error: %s\n", sqlite3_errstr(result)); (void) sqlite3_close(db); return 1; } } else if (db_mode->integer == 2) { char *to_ospath; to_ospath = FS_BuildOSPath(Cvar_VariableString("fs_homepath"), db_url->string, ""); // FIXME: check for empty db_url to_ospath[strlen(to_ospath) - 1] = '\0'; result = sqlite3_open(to_ospath, &db); if (result != SQLITE_OK) { Com_Printf("... failed to create file database - error: %s\n", sqlite3_errstr(result)); (void) sqlite3_close(db); return 1; } } else { Com_Printf("... DB_Create failed - unknown mode\n"); return 1; } result = DB_Create_Schema(); if (result != 0) { Com_Printf("... failed to create database schema\n"); (void) sqlite3_close(db); return 1; } Com_Printf("... database %s created\n", db_url->string); return 0; }
/* ================= Try_CopyDLLForMod little utility function for media-only mods tries to copy a reference DLL to the mod's fs_homepath return false if failed, or if we are not in a mod situation returns true if successful, *p_fn is set to the correct path this is used when we are loading a mod and realize we don't have the DLL in the standard path ================= */ qboolean CopyDLLForMod( char **p_fn, const char* gamedir, const char *pwdpath, const char *homepath, const char *basepath, const char *fname ) { char *fn = *p_fn; // this may be a media only mod, so next we need to search in the basegame if ( strlen( gamedir ) && Q_stricmp( gamedir, BASEGAME ) ) { // walk for a base file // NOTE TTimo: we don't attempt to validate version-wise, it could be a problem // (acceptable tradeoff I say, should not cause major issues) #ifndef NDEBUG fn = FS_BuildOSPath( pwdpath, BASEGAME, fname ); if ( access( fn, R_OK ) == -1 ) { #endif fn = FS_BuildOSPath( homepath, BASEGAME, fname ); if ( access( fn, R_OK ) == -1 ) { fn = FS_BuildOSPath( basepath, BASEGAME, fname ); if ( access( fn, R_OK ) == -1 ) { return qfalse; // this one is hopeless } } #ifndef NDEBUG } #endif // basefile found, we copy to homepath in all cases // fortunately FS_BuildOSPath does a flip flop, we have 'from path' in fn and 'to path' in *p_fn *p_fn = FS_BuildOSPath( homepath, gamedir, fname ); // copy to destination FS_CopyFile( fn, *p_fn ); if ( access( *p_fn, R_OK ) == -1 ) { // could do with FS_CopyFile returning a boolean actually Com_DPrintf( "Copy operation failed\n" ); return qfalse; } return qtrue; } else { return qfalse; } }
static int FS_FOpenFileReadOS( const char *filename, fileHandle_t f ) { if (Sys_GetFileCode(filename) != -1) { char* osname = FS_BuildOSPath( filename ); fsh[f].whandle = WF_Open(osname, true, false); if (fsh[f].whandle >= 0) { fsh[f].used = qtrue; fsh[f].gob = qfalse; return FS_filelength(f); } } return -1; }
/* ================ FS_DemoFileExists Tests if the file exists in the current gamedir, this DOES NOT search the paths. This is to determine if opening a file to write (which always goes into the current gamedir) will cause any overwrites. NOTE TTimo: this goes with FS_FOpenFileWrite for opening the file afterwards ================ */ qboolean FS_DemoFileExists( const char *file ) { FILE *f; char *testpath; testpath = FS_BuildOSPath( fs_homepath->string, file, "" ); testpath[strlen(testpath)-1] = '\0'; f = fopen( testpath, "rb" ); if (f) { fclose( f ); return qtrue; } return qfalse; }
static void Com_SetupDownload(const char *remote, const char *filename) { dld.bWWWDl = qtrue; dld.bWWWDlDisconnected = qtrue; // download format: @remotename@localname Q_strncpyz(dld.downloadList, va("@%s@%s", filename, filename), MAX_INFO_STRING); Q_strncpyz(dld.originalDownloadName, va("%s/%s", Cvar_VariableString("fs_game"), filename), sizeof(dld.originalDownloadName)); Q_strncpyz(dld.downloadName, va("%s/%s", remote, filename), sizeof(dld.downloadName)); Q_strncpyz(dld.downloadTempName, FS_BuildOSPath(Cvar_VariableString("fs_homepath"), Cvar_VariableString("fs_game"), va("%s.tmp", filename)), sizeof(dld.downloadTempName)); if (!DL_BeginDownload(dld.downloadTempName, dld.downloadName)) { Com_Error(ERR_DROP, "Could not download file: \"%s\"", dld.downloadName); dld.bWWWDlAborting = qtrue; } }
fileHandle_t FS_FOpenFileWrite( const char *filename ) { FS_CheckInit(); fileHandle_t f = FS_HandleForFile(); char* osname = FS_BuildOSPath( filename ); fsh[f].whandle = WF_Open(osname, false, false); if (fsh[f].whandle >= 0) { fsh[f].used = qtrue; fsh[f].gob = qfalse; return f; } return 0; }
/** * @brief Display an error message * @param[in] error Error String */ void Sys_ErrorDialog(const char *error) { char buffer[1024]; unsigned int size; int f = -1; const char *homepath = Cvar_VariableString("fs_homepath"); const char *gamedir = Cvar_VariableString("fs_gamedir"); const char *fileName = "crashlog.txt"; char *ospath = FS_BuildOSPath(homepath, gamedir, fileName); Sys_Print(va("%s\n", error)); #ifndef DEDICATED Sys_Dialog(DT_ERROR, va("%s\nSee \"%s\" for details.\n", error, ospath), "Error"); #endif // Make sure the write path for the crashlog exists... if (FS_CreatePath(ospath)) { Com_Printf("ERROR: couldn't create path '%s' for crash log.\n", ospath); return; } // We might be crashing because we maxed out the Quake MAX_FILE_HANDLES, // which will come through here, so we don't want to recurse forever by // calling FS_FOpenFileWrite()...use the Unix system APIs instead. f = open(ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640); if (f == -1) { Com_Printf("ERROR: couldn't open %s\n", fileName); return; } // We're crashing, so we don't care much if write() or close() fails. while ((size = CON_LogRead(buffer, sizeof(buffer))) > 0) { if (write(f, buffer, size) != size) { Com_Printf("ERROR: couldn't fully write to %s\n", fileName); break; } } close(f); }
int Sys_GetFileCode(const char* name) { WaitForSingleObject(s_Mutex, INFINITE); // Get system level path char* osname = FS_BuildOSPath(name); // Generate hash for file name Q_strlwr(osname); unsigned int code = crc32(0, (const byte *)osname, strlen(osname)); // Check if the file exists if (!s_Files->Find(code)) { ReleaseMutex(s_Mutex); return -1; } ReleaseMutex(s_Mutex); return code; }
void *Sys_LoadMachOBundle( const char *name ) { if ( !FS_LoadMachOBundle(name) ) return NULL; char *homepath = Cvar_VariableString( "fs_homepath" ); char *gamedir = Cvar_VariableString( "fs_game" ); char dllName[MAX_QPATH]; Com_sprintf( dllName, sizeof(dllName), "%s_pk3" DLL_EXT, name ); //load the unzipped library char *fn = FS_BuildOSPath( homepath, gamedir, dllName ); void *libHandle = Sys_LoadLibrary( fn ); if ( libHandle != NULL ) { Com_Printf( "Loaded pk3 bundle %s.\n", name ); } return libHandle; }
/* ================= Sys_TryLibraryLoad ================= */ static void* Sys_TryLibraryLoad(const char* base, const char* gamedir, const char* fname, char* fqpath ) { void* libHandle; char* fn; *fqpath = 0; fn = FS_BuildOSPath( base, gamedir, fname ); Com_Printf( "Sys_LoadDll(%s)... \n", fn ); libHandle = Sys_LoadLibrary(fn); if(!libHandle) { Com_Printf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", fn, Sys_LibraryError() ); return NULL; } Com_Printf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); Q_strncpyz ( fqpath , fn , MAX_QPATH ) ; return libHandle; }
void *Sys_LoadDll( const char *name, int( **entryPoint ) ( int, ... ), int ( *systemcalls )( int, ... ) ) #endif { void *libHandle; void ( *dllEntry )( int ( *syscallptr )( int, ... ) ); char fname[MAX_OSPATH]; char *homepath; char *basepath; char *pwdpath; char *gamedir; char *fn; const char* err = NULL; // bk001206 // rb0101023 - now const // bk001206 - let's have some paranoia assert( name ); #if defined __i386__ snprintf( fname, sizeof( fname ), "%si386.so", name ); #elif defined __powerpc__ //rcg010207 - PPC support. snprintf( fname, sizeof( fname ), "%sppc.so", name ); #elif defined __axp__ snprintf( fname, sizeof( fname ), "%saxp.so", name ); #elif defined __mips__ snprintf( fname, sizeof( fname ), "%smips.so", name ); #elif defined __arm__ snprintf( fname, sizeof( fname ), "%sarm.so", name ); #else #error Unknown arch #endif // bk001129 - was RTLD_LAZY #define Q_RTLD RTLD_NOW homepath = Cvar_VariableString( "fs_homepath" ); basepath = Cvar_VariableString( "fs_basepath" ); gamedir = Cvar_VariableString( "fs_game" ); pwdpath = Sys_Cwd(); fn = FS_BuildOSPath( pwdpath, gamedir, fname ); // bk001206 - verbose Com_Printf( "Sys_LoadDll(%s)... ", fn ); // bk001129 - from cvs1.17 (mkv), was fname not fn libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { Com_Printf( "failed (%s)\n", dlerror() ); // homepath fn = FS_BuildOSPath( homepath, gamedir, fname ); Com_Printf( "Sys_LoadDll(%s)... ", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { Com_Printf( "failed (%s)\n", dlerror() ); // basepath fn = FS_BuildOSPath( basepath, gamedir, fname ); Com_Printf( "Sys_LoadDll(%s)... ", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { Com_Printf( "failed (%s)\n", dlerror() ); if ( strlen( gamedir ) && Q_stricmp( gamedir, BASEGAME ) ) { // begin BASEGAME != fs_game section // media-only mods: no DLL whatsoever in the fs_game // start the loop again using the hardcoded BASEDIRNAME fn = FS_BuildOSPath( pwdpath, BASEGAME, fname ); Com_Printf( "Sys_LoadDll(%s)... ", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { Com_Printf( "failed (%s)\n", dlerror() ); // homepath fn = FS_BuildOSPath( homepath, BASEGAME, fname ); Com_Printf( "Sys_LoadDll(%s)... ", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { Com_Printf( "failed (%s)\n", dlerror() ); // homepath fn = FS_BuildOSPath( basepath, BASEGAME, fname ); Com_Printf( "Sys_LoadDll(%s)... ", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { // ok, this time things are really f****d Com_Printf( "failed (%s)\n", dlerror() ); } else { Com_Printf( "ok\n" ); } } else { Com_Printf( "ok\n" ); } } else { Com_Printf( "ok\n" ); } } // end BASEGAME != fs_game section } else { Com_Printf( "ok\n" ); } } else { Com_Printf( "ok\n" ); } } else { Com_Printf( "ok\n" ); } 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; } dllEntry = dlsym( libHandle, "dllEntry" ); *entryPoint = dlsym( libHandle, "vmMain" ); if ( !*entryPoint || !dllEntry ) { err = dlerror(); #ifndef NDEBUG // bk001206 - 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 ); // bk001212 dllEntry( systemcalls ); Com_Printf( "Sys_LoadDll(%s) succeeded!\n", name ); return libHandle; }
/* ================== Com_WWWDownload ================== */ void Com_WWWDownload(void) { char *to_ospath; dlStatus_t ret; static qboolean bAbort = qfalse; if (dld.bWWWDlAborting) { if (!bAbort) { Com_DPrintf("Com_WWWDownload: WWWDlAborting\n"); bAbort = qtrue; } return; } if (bAbort) { Com_DPrintf("Com_WWWDownload: WWWDlAborting done\n"); bAbort = qfalse; } ret = DL_DownloadLoop(); if (ret == DL_CONTINUE) { return; } if (ret == DL_DONE) { // taken from CL_ParseDownload // we work with OS paths dld.download = 0; to_ospath = FS_BuildOSPath(Cvar_VariableString("fs_homepath"), dld.originalDownloadName, ""); to_ospath[strlen(to_ospath) - 1] = '\0'; if (rename(dld.downloadTempName, to_ospath)) { FS_CopyFile(dld.downloadTempName, to_ospath); remove(dld.downloadTempName); } *dld.downloadTempName = *dld.downloadName = 0; Cvar_Set("cl_downloadName", ""); if (dld.bWWWDlDisconnected) { // for an auto-update in disconnected mode, we'll be spawning the setup in CL_DownloadsComplete if (!autoupdate.updateStarted && !dld.noReconnect) { // reconnect to the server, which might send us to a new disconnected download Cbuf_ExecuteText(EXEC_APPEND, "reconnect\n"); } } else { Com_AddReliableCommand("wwwdl done"); // tracking potential web redirects leading us to wrong checksum - only works in connected mode if (strlen(dld.redirectedList) + strlen(dld.originalDownloadName) + 1 >= sizeof(dld.redirectedList)) { // just to be safe Com_Printf("ERROR: redirectedList overflow (%s)\n", dld.redirectedList); } else { strcat(dld.redirectedList, "@"); strcat(dld.redirectedList, dld.originalDownloadName); } } } else { if (dld.bWWWDlDisconnected) { // in a connected download, we'd tell the server about failure and wait for a reply // but in this case we can't get anything from server // if we just reconnect it's likely we'll get the same disconnected download message, and error out again // this may happen for a regular dl or an auto update const char *error = va("Download failure while getting '%s'\n", dld.downloadName); // get the msg before clearing structs dld.bWWWDlDisconnected = qfalse; // need clearing structs before ERR_DROP, or it goes into endless reload Com_ClearStaticDownload(); Com_Error(ERR_DROP, "%s", error); } else { // see CL_ParseDownload, same abort strategy Com_Printf("Download failure while getting '%s'\n", dld.downloadName); Com_AddReliableCommand("wwwdl fail"); dld.bWWWDlAborting = qtrue; } return; } dld.bWWWDl = qfalse; Com_NextDownload(); }
/** * @brief Used by Sys_LoadGameDll to get handle on a mod library * @return Handle to a mod library */ static void *Sys_TryLibraryLoad(const char *base, const char *gamedir, const char *fname) { void *libHandle; char *fn; #ifdef __MORPHOS__ int (*morphos_so_init)(void); void (*morphos_so_deinit)(void); #endif #ifdef __APPLE__ Com_Printf("Sys_LoadDll -> Sys_TryLibraryLoad(%s, %s, %s)... \n", base, gamedir, fname); libHandle = NULL; // Incoming is (for example) "cgame_mac" // What we may actually have is: // 1) A zipped .bundle package // 2) A .dylib without an extension // 3) A .dylib with an extension we need to append. // // In older versions of OS X (pre 10.5), dylibs could not be unloaded allowing the host process to reclaim that address space. // This is why .bundles were used instead. When W:ET originally shipped, it used used .bundle packages for the VM libraries, // but to make them single files, it zipped that .bundle package and had no extension at all (ie just "cgame_mac"). But now // that dylibs can be unloaded, there's no practical difference between the two (for W:ET's purposes), so using a single file // dylib is simpler. That's why we now support a dylib with some backward compatibility to allow .bundles. // 1: The zipped .bundle package { Com_Printf("-- Trying zipped .bundle... "); fn = FS_BuildOSPath(base, gamedir, fname); if (FS_Unzip(fn, qtrue)) { char buffer[MAX_OSPATH]; Com_sprintf(buffer, sizeof(buffer), "%s.bundle/Contents/MacOS/%s", fname, fname); fn = FS_BuildOSPath(Cvar_VariableString("fs_homepath"), gamedir, buffer); libHandle = Sys_LoadLibrary(fn); if (!libHandle) { Com_Printf("failed: \"%s\"\n", Sys_LibraryError()); } else { Com_Printf("succeeded\n"); } } else { Com_Printf("failed. (Not a zip).\n"); } } // 2: The dylib without an extension if (!libHandle) { fn = FS_BuildOSPath(base, gamedir, fname); Com_Printf("-- Trying extension-less dylib... "); libHandle = Sys_LoadLibrary(fn); if (!libHandle) { Com_Printf("failed: \"%s\"\n", Sys_LibraryError()); } else { Com_Printf("succeeded\n"); } } // 3: The dylib with an extension if (!libHandle) { char buffer[MAX_OSPATH]; Com_sprintf(buffer, sizeof(buffer), "%s.dylib", fname); fn = FS_BuildOSPath(Cvar_VariableString("fs_homepath"), gamedir, buffer); Com_Printf("-- Trying dylib with extension... "); libHandle = Sys_LoadLibrary(fn); if (!libHandle) { Com_Printf("failed: \"%s\"\n", Sys_LibraryError()); } else { Com_Printf("succeeded\n"); } } return libHandle; #else // __APPLE__ fn = FS_BuildOSPath(base, gamedir, fname); Com_Printf("Sys_LoadDll(%s)... ", fn); libHandle = Sys_LoadLibrary(fn); if (!libHandle) { Com_Printf("failed: \"%s\"\n", Sys_LibraryError()); return NULL; } #endif // __APPLE__ #ifdef __MORPHOS__ morphos_so_init = dlsym(libHandle, "morphos_so_init"); morphos_so_deinit = dlsym(libHandle, "morphos_so_deinit"); if (!(morphos_so_init && morphos_so_deinit && morphos_so_init())) { Com_Printf("failed: \"can't find the morphos_so_init and morphos_so_deinit symbols\"\n"); Sys_UnloadLibrary(libHandle); return NULL; } #endif Com_Printf("succeeded\n"); return libHandle; }
/* ===================== CL_ParseDownload A download message has been received from the server ===================== */ void CL_ParseDownload( msg_t *msg ) { int size; unsigned char data[ MAX_MSGLEN ]; int block; if ( !*cls.downloadTempName ) { Com_Printf("%s", _( "Server sending download, but no download was requested\n" )); CL_AddReliableCommand( "stopdl" ); return; } // read the data block = MSG_ReadShort( msg ); // TTimo - www dl // if we haven't acked the download redirect yet if ( block == -1 ) { if ( !clc.bWWWDl ) { // server is sending us a www download Q_strncpyz( cls.originalDownloadName, cls.downloadName, sizeof( cls.originalDownloadName ) ); Q_strncpyz( cls.downloadName, MSG_ReadString( msg ), sizeof( cls.downloadName ) ); clc.downloadSize = MSG_ReadLong( msg ); clc.downloadFlags = MSG_ReadLong( msg ); Cvar_SetValue( "cl_downloadSize", clc.downloadSize ); Com_DPrintf( "Server redirected download: %s\n", cls.downloadName ); clc.bWWWDl = qtrue; // activate wwwdl client loop CL_AddReliableCommand( "wwwdl ack" ); // make sure the server is not trying to redirect us again on a bad checksum if ( strstr( clc.badChecksumList, va( "@%s", cls.originalDownloadName ) ) ) { Com_Printf(_( "refusing redirect to %s by server (bad checksum)\n"), cls.downloadName ); CL_AddReliableCommand( "wwwdl fail" ); clc.bWWWDlAborting = qtrue; return; } // make downloadTempName an OS path Q_strncpyz( cls.downloadTempName, FS_BuildOSPath( Cvar_VariableString( "fs_homepath" ), cls.downloadTempName, "" ), sizeof( cls.downloadTempName ) ); cls.downloadTempName[ strlen( cls.downloadTempName ) - 1 ] = '\0'; if ( !DL_BeginDownload( cls.downloadTempName, cls.downloadName, com_developer->integer ) ) { // setting bWWWDl to false after sending the wwwdl fail doesn't work // not sure why, but I suspect we have to eat all remaining block -1 that the server has sent us // still leave a flag so that CL_WWWDownload is inactive // we count on server sending us a gamestate to start up clean again CL_AddReliableCommand( "wwwdl fail" ); clc.bWWWDlAborting = qtrue; Com_Printf(_( "Failed to initialize download for '%s'\n"), cls.downloadName ); } // Check for a disconnected download // we'll let the server disconnect us when it gets the bbl8r message if ( clc.downloadFlags & ( 1 << DL_FLAG_DISCON ) ) { CL_AddReliableCommand( "wwwdl bbl8r" ); cls.bWWWDlDisconnected = qtrue; } return; } else { // server keeps sending that message till we ack it, eat and ignore //MSG_ReadLong( msg ); MSG_ReadString( msg ); MSG_ReadLong( msg ); MSG_ReadLong( msg ); return; } } if ( !block ) { // block zero is special, contains file size clc.downloadSize = MSG_ReadLong( msg ); Cvar_SetValue( "cl_downloadSize", clc.downloadSize ); if ( clc.downloadSize < 0 ) { Com_Error( ERR_DROP, "%s", MSG_ReadString( msg ) ); } } size = MSG_ReadShort( msg ); if ( size < 0 || size > sizeof( data ) ) { Com_Error( ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk.", size ); } MSG_ReadData( msg, data, size ); if ( clc.downloadBlock != block ) { Com_DPrintf( "CL_ParseDownload: Expected block %d, got %d\n", clc.downloadBlock, block ); return; } // open the file if not opened yet if ( !clc.download ) { clc.download = FS_SV_FOpenFileWrite( cls.downloadTempName ); if ( !clc.download ) { Com_Printf(_( "Could not create %s\n"), cls.downloadTempName ); CL_AddReliableCommand( "stopdl" ); CL_NextDownload(); return; } } if ( size ) { FS_Write( data, size, clc.download ); } CL_AddReliableCommand( va( "nextdl %d", clc.downloadBlock ) ); clc.downloadBlock++; clc.downloadCount += size; // So UI gets access to it Cvar_SetValue( "cl_downloadCount", clc.downloadCount ); if ( !size ) { // A zero length block means EOF if ( clc.download ) { FS_FCloseFile( clc.download ); clc.download = 0; // rename the file FS_SV_Rename( cls.downloadTempName, cls.downloadName ); } *cls.downloadTempName = *cls.downloadName = 0; Cvar_Set( "cl_downloadName", "" ); // send intentions now // We need this because without it, we would hold the last nextdl and then start // loading right away. If we take a while to load, the server is happily trying // to send us that last block over and over. // Write it twice to help make sure we acknowledge the download CL_WritePacket(); CL_WritePacket(); // get another file if needed CL_NextDownload(); } }
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 *cdpath; char *basepath; char *homepath; char *pwdpath; char *gamedir; char *fn; const char* err = NULL; *fqpath = 0; // bk001206 - let's have some paranoia assert( name ); #ifdef _PANDORA_ snprintf (fname, sizeof(fname), "%s.so", name); #else snprintf (fname, sizeof(fname), "%s." SHLIB_SUFFIX, name); #endif // bk001129 - was RTLD_LAZY #define Q_RTLD RTLD_NOW pwdpath = Sys_Cwd(); cdpath = Cvar_VariableString( "fs_cdpath" ); basepath = Cvar_VariableString( "fs_basepath" ); homepath = Cvar_VariableString( "fs_homepath" ); gamedir = Cvar_VariableString( "fs_game" ); // pwdpath fn = FS_BuildOSPath( pwdpath, gamedir, fname ); Com_Printf( "Loading '%s'.\n", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { Com_DPrintf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", fn, dlerror() ); // fs_cdpath fn = FS_BuildOSPath( cdpath, gamedir, fname ); Com_Printf( "Loading '%s'.\n", fn ); libHandle = dlopen( fn, Q_RTLD); if ( !libHandle ) { Com_DPrintf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", fn, dlerror() ); // fs_homepath fn = FS_BuildOSPath( homepath, gamedir, fname ); Com_Printf( "Loading '%s'.\n", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { Com_DPrintf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", fn, dlerror() ); // fs_basepath fn = FS_BuildOSPath( basepath, gamedir, fname ); Com_Printf( "Loading '%s'.\n", fn ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { #ifndef NDEBUG // bk001206 - 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_DPrintf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); } else Com_DPrintf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); } else Com_DPrintf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); } else Com_DPrintf ( "Sys_LoadDll(%s): succeeded ...\n", fn); dllEntry = dlsym( libHandle, "dllEntry" ); *entryPoint = dlsym( libHandle, "vmMain" ); if ( !*entryPoint || !dllEntry ) { err = dlerror(); #ifndef NDEBUG // bk001206 - 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_DPrintf ( "Sys_LoadDll(%s) found **vmMain** at %p \n", name, *entryPoint ); // bk001212 dllEntry( systemcalls ); Com_DPrintf ( "Sys_LoadDll(%s) succeeded!\n", name ); if ( libHandle ) Q_strncpyz ( fqpath , fn , MAX_QPATH ) ; // added 7/20/02 by T.Ray return libHandle; }
/* ================ FS_Startup ================ */ void FS_Startup( const char *gameName ) { Com_Printf( "----- FS_Startup -----\n" ); fs_openorder = Cvar_Get( "fs_openorder", "0", 0 ); fs_debug = Cvar_Get( "fs_debug", "0", 0 ); fs_copyfiles = Cvar_Get( "fs_copyfiles", "0", CVAR_INIT ); fs_cdpath = Cvar_Get ("fs_cdpath", Sys_DefaultCDPath(), CVAR_INIT ); fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultBasePath(), CVAR_INIT ); fs_gamedirvar = Cvar_Get ("fs_game", "base", CVAR_INIT|CVAR_SERVERINFO ); fs_restrict = Cvar_Get ("fs_restrict", "", CVAR_INIT ); gi_handles = new gi_handleTable[MAX_FILE_HANDLES]; for (int f = 0; f < MAX_FILE_HANDLES; ++f) { fsh[f].used = false; gi_handles[f].used = false; } zi_stackBase = (char*)Z_Malloc(ZI_STACKSIZE, TAG_FILESYS, qfalse); GOBMemoryFuncSet mem; mem.alloc = gi_alloc; mem.free = gi_free; GOBFileSysFuncSet file; file.close = gi_close; file.open = gi_open; file.read = gi_read; file.seek = gi_seek; file.write = NULL; GOBCacheFileFuncSet cache; cache.close = cache_close; cache.open = cache_open; cache.read = cache_read; cache.seek = cache_seek; cache.write = cache_write; GOBCodecFuncSet codec = { 2, // codecs { { // Codec 0 - zlib 'z', GOB_INFINITE_RATIO, // tag, ratio (ratio is meaningless for decomp) NULL, gi_decompress_zlib, }, { // Codec 1 - null '0', GOB_INFINITE_RATIO, // tag, ratio (ratio is meaningless for decomp) NULL, gi_decompress_null, }, } }; if ( #ifdef _XBOX GOBInit(&mem, &file, &codec, &cache) #else GOBInit(&mem, &file, &codec, NULL) #endif != GOBERR_OK) { Com_Error( ERR_FATAL, "Could not initialize GOB" ); } #ifdef CUSTOM_MP_GOBS char* archive = FS_BuildOSPath( "assets_mp" ); #else char* archive = FS_BuildOSPath( "assets" ); #endif if (GOBArchiveOpen(archive, GOBACCESS_READ, GOB_FALSE, GOB_TRUE) != GOBERR_OK) { #if defined(FINAL_BUILD) extern void ERR_DiscFail(bool); ERR_DiscFail(false); #else //Com_Error( ERR_FATAL, "Could not initialize GOB" ); Cvar_Set("fs_openorder", "1"); #endif } GOBSetCacheSize(1); GOBSetReadBufferSize(32 * 1024); #ifdef GOB_PROFILE GOBProfileFuncSet profile = { gi_profileread }; GOBSetProfileFuncs(&profile); GOBStartProfile(); #endif Com_Printf( "----------------------\n" ); }
void *Sys_LoadDll(const char *name, char *fqpath, int (**entryPoint)(int, ...), int (*systemcalls)(int, ...)) { image_id libHandle = -1; void (*dllEntry)( int (*syscallptr)(int, ...) ); char curpath[MAX_OSPATH]; char fname[MAX_OSPATH]; char *basepath; char *homepath; char *pwdpath; char *gamedir; char *fn; const char* err = NULL; *fqpath = 0; // bk001206 - let's have some paranoia assert(name); getcwd(curpath, sizeof(curpath)); snprintf (fname, sizeof(fname), "%si386.so", name); // bk001129 - was RTLD_LAZY #define Q_RTLD RTLD_NOW pwdpath = Sys_Cwd(); basepath = Cvar_VariableString( "fs_basepath" ); homepath = Cvar_VariableString( "fs_homepath" ); gamedir = Cvar_VariableString( "fs_game" ); //pwdpath fn = FS_BuildOSPath( pwdpath, gamedir, fname ); Com_Printf( "Sys_LoadDll(%s)... \n", fn ); //libHandle = dlopen( fn, Q_RTLD ); libHandle = load_add_on(fn); if (/*!libHandle*/libHandle < 0) { Com_Printf("Sys_LoadDll(%s) failed:\n", fn /*dlerror()*/); // fs_homepath fn = FS_BuildOSPath( homepath, gamedir, fname ); Com_Printf( "Sys_LoadDll(%s)... \n", fn ); //libHandle = dlopen( fn, Q_RTLD ); libHandle = load_add_on(fn); if (/*!libHandle*/libHandle < 0) { Com_Printf("Sys_LoadDll(%s) failed:\n", fn /*dlerror()*/); // fs_basepath fn = FS_BuildOSPath( basepath, gamedir, fname ); Com_Printf("Sys_LoadDll(%s)... \n", fn); //libHandle = dlopen( fn, Q_RTLD ); libHandle = load_add_on(fn); if (/*!libHandle*/libHandle < 0) { #ifndef NDEBUG // bk001206 - 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 ( "Sys_LoadDll(%s): succeeded ...\n", fn ); } else Com_Printf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); } else Com_Printf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); get_image_symbol(libHandle, "dllEntry", B_SYMBOL_TYPE_TEXT, (void**)&dllEntry); get_image_symbol(libHandle, "vmMain", B_SYMBOL_TYPE_TEXT, (void**)entryPoint); if (!*entryPoint || !dllEntry) { //jens err = dlerror(); #ifndef NDEBUG // bk001206 - 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); unload_add_on(libHandle); //jenserr = 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); // bk001212 dllEntry(systemcalls); Com_Printf("Sys_LoadDll(%s) succeeded!\n", name ); if (libHandle) Q_strncpyz(fqpath, fn, MAX_QPATH); // added 7/20/02 by T.Ray return (void*)libHandle; }
/* =========== FS_SV_FOpenFileRead =========== */ int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp ) { char *ospath; fileHandle_t f = 0; if ( !fs_searchpaths ) { Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" ); } f = FS_HandleForFile(); fsh[f].zipFile = qfalse; Q_strncpyz( fsh[f].name, filename, sizeof( fsh[f].name ) ); // don't let sound stutter S_ClearSoundBuffer(); ospath = FS_BuildOSPath( fs_homepath->string, filename, "" ); // remove trailing slash ospath[strlen(ospath)-1] = '\0'; if ( fs_debug->integer ) { Com_Printf( "FS_SV_FOpenFileRead: %s\n", ospath ); } fsh[f].handleFiles.file.o = fopen( ospath, "rb" ); fsh[f].handleSync = qfalse; if (!fsh[f].handleFiles.file.o) { // NOTE TTimo on non *nix systems, fs_homepath == fs_basepath, might want to avoid if (Q_stricmp(fs_homepath->string,fs_basepath->string)) { // search basepath ospath = FS_BuildOSPath( fs_basepath->string, filename, "" ); ospath[strlen(ospath)-1] = '\0'; if ( fs_debug->integer ) { Com_Printf( "FS_SV_FOpenFileRead (fs_basepath): %s\n", ospath ); } fsh[f].handleFiles.file.o = fopen( ospath, "rb" ); fsh[f].handleSync = qfalse; if ( !fsh[f].handleFiles.file.o ) { f = 0; } } } if (!fsh[f].handleFiles.file.o) { // search cd path ospath = FS_BuildOSPath( fs_cdpath->string, filename, "" ); ospath[strlen(ospath)-1] = '\0'; if (fs_debug->integer) { Com_Printf( "FS_SV_FOpenFileRead (fs_cdpath) : %s\n", ospath ); } fsh[f].handleFiles.file.o = fopen( ospath, "rb" ); fsh[f].handleSync = qfalse; if( !fsh[f].handleFiles.file.o ) { f = 0; } } *fp = f; if (f) { return FS_filelength(f); } return 0; }
void *Sys_LoadDll( const char *name, int (**entryPoint)(int, ...), int (*systemcalls)(int, ...) ) { void *libHandle; void (*dllEntry)( int (*syscallptr)(int, ...) ); char curpath[MAX_OSPATH]; char fname[MAX_OSPATH]; //char loadname[MAX_OSPATH]; char *basepath; char *cdpath; char *gamedir; char *fn; const char* err = NULL; // bk001206 // rb0101023 - now const // bk001206 - let's have some paranoia assert( name ); getcwd(curpath, sizeof(curpath)); #if defined __i386__ #ifndef NDEBUG snprintf (fname, sizeof(fname), "%sx86-debug.so", name); // bk010205 - different DLL name #else snprintf (fname, sizeof(fname), "%sx86.so", name); #endif #elif defined(__amd64__) || defined(__x86_64__) snprintf (fname, sizeof(fname), "%samd64.so", name); #elif defined __powerpc__ //rcg010207 - PPC support. snprintf (fname, sizeof(fname), "%sppc.so", name); #elif defined __axp__ snprintf (fname, sizeof(fname), "%saxp.so", name); #elif defined __mips__ snprintf (fname, sizeof(fname), "%smips.so", name); #else #error Unknown arch #endif // bk001129 - was RTLD_LAZY #define Q_RTLD RTLD_NOW #if 0 // bk010205 - was NDEBUG // bk001129 - FIXME: what is this good for? // bk001206 - do not have different behavior in builds Q_strncpyz(loadname, curpath, sizeof(loadname)); // bk001129 - from cvs1.17 (mkv) Q_strcat(loadname, sizeof(loadname), "/"); Q_strcat(loadname, sizeof(loadname), fname); Com_Printf( "Sys_LoadDll(%s)... \n", loadname ); libHandle = dlopen( loadname, Q_RTLD ); //if ( !libHandle ) { // bk001206 - report any problem //Com_Printf( "Sys_LoadDll(%s) failed: \"%s\"\n", loadname, dlerror() ); #endif // bk010205 - do not load from installdir basepath = Cvar_VariableString( "fs_basepath" ); cdpath = Cvar_VariableString( "fs_cdpath" ); gamedir = Cvar_VariableString( "fs_game" ); fn = FS_BuildOSPath( basepath, gamedir, fname ); // bk001206 - verbose Com_Printf( "Sys_LoadDll(%s)... \n", fn ); // bk001129 - from cvs1.17 (mkv), was fname not fn libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { if( cdpath[0] ) { // bk001206 - report any problem Com_Printf( "Sys_LoadDll(%s) failed: \"%s\"\n", fn, dlerror() ); fn = FS_BuildOSPath( cdpath, gamedir, fname ); libHandle = dlopen( fn, Q_RTLD ); if ( !libHandle ) { // bk001206 - report any problem Com_Printf( "Sys_LoadDll(%s) failed: \"%s\"\n", fn, dlerror() ); } else Com_Printf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); } else Com_Printf ( "Sys_LoadDll(%s): succeeded ...\n", fn ); if ( !libHandle ) { #ifdef NDEBUG // bk001206 - 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; } } // bk001206 - no different behavior //#ifndef NDEBUG } //else Com_Printf ( "Sys_LoadDll(%s): succeeded ...\n", loadname ); //#endif dllEntry = (void (*)(int (*)(int,...))) dlsym( libHandle, "dllEntry" ); *entryPoint = (int(*)(int,...))dlsym( libHandle, "vmMain" ); if ( !*entryPoint || !dllEntry ) { err = dlerror(); #ifdef NDEBUG // bk001206 - in debug abort on failure Com_Error ( ERR_FATAL, "Sys_LoadDll(%s) failed dlsym(vmMain): \"%s\" !\n", name, err ); #else Com_Printf ( "Sys_LoadDll(%s) failed dlsym(vmMain): \"%s\" !\n", name, err ); #endif dlclose( libHandle ); err = dlerror(); if ( err != NULL ) Com_Printf ( "Sys_LoadDll(%s) failed dlcose: \"%s\"\n", name, err ); return NULL; } Com_Printf ( "Sys_LoadDll(%s) found **vmMain** at %p \n", name, *entryPoint ); // bk001212 dllEntry( systemcalls ); Com_Printf ( "Sys_LoadDll(%s) succeeded!\n", name ); return libHandle; }
void *Sys_GetGameAPI (void *parms) { void *(*GetGameAPI) (void *); const char *basepath; const char *cdpath; const char *gamedir; const char *homepath; #ifdef MACOS_X const char *apppath; #endif const char *fn; #ifdef JK2_MODE const char *gamename = "jospgame" ARCH_STRING DLL_EXT; #else const char *gamename = "jagame" ARCH_STRING DLL_EXT; #endif if (game_library) Com_Error (ERR_FATAL, "Sys_GetGameAPI without calling Sys_UnloadGame"); // check the current debug directory first for development purposes homepath = Cvar_VariableString( "fs_homepath" ); basepath = Cvar_VariableString( "fs_basepath" ); cdpath = Cvar_VariableString( "fs_cdpath" ); gamedir = Cvar_VariableString( "fs_game" ); #ifdef MACOS_X apppath = Cvar_VariableString( "fs_apppath" ); #endif fn = FS_BuildOSPath( basepath, gamedir, gamename ); game_library = Sys_LoadLibrary( fn ); //First try in mod directories. basepath -> homepath -> cdpath if (!game_library) { if (homepath[0]) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); fn = FS_BuildOSPath( homepath, gamedir, gamename); game_library = Sys_LoadLibrary( fn ); } } #ifdef MACOS_X if (!game_library) { if( apppath[0] ) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); fn = FS_BuildOSPath( apppath, gamedir, gamename ); game_library = Sys_LoadLibrary( fn ); } } #endif if (!game_library) { if( cdpath[0] ) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); fn = FS_BuildOSPath( cdpath, gamedir, gamename ); game_library = Sys_LoadLibrary( fn ); } } //Now try in base. basepath -> homepath -> cdpath if (!game_library) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); fn = FS_BuildOSPath( basepath, BASEGAME, gamename); game_library = Sys_LoadLibrary( fn ); } if (!game_library) { if ( homepath[0] ) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); fn = FS_BuildOSPath( homepath, BASEGAME, gamename); game_library = Sys_LoadLibrary( fn ); } } #ifdef MACOS_X if (!game_library) { if( apppath[0] ) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); fn = FS_BuildOSPath( apppath, BASEGAME, gamename ); game_library = Sys_LoadLibrary( fn ); } } #endif if (!game_library) { if( cdpath[0] ) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); fn = FS_BuildOSPath( cdpath, BASEGAME, gamename ); game_library = Sys_LoadLibrary( fn ); } } //Still couldn't find it. if (!game_library) { Com_Printf( "Sys_GetGameAPI(%s) failed: \"%s\"\n", fn, Sys_LibraryError() ); Com_Error( ERR_FATAL, "Couldn't load game" ); } Com_Printf ( "Sys_GetGameAPI(%s): succeeded ...\n", fn ); GetGameAPI = (void *(*)(void *))Sys_LoadFunction (game_library, "GetGameAPI"); if (!GetGameAPI) { Sys_UnloadGame (); return NULL; } return GetGameAPI (parms); }
static HINSTANCE Sys_RetrieveDLL( const char *gamename ) { char *basepath = Cvar_VariableString( "fs_basepath" ); char *homepath = Cvar_VariableString( "fs_homepath" ); char *cdpath = Cvar_VariableString( "fs_cdpath" ); char *gamedir = Cvar_VariableString( "fs_game" ); // Try basepath/fs_game char *fn = FS_BuildOSPath( basepath, gamedir, gamename ); HINSTANCE retVal = LoadLibrary( fn ); if(retVal) goto successful; if( homepath[0] ) { // Try homepath/fs_game fn = FS_BuildOSPath( homepath, gamedir, gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; } if( cdpath[0] ) { // Try cdpath/fs_game fn = FS_BuildOSPath( cdpath, gamedir, gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; } // Try base folder if mod is loaded but not found if (gamedir[0] ) { // Try basepath/base fn = FS_BuildOSPath( basepath, "base", gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; if( homepath[0] ) { // Try homepath/base fn = FS_BuildOSPath( homepath, "base", gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; } if( cdpath[0] ) { // Try cdpath/fs_game fn = FS_BuildOSPath( cdpath, "base", gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; } } // Try basepath fn = va( "%s/%s", basepath, gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; if( homepath[0] ) { // Try homepath fn = va( "%s/%s", homepath, gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; } if( cdpath[0] ) { // Try cdpath/fs_game fn = va( "%s/%s", cdpath, gamename ); retVal = LoadLibrary( fn ); if(retVal) goto successful; } #ifdef _DEBUG // Try exepath (cwd) fn = NULL; retVal = LoadLibrary( gamename ); if(retVal) goto successful; #endif successful: Com_DPrintf("LoadLibrary (%s)\n", fn?fn:gamename); return retVal; }