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;
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;
pack_t *pak;
@ -1190,7 +1190,7 @@ long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_
if(search->pack->hashTable[hash])
{
// 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;
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
// I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
// turned out I used FS_FileExists instead
if(fs_numServerPaks)
if(!unpure && fs_numServerPaks)
{
if(!FS_IsExt(filename, ".cfg", len) && // for config 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)
{
len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE);
len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE, qfalse);
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;
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;
@ -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
============
*/
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;
searchpath_t *search;
@ -1825,7 +1825,7 @@ long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer)
else
{
// 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 ) {
@ -1884,7 +1884,7 @@ a null buffer will just return the file length without loading
*/
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;
if(FS_FOpenFileReadDir(filename, search, NULL, qfalse) > 0)
if(FS_FOpenFileReadDir(filename, search, NULL, qfalse, qfalse) > 0)
{
if(search->pack)
{

View file

@ -363,7 +363,7 @@ void VM_Free( vm_t *vm );
void VM_Clear(void);
void VM_Forced_Unload_Start(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, ... );
@ -663,7 +663,7 @@ int FS_Read( void *buffer, int len, fileHandle_t f );
void FS_FCloseFile( fileHandle_t f );
// 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);
// returns the length of the file
// a null buffer will just return the file length without loading

View file

@ -363,7 +363,8 @@ VM_LoadQVM
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 i;
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_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 ) {
Com_Printf( "Failed.\n" );
@ -522,9 +523,13 @@ VM_Restart
Reload the data, but leave everything else in place
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;
// DLL's can't be restarted in place
@ -542,15 +547,16 @@ vm_t *VM_Restart( vm_t *vm ) {
}
// load the image
Com_Printf( "VM_Restart()\n" );
Com_Printf("VM_Restart()\n");
if( !( header = VM_LoadQVM( vm, qfalse ) ) ) {
Com_Error( ERR_DROP, "VM_Restart failed" );
if(!(header = VM_LoadQVM(vm, qfalse, unpure)))
{
Com_Error(ERR_DROP, "VM_Restart failed");
return NULL;
}
// free the original file
FS_FreeFile( header );
FS_FreeFile(header);
return vm;
}
@ -621,7 +627,7 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
else if(retval == VMI_COMPILED)
{
vm->searchPath = startSearch;
if((header = VM_LoadQVM(vm, qtrue)))
if((header = VM_LoadQVM(vm, qtrue, qfalse)))
break;
// VM_Free overwrites the name on failed load

View file

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