From 22b134269873234b2815a536fa77a63cf7b6bede Mon Sep 17 00:00:00 2001 From: danij Date: Fri, 10 Feb 2012 05:12:52 +0000 Subject: [PATCH] Filesys|Fixed: Do not assume a resource is found until it is validated Previously it was possible to use a dummy file with the same name as that of a Package resource required for startup, to coax the engine into thinking the game was playable. Game resource files are now only marked found once they pass validation. --- doomsday/engine/api/dd_share.h | 1 + .../portable/include/abstractresource.h | 9 +++ .../engine/portable/src/abstractresource.c | 18 ++++-- doomsday/engine/portable/src/dd_main.c | 60 ++++++++++++------- doomsday/engine/portable/src/def_main.c | 9 +-- doomsday/engine/portable/src/fs_main.c | 6 +- 6 files changed, 72 insertions(+), 31 deletions(-) diff --git a/doomsday/engine/api/dd_share.h b/doomsday/engine/api/dd_share.h index 615a09d5c4..ec67c57047 100644 --- a/doomsday/engine/api/dd_share.h +++ b/doomsday/engine/api/dd_share.h @@ -385,6 +385,7 @@ typedef struct gameinfo_s { */ ///@{ #define RF_STARTUP 0x1 ///< A required resource needed for and loaded during game start up (can't be a virtual file). +#define RF_FOUND 0x2 ///< Resource has been located. ///@} //------------------------------------------------------------------------ diff --git a/doomsday/engine/portable/include/abstractresource.h b/doomsday/engine/portable/include/abstractresource.h index 7d1b123929..4af890139b 100644 --- a/doomsday/engine/portable/include/abstractresource.h +++ b/doomsday/engine/portable/include/abstractresource.h @@ -67,6 +67,15 @@ void AbstractResource_Print(AbstractResource* resource, boolean printStatus); */ ddstring_t* AbstractResource_NameStringList(AbstractResource* resource); +/** + * Update the "found" status for this resource. + * + * @param resource AbstractResource instance. + * @param yes @c true = mark as found, else mark not-found. + * @return Same as @a resource for caller convenience. + */ +AbstractResource* AbstractResource_MarkAsFound(AbstractResource* r, boolean yes); + /** * Accessor methods. */ diff --git a/doomsday/engine/portable/src/abstractresource.c b/doomsday/engine/portable/src/abstractresource.c index 7b36f36edb..c1eebd8fa4 100644 --- a/doomsday/engine/portable/src/abstractresource.c +++ b/doomsday/engine/portable/src/abstractresource.c @@ -96,7 +96,7 @@ AbstractResource* AbstractResource_NewWithName(resourceclass_t rclass, int flags if(!r) Con_Error("AbstractResource::NewWithName: Failed on allocation of %lu bytes.", (unsigned long) sizeof(*r)); r->rclass = rclass; - r->flags = flags; + r->flags = flags & ~RF_FOUND; r->names = 0; r->namesCount = 0; r->identityKeys = 0; @@ -207,6 +207,7 @@ const ddstring_t* AbstractResource_ResolvedPath(AbstractResource* r, boolean can { r->searchPathUsed = F_FindResourceForRecord(r, &r->foundPath); } + /// @todo Move resource validation here. if(r->searchPathUsed != 0) { return &r->foundPath; @@ -226,6 +227,14 @@ int AbstractResource_ResourceFlags(AbstractResource* r) return r->flags; } +AbstractResource* AbstractResource_MarkAsFound(AbstractResource* r, boolean yes) +{ + assert(r); + if(yes) r->flags |= RF_FOUND; + else r->flags &= ~RF_FOUND; + return r; +} + ddstring_t* const* AbstractResource_IdentityKeys(AbstractResource* r) { assert(r); @@ -235,16 +244,17 @@ ddstring_t* const* AbstractResource_IdentityKeys(AbstractResource* r) void AbstractResource_Print(AbstractResource* r, boolean printStatus) { ddstring_t* searchPaths = AbstractResource_NameStringList(r); + const boolean markedFound = !!(r->flags & RF_FOUND); if(printStatus) - Con_Printf("%s", r->searchPathUsed == 0? " ! ":" "); + Con_Printf("%s", !markedFound? " ! ":" "); Con_PrintPathList4(Str_Text(searchPaths), ';', " or ", PPF_TRANSFORM_PATH_MAKEPRETTY); if(printStatus) { - Con_Printf(" %s%s", r->searchPathUsed == 0? "- missing" : "- found ", - r->searchPathUsed == 0? "" : F_PrettyPath(Str_Text(AbstractResource_ResolvedPath(r, false)))); + Con_Printf(" %s%s", !markedFound? "- missing" : "- found ", + !markedFound? "" : F_PrettyPath(Str_Text(AbstractResource_ResolvedPath(r, false)))); } Con_Printf("\n"); Str_Delete(searchPaths); diff --git a/doomsday/engine/portable/src/dd_main.c b/doomsday/engine/portable/src/dd_main.c index ae9f7ca707..ee1768d08f 100644 --- a/doomsday/engine/portable/src/dd_main.c +++ b/doomsday/engine/portable/src/dd_main.c @@ -484,36 +484,50 @@ void DD_StartTitle(void) static boolean recognizeWAD(const char* filePath, void* data) { lumpnum_t auxLumpBase = F_OpenAuxiliary3(filePath, 0, true); - boolean result; + boolean result = false; - if(auxLumpBase == -1) return false; - - // Ensure all identity lumps are present. - result = true; - if(data) + if(auxLumpBase >= 0) { - const ddstring_t* const* lumpNames = (const ddstring_t* const*) data; - for(; result && *lumpNames; lumpNames++) + // Ensure all identity lumps are present. + if(data) { - lumpnum_t lumpNum = F_CheckLumpNumForName2(Str_Text(*lumpNames), true); - if(lumpNum == -1) + const ddstring_t* const* lumpNames = (const ddstring_t* const*) data; + result = true; + for(; result && *lumpNames; lumpNames++) { - result = false; + lumpnum_t lumpNum = F_CheckLumpNumForName2(Str_Text(*lumpNames), true); + if(lumpNum < 0) + { + result = false; + } } } - } + else + { + // Matched. + result = true; + } - F_CloseAuxiliary(); + F_CloseAuxiliary(); + } return result; } /// @return @c true, iff the resource appears to be what we think it is. static boolean recognizeZIP(const char* filePath, void* data) { - /// \todo dj: write me. - return F_FileExists(filePath); + DFile* dfile = F_Open(filePath, "bf"); + boolean result = false; + if(dfile) + { + result = ZipFile_Recognise(dfile); + /// @todo Check files. We should implement an auxiliary zip lumpdirectory... + F_Close(dfile); + } + return result; } +/// @todo This logic should be encapsulated by AbstractResource. static int validateResource(AbstractResource* rec, void* paramaters) { int validated = false; @@ -533,10 +547,15 @@ static int validateResource(AbstractResource* rec, void* paramaters) validated = true; } break; - default: break; + default: + // Other resource types are not validated. + validated = true; + break; } } + AbstractResource_MarkAsFound(rec, validated); + return validated; } @@ -595,9 +614,9 @@ static boolean allGameResourcesFound(Game* game) for(recordIt = records; *recordIt; recordIt++) { AbstractResource* rec = *recordIt; + const int flags = AbstractResource_ResourceFlags(rec); - if((AbstractResource_ResourceFlags(rec) & RF_STARTUP) && - !AbstractResource_ResolvedPath(rec, false)) + if((flags & RF_STARTUP) && !(flags & RF_FOUND)) return false; } } @@ -769,6 +788,7 @@ static boolean exchangeEntryPoints(pluginid_t pluginId) static void loadResource(AbstractResource* res) { if(!res) return; + switch(AbstractResource_ResourceClass(res)) { case RC_PACKAGE: { @@ -777,8 +797,8 @@ static void loadResource(AbstractResource* res) { F_AddFile(Str_Text(path), 0, false); } - break; - } + break; } + default: Con_Error("loadGameResource: No resource loader found for %s.", F_ResourceClassStr(AbstractResource_ResourceClass(res))); } diff --git a/doomsday/engine/portable/src/def_main.c b/doomsday/engine/portable/src/def_main.c index f70aff4fdb..8b46aa1491 100644 --- a/doomsday/engine/portable/src/def_main.c +++ b/doomsday/engine/portable/src/def_main.c @@ -837,9 +837,9 @@ static void readAllDefinitions(void) for(recordIt = records; *recordIt; recordIt++) { AbstractResource* rec = *recordIt; - const ddstring_t* resolvedPath = AbstractResource_ResolvedPath(rec, true); + const ddstring_t* path; - if(!resolvedPath) + if(!(AbstractResource_ResourceFlags(rec) & RF_FOUND)) { ddstring_t* names = AbstractResource_NameStringList(rec); Con_Error("readAllDefinitions: Error, failed to locate required game definition \"%s\".", Str_Text(names)); @@ -847,9 +847,10 @@ static void readAllDefinitions(void) Str_Delete(names); } - VERBOSE( Con_Message(" Processing '%s'...\n", F_PrettyPath(Str_Text(resolvedPath))) ) + path = AbstractResource_ResolvedPath(rec, true); + VERBOSE( Con_Message(" Processing '%s'...\n", F_PrettyPath(Str_Text(path))) ) - readDefinitionFile(Str_Text(resolvedPath)); + readDefinitionFile(Str_Text(path)); } } diff --git a/doomsday/engine/portable/src/fs_main.c b/doomsday/engine/portable/src/fs_main.c index 2ad3b0719c..3d13c0a5b9 100644 --- a/doomsday/engine/portable/src/fs_main.c +++ b/doomsday/engine/portable/src/fs_main.c @@ -754,7 +754,7 @@ lumpnum_t F_OpenAuxiliary3(const char* path, size_t baseOffset, boolean silent) // We must have an absolute path, so prepend the current working directory if necessary. F_PrependWorkPath(&searchPath, &searchPath); - /// \todo Allow opening WAD/ZIP files from lumps in other containers. + /// @todo Allow opening WAD/ZIP files from lumps in other containers. file = findRealFile(Str_Text(&searchPath), "rb", &foundPath); Str_Free(&searchPath); if(!file) @@ -807,8 +807,8 @@ lumpnum_t F_OpenAuxiliary3(const char* path, size_t baseOffset, boolean silent) Con_Message("Warning:F_OpenAuxiliary: Cannot open a resource with neither a path nor a handle to it.\n"); } - if(foundPath) - Str_Delete(foundPath); + if(foundPath) Str_Delete(foundPath); + DFile_Delete(dfile, true); return -1; }