From e3f85eb559bbdf8251b07964f1f7dda72e8ea04c Mon Sep 17 00:00:00 2001 From: MysterD Date: Sat, 16 Apr 2022 20:29:40 -0700 Subject: [PATCH 1/4] Sanity check mod_cache_save --- src/pc/mods/mod_cache.c | 115 +++++++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 37 deletions(-) diff --git a/src/pc/mods/mod_cache.c b/src/pc/mods/mod_cache.c index 0459066b..f967e6b8 100644 --- a/src/pc/mods/mod_cache.c +++ b/src/pc/mods/mod_cache.c @@ -31,35 +31,90 @@ void mod_cache_shutdown(void) { } } +void mod_cache_md5(const char* inPath, u8* outDataPath) { + char cpath[SYS_MAX_PATH] = { 0 }; + u8 buffer[MD5_BUFFER_SIZE] = { 0 }; + + MD5_CTX ctx = { 0 }; + MD5_Init(&ctx); + + snprintf(cpath, SYS_MAX_PATH-1, "%s", inPath); + normalize_path(cpath); + + // open file pointer + FILE* fp = fopen(cpath, "rb"); + if (fp == NULL) { + LOG_ERROR("Failed to open filepointer for mod hashing: '%s'.", cpath); + return; + } + + // read bytes and md5 them + size_t readBytes = 0; + do { + readBytes = fread(buffer, sizeof(u8), MD5_BUFFER_SIZE, fp); + MD5_Update(&ctx, buffer, readBytes); + } while (readBytes >= MD5_BUFFER_SIZE); + + // close file pointer + fclose(fp); + + // finish computing + MD5_Final(outDataPath, &ctx); +} + +static bool mod_cache_is_valid(struct ModCacheEntry* node) { + u8 dataHash[16]; + mod_cache_md5(node->path, dataHash); + return !memcmp(node->dataHash, dataHash, 16); +} + struct ModCacheEntry* mod_cache_get_from_hash(u8* dataHash) { struct ModCacheEntry* node = sModCacheHead; - char str[128] = { 0 }; - MD5_ToString(dataHash, str); + struct ModCacheEntry* prev = NULL; while (node != NULL) { - MD5_ToString(node->dataHash, str); + struct ModCacheEntry* next = node->next; if (!memcmp(node->dataHash, dataHash, 16)) { - return node; + if (mod_cache_is_valid(node)) { + return node; + } else { + mod_cache_remove_node(node, prev); + } } - node = node->next; + prev = node; + node = next; } return NULL; } struct ModCacheEntry* mod_cache_get_from_path(const char* path) { struct ModCacheEntry* node = sModCacheHead; + struct ModCacheEntry* prev = NULL; while (node != NULL) { + struct ModCacheEntry* next = node->next; if (!strcmp(node->path, path)) { - return node; + if (mod_cache_is_valid(node)) { + return node; + } else { + mod_cache_remove_node(node, prev); + } } - node = node->next; + prev = node; + node = next; } return NULL; } void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) { + // sanity check if (mod_cache_get_from_hash(dataHash)) { return; } + if (path == NULL || strlen(path) == 0) { + return; + } + if (!fs_sys_file_exists(path)) { + return; + } struct ModCacheEntry* node = calloc(1, sizeof(struct ModCacheEntry)); memcpy(node->dataHash, dataHash, 16); @@ -95,38 +150,15 @@ void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) { } } -void mod_cache_md5(const char* inPath, u8* outDataPath) { - char cpath[SYS_MAX_PATH] = { 0 }; - u8 buffer[MD5_BUFFER_SIZE] = { 0 }; - - MD5_CTX ctx = { 0 }; - MD5_Init(&ctx); - - snprintf(cpath, SYS_MAX_PATH-1, "%s", inPath); - normalize_path(cpath); - - // open file pointer - FILE* fp = fopen(cpath, "rb"); - if (fp == NULL) { - LOG_ERROR("Failed to open filepointer for mod hashing: '%s'.", cpath); +void mod_cache_add(struct Mod* mod, struct ModFile* file) { + // sanity check + if (mod == NULL || file == NULL) { + return; + } + if (mod->basePath == NULL || file->relativePath == NULL) { return; } - // read bytes and md5 them - size_t readBytes = 0; - do { - readBytes = fread(buffer, sizeof(u8), MD5_BUFFER_SIZE, fp); - MD5_Update(&ctx, buffer, readBytes); - } while (readBytes >= MD5_BUFFER_SIZE); - - // close file pointer - fclose(fp); - - // finish computing - MD5_Final(outDataPath, &ctx); -} - -void mod_cache_add(struct Mod* mod, struct ModFile* file) { // if we already have a cached path, don't do anything if (file->cachedPath != NULL) { return; @@ -193,6 +225,12 @@ void mod_cache_load(void) { void mod_cache_save(void) { LOG_INFO("Saving mod cache"); const char* filename = fs_get_write_path(MOD_CACHE_FILENAME); + + if (filename == NULL) { + LOG_ERROR("Failed to get filename for mod cache"); + return; + } + FILE* fp = fopen(filename, "wb"); if (fp == NULL) { LOG_ERROR("Failed to open mod cache save fp: %s", filename); @@ -204,9 +242,12 @@ void mod_cache_save(void) { struct ModCacheEntry* node = sModCacheHead; while (node != NULL) { + if (node->path == NULL) { continue; } + u16 pathLen = strlen(node->path); + if (pathLen == 0) { continue; } + fwrite(node->dataHash, sizeof(u8), 16, fp); fwrite(&node->lastLoaded, sizeof(u64), 1, fp); - u16 pathLen = strlen(node->path); fwrite(&pathLen, sizeof(u16), 1, fp); fwrite(node->path, sizeof(u8), pathLen + 1, fp); node = node->next; From d6f38d6cf544ecd739aea98d17ff1b2d3059e075 Mon Sep 17 00:00:00 2001 From: MysterD Date: Sat, 16 Apr 2022 22:46:29 -0700 Subject: [PATCH 2/4] More mod cache fixes --- src/pc/mods/mod_cache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pc/mods/mod_cache.c b/src/pc/mods/mod_cache.c index f967e6b8..4c094f9a 100644 --- a/src/pc/mods/mod_cache.c +++ b/src/pc/mods/mod_cache.c @@ -242,14 +242,15 @@ void mod_cache_save(void) { struct ModCacheEntry* node = sModCacheHead; while (node != NULL) { - if (node->path == NULL) { continue; } + if (node->path == NULL) { goto iterate; } u16 pathLen = strlen(node->path); - if (pathLen == 0) { continue; } + if (pathLen == 0) { goto iterate; } fwrite(node->dataHash, sizeof(u8), 16, fp); fwrite(&node->lastLoaded, sizeof(u64), 1, fp); fwrite(&pathLen, sizeof(u16), 1, fp); fwrite(node->path, sizeof(u8), pathLen + 1, fp); +iterate: node = node->next; } From 069ca46a448d6d2f85d557ff63812da52dc14c2f Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 18 Apr 2022 21:59:42 -0700 Subject: [PATCH 3/4] Even more mod cache fixes --- src/pc/mods/mod.c | 1 + src/pc/mods/mod_cache.c | 53 ++++++++++++++++++++++++++++++++++------ src/pc/mods/mods.c | 4 +-- src/pc/mods/mods_utils.c | 15 ++++++++++++ src/pc/mods/mods_utils.h | 1 + 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/pc/mods/mod.c b/src/pc/mods/mod.c index 168910d7..398f2a77 100644 --- a/src/pc/mods/mod.c +++ b/src/pc/mods/mod.c @@ -123,6 +123,7 @@ void mod_clear(struct Mod* mod) { if (mod->files != NULL) { free(mod->files); + mod->files = NULL; } mod->fileCount = 0; diff --git a/src/pc/mods/mod_cache.c b/src/pc/mods/mod_cache.c index 4c094f9a..edaf40d0 100644 --- a/src/pc/mods/mod_cache.c +++ b/src/pc/mods/mod_cache.c @@ -8,7 +8,7 @@ #include "pc/utils/md5.h" #define MOD_CACHE_FILENAME "mod.cache" -#define MOD_CACHE_VERSION 5 +#define MOD_CACHE_VERSION 6 #define MD5_BUFFER_SIZE 1024 struct ModCacheEntry* sModCacheHead = NULL; @@ -20,6 +20,7 @@ static void mod_cache_remove_node(struct ModCacheEntry* node, struct ModCacheEnt LOG_INFO("Removing node: %s", node->path); if (node->path) { free(node->path); + node->path = NULL; } free(node); } @@ -35,10 +36,20 @@ void mod_cache_md5(const char* inPath, u8* outDataPath) { char cpath[SYS_MAX_PATH] = { 0 }; u8 buffer[MD5_BUFFER_SIZE] = { 0 }; + for (u8 i = 0; i < 16; i++) { + outDataPath[i] = 0; + } + MD5_CTX ctx = { 0 }; MD5_Init(&ctx); snprintf(cpath, SYS_MAX_PATH-1, "%s", inPath); + + if (strlen(cpath) == 0) { + LOG_ERROR("Failed to retrieve path"); + return; + } + normalize_path(cpath); // open file pointer @@ -63,12 +74,16 @@ void mod_cache_md5(const char* inPath, u8* outDataPath) { } static bool mod_cache_is_valid(struct ModCacheEntry* node) { - u8 dataHash[16]; + if (node == NULL || node->path == NULL || strlen(node->path) == 0) { + return; + } + u8 dataHash[16] = { 0 }; mod_cache_md5(node->path, dataHash); return !memcmp(node->dataHash, dataHash, 16); } struct ModCacheEntry* mod_cache_get_from_hash(u8* dataHash) { + if (dataHash == NULL) { return NULL; } struct ModCacheEntry* node = sModCacheHead; struct ModCacheEntry* prev = NULL; while (node != NULL) { @@ -87,6 +102,7 @@ struct ModCacheEntry* mod_cache_get_from_hash(u8* dataHash) { } struct ModCacheEntry* mod_cache_get_from_path(const char* path) { + if (path == NULL || strlen(path) == 0) { return NULL; } struct ModCacheEntry* node = sModCacheHead; struct ModCacheEntry* prev = NULL; while (node != NULL) { @@ -106,18 +122,30 @@ struct ModCacheEntry* mod_cache_get_from_path(const char* path) { void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) { // sanity check - if (mod_cache_get_from_hash(dataHash)) { - return; - } if (path == NULL || strlen(path) == 0) { + LOG_ERROR("Invalid path"); return; } if (!fs_sys_file_exists(path)) { + LOG_ERROR("File does not exist: %s", path); + return; + } + normalize_path((char*)path); + + bool foundNonZero = false; + for (u8 i = 0; i < 16; i++) { + if (dataHash[i] != 0) { + foundNonZero = true; + break; + } + } + if (!foundNonZero) { + LOG_ERROR("Hash was all zeros for path '%s'", path); return; } struct ModCacheEntry* node = calloc(1, sizeof(struct ModCacheEntry)); - memcpy(node->dataHash, dataHash, 16); + memcpy(node->dataHash, dataHash, sizeof(u8) * 16); if (lastLoaded == 0) { lastLoaded = clock(); } node->lastLoaded = lastLoaded; node->path = (char*)path; @@ -125,6 +153,8 @@ void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) { if (sModCacheHead == NULL) { sModCacheHead = node; + LOG_INFO("Added head: %s", node->path); + return; } struct ModCacheEntry* n = sModCacheHead; @@ -148,14 +178,18 @@ void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) { prev = n; n = next; } + + LOG_ERROR("Did not add node for some reason?"); } void mod_cache_add(struct Mod* mod, struct ModFile* file) { // sanity check if (mod == NULL || file == NULL) { + LOG_ERROR("Could not add to cache, mod or file is null"); return; } if (mod->basePath == NULL || file->relativePath == NULL) { + LOG_ERROR("Could not add to cache, basepath or relativepath is null"); return; } @@ -167,6 +201,7 @@ void mod_cache_add(struct Mod* mod, struct ModFile* file) { // build the path char modFilePath[SYS_MAX_PATH] = { 0 }; if (!concat_path(modFilePath, mod->basePath, file->relativePath)) { + LOG_ERROR("Could not concat mod file path"); return; } @@ -195,6 +230,7 @@ void mod_cache_load(void) { if (version != MOD_CACHE_VERSION) { fclose(fp); LOG_INFO("Mod cache version mismatch"); + mods_delete_tmp(); return; } @@ -226,7 +262,7 @@ void mod_cache_save(void) { LOG_INFO("Saving mod cache"); const char* filename = fs_get_write_path(MOD_CACHE_FILENAME); - if (filename == NULL) { + if (filename == NULL || strlen(filename) == 0) { LOG_ERROR("Failed to get filename for mod cache"); return; } @@ -242,6 +278,7 @@ void mod_cache_save(void) { struct ModCacheEntry* node = sModCacheHead; while (node != NULL) { + struct ModCacheEntry* next = node->next; if (node->path == NULL) { goto iterate; } u16 pathLen = strlen(node->path); if (pathLen == 0) { goto iterate; } @@ -251,7 +288,7 @@ void mod_cache_save(void) { fwrite(&pathLen, sizeof(u16), 1, fp); fwrite(node->path, sizeof(u8), pathLen + 1, fp); iterate: - node = node->next; + node = next; } fclose(fp); diff --git a/src/pc/mods/mods.c b/src/pc/mods/mods.c index 8db1ef2d..bef207ce 100644 --- a/src/pc/mods/mods.c +++ b/src/pc/mods/mods.c @@ -38,9 +38,6 @@ bool mods_generate_remote_base_path(void) { return false; } - // make directory - if (!fs_sys_dir_exists(gRemoteModsBasePath)) { fs_sys_mkdir(gRemoteModsBasePath); } - return true; } @@ -190,6 +187,7 @@ void mods_clear(struct Mods* mods) { for (int i = 0; i < mods->entryCount; i ++) { struct Mod* mod = mods->entries[i]; mod_clear(mod); + mods->entries[i] = NULL; } } diff --git a/src/pc/mods/mods_utils.c b/src/pc/mods/mods_utils.c index b42fcc9d..fd413f2e 100644 --- a/src/pc/mods/mods_utils.c +++ b/src/pc/mods/mods_utils.c @@ -105,6 +105,21 @@ static void mods_delete_folder(char* path) { rmdir(path); } +void mods_delete_tmp(void) { + // ensure tmpPath exists + char tmpPath[SYS_MAX_PATH] = { 0 }; + if (snprintf(tmpPath, SYS_MAX_PATH - 1, "%s", fs_get_write_path(TMP_DIRECTORY)) < 0) { + LOG_ERROR("Failed to concat tmp path"); + return; + } + + // sanity + if (strlen(tmpPath) < 1) { return; } + + // delete + mods_delete_folder(tmpPath); +} + ////////////////////////////////////////////////////////////////////////////////////////// bool mod_file_full_path(char* destination, struct Mod* mod, struct ModFile* modFile) { diff --git a/src/pc/mods/mods_utils.h b/src/pc/mods/mods_utils.h index 529e1dad..7f45ad1e 100644 --- a/src/pc/mods/mods_utils.h +++ b/src/pc/mods/mods_utils.h @@ -7,6 +7,7 @@ void mods_size_enforce(struct Mods* mods); void mods_update_selectable(void); +void mods_delete_tmp(void); bool mod_file_full_path(char* destination, struct Mod* mod, struct ModFile* modFile); bool mod_file_create_directories(struct Mod* mod, struct ModFile* modFile); From 1fdf8eb24085110e0110fd6a18fe0101a9680f75 Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 18 Apr 2022 22:03:37 -0700 Subject: [PATCH 4/4] Whoops --- src/pc/mods/mod_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pc/mods/mod_cache.c b/src/pc/mods/mod_cache.c index edaf40d0..9449bc39 100644 --- a/src/pc/mods/mod_cache.c +++ b/src/pc/mods/mod_cache.c @@ -75,7 +75,7 @@ void mod_cache_md5(const char* inPath, u8* outDataPath) { static bool mod_cache_is_valid(struct ModCacheEntry* node) { if (node == NULL || node->path == NULL || strlen(node->path) == 0) { - return; + return false; } u8 dataHash[16] = { 0 }; mod_cache_md5(node->path, dataHash);