From e8f23ad0232786a2add6e2538d61a919e33619e0 Mon Sep 17 00:00:00 2001 From: taaaki Date: Tue, 26 Mar 2013 03:58:38 +0000 Subject: [PATCH] Added timestamp check when determining whether to use the existing game dll/so in the executable path or the dll/so in the game pak file. Refer to issue #3224. git-svn-id: https://svn.thedarkmod.com/svn/darkmod_src/trunk@5723 49c82d7f-2e2a-0410-a16f-ae8f201b507f --- TypeInfo/main.cpp | 3 +- framework/File.cpp | 3 +- framework/File.h | 1 + framework/FileSystem.cpp | 89 ++++++++++++++++++++++++---------------- sys/posix/posix_main.cpp | 37 +++++++++++++++++ sys/sys_public.h | 3 +- sys/win32/win_main.cpp | 37 +++++++++++++++++ 7 files changed, 135 insertions(+), 38 deletions(-) diff --git a/TypeInfo/main.cpp b/TypeInfo/main.cpp index 3835c1813..bbb6479f9 100644 --- a/TypeInfo/main.cpp +++ b/TypeInfo/main.cpp @@ -96,7 +96,8 @@ idCommon * common = &commonLocal; */ void Sys_Mkdir( const char *path ) {} -ID_TIME_T Sys_FileTimeStamp( FILE *fp ) { return 0; } +ID_TIME_T Sys_FileTimeStamp( FILE *fp ) { return 0; } +ID_TIME_T Sys_DosToUnixTime( unsigned long dostime ) { return 0; } #ifdef _WIN32 diff --git a/framework/File.cpp b/framework/File.cpp index a72eb0d34..3606b4ab4 100644 --- a/framework/File.cpp +++ b/framework/File.cpp @@ -1260,6 +1260,7 @@ idFile_InZip::idFile_InZip( void ) { name = "invalid"; zipFilePos = 0; fileSize = 0; + fileLastMod = 0; memset( &z, 0, sizeof( z ) ); } @@ -1339,7 +1340,7 @@ idFile_InZip::Timestamp ================ */ ID_TIME_T idFile_InZip::Timestamp( void ) { - return 0; + return fileLastMod; } /* diff --git a/framework/File.h b/framework/File.h index 26b12fd5f..4efcfecca 100644 --- a/framework/File.h +++ b/framework/File.h @@ -232,6 +232,7 @@ class idFile_InZip : public idFile { idStr fullPath; // full file path including pak file name int zipFilePos; // zip file info position in pak int fileSize; // size of the file + ID_TIME_T fileLastMod; // last modified date/time of the file void * z; // unzip info }; diff --git a/framework/FileSystem.cpp b/framework/FileSystem.cpp index a68c07eb9..910c1ca8a 100644 --- a/framework/FileSystem.cpp +++ b/framework/FileSystem.cpp @@ -2580,6 +2580,7 @@ idFile_InZip * idFileSystemLocal::ReadFileFromZip( pack_t *pak, fileInPack_t *pa unzOpenCurrentFile( file->z ); file->zipFilePos = pakFile->pos; file->fileSize = zfi->cur_file_info.uncompressed_size; + file->fileLastMod = Sys_DosToUnixTime(zfi->cur_file_info.dosDate); } return file; @@ -3298,6 +3299,7 @@ idFileSystemLocal::FindDLL */ void idFileSystemLocal::FindDLL( const char *name, char _dllPath[ MAX_OSPATH ], bool updateChecksum ) { idFile *dllFile = NULL; + idFile *dllFileInPak = NULL; char dllName[MAX_OSPATH]; idStr dllPath; int dllHash; @@ -3315,49 +3317,66 @@ void idFileSystemLocal::FindDLL( const char *name, char _dllPath[ MAX_OSPATH ], dllPath.AppendPath( dllName ); dllFile = OpenExplicitFileRead( dllPath ); + if ( !serverPaks.Num() ) { + // try to find dll in a pak file + dllFileInPak = OpenFileReadFlags( dllName, FSFLAG_SEARCH_PAKS | FSFLAG_BINARY_ONLY, &inPak ); + } + if ( dllFile ) { common->Printf( "Found DLL in EXE path: %s\n", dllFile->GetFullPath() ); - } else { - // DLL not found in alongside executable - if ( !serverPaks.Num() ) { - // try to extract from a pak file first - dllFile = OpenFileReadFlags( dllName, FSFLAG_SEARCH_PAKS | FSFLAG_BINARY_ONLY, &inPak ); - - if (dllFile) { - common->Printf( "found DLL in pak file: %s, extracting to darkmod path\n", dllFile->GetFullPath() ); - - dllPath = ModPath(); - dllPath.Append(dllName); - - //dllPath = RelativePathToOSPath( dllName, "fs_savepath" ); - CopyFile( dllFile, dllPath ); - - CloseFile( dllFile ); - - dllFile = OpenFileReadFlags( dllName, FSFLAG_SEARCH_DIRS ); + } + + if ( dllFileInPak ) { + common->Printf( "Found DLL in pak file: %s\n", dllFileInPak->GetFullPath() ); + } - if ( !dllFile ) { - common->Error( "DLL extraction to darkmod path failed\n" ); - } else if ( updateChecksum ) { + if ( dllFile && (dllFileInPak == NULL || (dllFileInPak && dllFile->Timestamp() >= dllFileInPak->Timestamp())) ) { + common->Printf( "DLL in EXE path is newer, ignoring DLL in pak file\n" ); + if ( dllFileInPak ) { + CloseFile( dllFileInPak ); + dllFileInPak = NULL; + } + } else { + if ( dllFileInPak ) { + common->Printf( "DLL in pak file is newer, extracting to darkmod path\n", dllFileInPak->GetFullPath() ); + + if ( dllFile ) { + CloseFile( dllFile ); + dllFile = NULL; + } + + dllPath = ModPath(); + dllPath.Append(dllName); + + //dllPath = RelativePathToOSPath( dllName, "fs_savepath" ); + CopyFile( dllFileInPak, dllPath ); + + CloseFile( dllFileInPak ); + + dllFile = OpenFileReadFlags( dllName, FSFLAG_SEARCH_DIRS ); + + if ( !dllFile ) { + common->Error( "DLL extraction to darkmod path failed\n" ); + } else if ( updateChecksum ) { + gameDLLChecksum = GetFileChecksum( dllFile ); + gamePakChecksum = inPak->checksum; + updateChecksum = false; // don't try again below + } + } else { + // didn't find a source in a pak file, try in the directory + dllFile = OpenFileReadFlags( dllName, FSFLAG_SEARCH_DIRS ); + if ( dllFile ) { + if ( updateChecksum ) { gameDLLChecksum = GetFileChecksum( dllFile ); - gamePakChecksum = inPak->checksum; - updateChecksum = false; // don't try again below - } - } else { - // didn't find a source in a pak file, try in the directory - dllFile = OpenFileReadFlags( dllName, FSFLAG_SEARCH_DIRS ); - if ( dllFile ) { - if ( updateChecksum ) { - gameDLLChecksum = GetFileChecksum( dllFile ); - // see if we can mark a pak file - pak = FindPakForFileChecksum( dllName, gameDLLChecksum, false ); - pak ? gamePakChecksum = pak->checksum : gamePakChecksum = 0; - updateChecksum = false; - } + // see if we can mark a pak file + pak = FindPakForFileChecksum( dllName, gameDLLChecksum, false ); + pak ? gamePakChecksum = pak->checksum : gamePakChecksum = 0; + updateChecksum = false; } } } } + if ( updateChecksum ) { if ( dllFile ) { gameDLLChecksum = GetFileChecksum( dllFile ); diff --git a/sys/posix/posix_main.cpp b/sys/posix/posix_main.cpp index 6adb30bdc..146de454f 100644 --- a/sys/posix/posix_main.cpp +++ b/sys/posix/posix_main.cpp @@ -411,6 +411,43 @@ long Sys_FileTimeStamp(FILE * fp) { return st.st_mtime; } +/* +================= +Sys_DosToUnixTime +================= +*/ +long Sys_DosToUnixTime( unsigned long dostime ) { + ID_TIME_T unix_time = 0; + unsigned int sec, min, hour, day, mon, year; + struct tm dostm; + + // break dos time down into its sec, min, hour components + sec = (dostime & 0x1F) * 2; + min = (dostime & 0x7E0) >> 5; + hour = (dostime & 0xF800) >> 11; + + // temporarily remove time component + year = dostime >> 16; + + // break dos date down into its day, month, year components + day = year & 0x1F; + mon = (year & 0x1E0) >> 5; + year = (year >> 9) + 1980; + + if (sec <= 60 && min <= 59 && hour <= 23 && day >= 1 && day <= 31 && mon >= 1 && mon <= 12 && year <= 2107) { + dostm.tm_sec = sec; + dostm.tm_min = min; + dostm.tm_hour = hour; + dostm.tm_mday = day; + dostm.tm_mon = mon - 1; + dostm.tm_year = year - 1900; + + unix_time = mktime(&dostm); + } + + return (long) unix_time; +} + void Sys_Sleep(int msec) { if ( msec < 20 ) { static int last = 0; diff --git a/sys/sys_public.h b/sys/sys_public.h index d3119f862..d9f0882c8 100644 --- a/sys/sys_public.h +++ b/sys/sys_public.h @@ -344,7 +344,8 @@ void Sys_ShowConsole( int visLevel, bool quitOnClose ); void Sys_Mkdir( const char *path ); -ID_TIME_T Sys_FileTimeStamp( FILE *fp ); +ID_TIME_T Sys_FileTimeStamp( FILE *fp ); +ID_TIME_T Sys_DosToUnixTime( unsigned long dostime ); // NOTE: do we need to guarantee the same output on all platforms? const char * Sys_TimeStampToStr( ID_TIME_T timeStamp ); const char * Sys_DefaultCDPath( void ); diff --git a/sys/win32/win_main.cpp b/sys/win32/win_main.cpp index b1b8cdb09..4aeb7a305 100644 --- a/sys/win32/win_main.cpp +++ b/sys/win32/win_main.cpp @@ -468,6 +468,43 @@ ID_TIME_T Sys_FileTimeStamp( FILE *fp ) { return (long) st.st_mtime; } +/* +================= +Sys_DosToUnixTime +================= +*/ +ID_TIME_T Sys_DosToUnixTime( unsigned long dostime ) { + ID_TIME_T unix_time = 0; + unsigned int sec, min, hour, day, mon, year; + struct tm dostm; + + // break dos time down into its sec, min, hour components + sec = (dostime & 0x1F) * 2; + min = (dostime & 0x7E0) >> 5; + hour = (dostime & 0xF800) >> 11; + + // temporarily remove time component + year = dostime >> 16; + + // break dos date down into its day, month, year components + day = year & 0x1F; + mon = (year & 0x1E0) >> 5; + year = (year >> 9) + 1980; + + if (sec <= 60 && min <= 59 && hour <= 23 && day >= 1 && day <= 31 && mon >= 1 && mon <= 12 && year <= 2107) { + dostm.tm_sec = sec; + dostm.tm_min = min; + dostm.tm_hour = hour; + dostm.tm_mday = day; + dostm.tm_mon = mon - 1; + dostm.tm_year = year - 1900; + + unix_time = mktime(&dostm); + } + + return (long) unix_time; +} + /* ============== Sys_Cwd