Allow VM_Restart to load unpure qagame.qvm so that local server won't crash after map_restart if server operator has qagame.qvm residing outside pak file (#5196)

Thanks to "rg3" for providing a shell account
This commit is contained in:
Thilo Schulz 2011-09-27 22:16:07 +00:00
parent d176ebe84a
commit 7eba074ce4
4 changed files with 27 additions and 21 deletions

View file

@ -1081,7 +1081,7 @@ Returns filesize and an open FILE pointer.
*/ */
extern qboolean com_fullyInitialized; extern qboolean com_fullyInitialized;
long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_t *file, qboolean uniqueFILE) long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_t *file, qboolean uniqueFILE, qboolean unpure)
{ {
long hash; long hash;
pack_t *pak; pack_t *pak;
@ -1190,7 +1190,7 @@ long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_
if(search->pack->hashTable[hash]) if(search->pack->hashTable[hash])
{ {
// disregard if it doesn't match one of the allowed pure pak files // disregard if it doesn't match one of the allowed pure pak files
if(!FS_PakIsPure(search->pack)) if(!unpure && !FS_PakIsPure(search->pack))
{ {
*file = 0; *file = 0;
return -1; return -1;
@ -1281,7 +1281,7 @@ long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_
// this test can make the search fail although the file is in the directory // this test can make the search fail although the file is in the directory
// I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8 // I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
// turned out I used FS_FileExists instead // turned out I used FS_FileExists instead
if(fs_numServerPaks) if(!unpure && fs_numServerPaks)
{ {
if(!FS_IsExt(filename, ".cfg", len) && // for config files if(!FS_IsExt(filename, ".cfg", len) && // for config files
!FS_IsExt(filename, ".menu", len) && // menu files !FS_IsExt(filename, ".menu", len) && // menu files
@ -1341,7 +1341,7 @@ long FS_FOpenFileRead(const char *filename, fileHandle_t *file, qboolean uniqueF
for(search = fs_searchpaths; search; search = search->next) for(search = fs_searchpaths; search; search = search->next)
{ {
len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE); len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE, qfalse);
if(file == NULL) if(file == NULL)
{ {
@ -1425,7 +1425,7 @@ vmInterpret_t FS_FindVM(void **startSearch, char *found, int foundlen, const cha
} }
} }
if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse) > 0) if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse, qfalse) > 0)
{ {
*startSearch = search; *startSearch = search;
return VMI_COMPILED; return VMI_COMPILED;
@ -1447,7 +1447,7 @@ vmInterpret_t FS_FindVM(void **startSearch, char *found, int foundlen, const cha
} }
} }
if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse) > 0) if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse, qfalse) > 0)
{ {
*startSearch = search; *startSearch = search;
@ -1752,7 +1752,7 @@ a null buffer will just return the file length without loading
If searchPath is non-NULL search only in that specific search path If searchPath is non-NULL search only in that specific search path
============ ============
*/ */
long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer) long FS_ReadFileDir(const char *qpath, void *searchPath, qboolean unpure, void **buffer)
{ {
fileHandle_t h; fileHandle_t h;
searchpath_t *search; searchpath_t *search;
@ -1825,7 +1825,7 @@ long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer)
else else
{ {
// look for it in a specific search path only // look for it in a specific search path only
len = FS_FOpenFileReadDir(qpath, search, &h, qfalse); len = FS_FOpenFileReadDir(qpath, search, &h, qfalse, unpure);
} }
if ( h == 0 ) { if ( h == 0 ) {
@ -1884,7 +1884,7 @@ a null buffer will just return the file length without loading
*/ */
long FS_ReadFile(const char *qpath, void **buffer) long FS_ReadFile(const char *qpath, void **buffer)
{ {
return FS_ReadFileDir(qpath, NULL, buffer); return FS_ReadFileDir(qpath, NULL, qfalse, buffer);
} }
/* /*
@ -2751,7 +2751,7 @@ qboolean FS_Which(const char *filename, void *searchPath)
{ {
searchpath_t *search = searchPath; searchpath_t *search = searchPath;
if(FS_FOpenFileReadDir(filename, search, NULL, qfalse) > 0) if(FS_FOpenFileReadDir(filename, search, NULL, qfalse, qfalse) > 0)
{ {
if(search->pack) if(search->pack)
{ {

View file

@ -363,7 +363,7 @@ void VM_Free( vm_t *vm );
void VM_Clear(void); void VM_Clear(void);
void VM_Forced_Unload_Start(void); void VM_Forced_Unload_Start(void);
void VM_Forced_Unload_Done(void); void VM_Forced_Unload_Done(void);
vm_t *VM_Restart( vm_t *vm ); vm_t *VM_Restart(vm_t *vm, qboolean unpure);
intptr_t QDECL VM_Call( vm_t *vm, int callNum, ... ); intptr_t QDECL VM_Call( vm_t *vm, int callNum, ... );
@ -663,7 +663,7 @@ int FS_Read( void *buffer, int len, fileHandle_t f );
void FS_FCloseFile( fileHandle_t f ); void FS_FCloseFile( fileHandle_t f );
// note: you can't just fclose from another DLL, due to MS libc issues // note: you can't just fclose from another DLL, due to MS libc issues
long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer); long FS_ReadFileDir(const char *qpath, void *searchPath, qboolean unpure, void **buffer);
long FS_ReadFile(const char *qpath, void **buffer); long FS_ReadFile(const char *qpath, void **buffer);
// returns the length of the file // returns the length of the file
// a null buffer will just return the file length without loading // a null buffer will just return the file length without loading

View file

@ -363,7 +363,8 @@ VM_LoadQVM
Load a .qvm file Load a .qvm file
================= =================
*/ */
vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) { vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc, qboolean unpure)
{
int dataLength; int dataLength;
int i; int i;
char filename[MAX_QPATH]; char filename[MAX_QPATH];
@ -376,7 +377,7 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name ); Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
Com_Printf( "Loading vm file %s...\n", filename ); Com_Printf( "Loading vm file %s...\n", filename );
FS_ReadFileDir(filename, vm->searchPath, &header.v); FS_ReadFileDir(filename, vm->searchPath, unpure, &header.v);
if ( !header.h ) { if ( !header.h ) {
Com_Printf( "Failed.\n" ); Com_Printf( "Failed.\n" );
@ -522,9 +523,13 @@ VM_Restart
Reload the data, but leave everything else in place Reload the data, but leave everything else in place
This allows a server to do a map_restart without changing memory allocation This allows a server to do a map_restart without changing memory allocation
We need to make sure that servers can access unpure QVMs (not contained in any pak)
even if the client is pure, so take "unpure" as argument.
================= =================
*/ */
vm_t *VM_Restart( vm_t *vm ) { vm_t *VM_Restart(vm_t *vm, qboolean unpure)
{
vmHeader_t *header; vmHeader_t *header;
// DLL's can't be restarted in place // DLL's can't be restarted in place
@ -542,15 +547,16 @@ vm_t *VM_Restart( vm_t *vm ) {
} }
// load the image // load the image
Com_Printf( "VM_Restart()\n" ); Com_Printf("VM_Restart()\n");
if( !( header = VM_LoadQVM( vm, qfalse ) ) ) { if(!(header = VM_LoadQVM(vm, qfalse, unpure)))
Com_Error( ERR_DROP, "VM_Restart failed" ); {
Com_Error(ERR_DROP, "VM_Restart failed");
return NULL; return NULL;
} }
// free the original file // free the original file
FS_FreeFile( header ); FS_FreeFile(header);
return vm; return vm;
} }
@ -621,7 +627,7 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
else if(retval == VMI_COMPILED) else if(retval == VMI_COMPILED)
{ {
vm->searchPath = startSearch; vm->searchPath = startSearch;
if((header = VM_LoadQVM(vm, qtrue))) if((header = VM_LoadQVM(vm, qtrue, qfalse)))
break; break;
// VM_Free overwrites the name on failed load // VM_Free overwrites the name on failed load

View file

@ -901,7 +901,7 @@ void SV_RestartGameProgs( void ) {
VM_Call( gvm, GAME_SHUTDOWN, qtrue ); VM_Call( gvm, GAME_SHUTDOWN, qtrue );
// do a restart instead of a free // do a restart instead of a free
gvm = VM_Restart( gvm ); gvm = VM_Restart(gvm, qtrue);
if ( !gvm ) { if ( !gvm ) {
Com_Error( ERR_FATAL, "VM_Restart on game failed" ); Com_Error( ERR_FATAL, "VM_Restart on game failed" );
} }