From 2d63fd8d92f2dd45f86d6d49ff5619bb7a4d8c46 Mon Sep 17 00:00:00 2001 From: Marc Date: Sun, 11 Sep 2022 14:14:42 +0200 Subject: [PATCH] Removed small memory leaks and improved error code path at first when i create the proof of concept i didn't care at all about memory leak sine the kernel was cleaning that for me. --- src/install.c | 144 +++++++++++++++++++++++++++----------------------- src/install.h | 2 +- src/main.c | 74 +++++++++++++++++--------- src/steam.c | 60 ++++++++++++++------- 4 files changed, 169 insertions(+), 111 deletions(-) diff --git a/src/install.c b/src/install.c index a820672..c72c31b 100644 --- a/src/install.c +++ b/src/install.c @@ -9,97 +9,109 @@ //TODO: replace ALL system call by execv / execl since it make my code into swiss cheese -void unzip(const char * path, const char * outdir) { - char * unzipCommand = g_strconcat("/bin/sh -c 'yes | unzip \"", path, "\" -d \"" , outdir, "\" > /dev/null'", NULL); - if(system(unzipCommand) != 0) { - printf("\nFailed to unzip archive\n"); - exit(EXIT_FAILURE); - } - free(unzipCommand); - +int unzip(const char * path, const char * outdir) { + int returnValue = EXIT_SUCCESS; + char * unzipCommand = g_strconcat("/bin/sh -c 'yes | unzip \"", path, "\" -d \"" , outdir, "\" > /dev/null'", NULL); + if(system(unzipCommand) != 0) { + printf("\nFailed to unzip archive\n"); + returnValue = EXIT_FAILURE; + } + free(unzipCommand); + return returnValue; } -void unrar(const char * path, const char * outdir) { - char * unrarCommand = g_strconcat("/bin/sh -c 'unrar -y x \"", path, "\" \"", outdir, "\" > /dev/null'", NULL); - if(system(unrarCommand) != 0) { - printf("Failed to unzip archive\n"); - exit(EXIT_FAILURE); - } - free(unrarCommand); +int unrar(const char * path, const char * outdir) { + int returnValue = EXIT_SUCCESS; + char * unrarCommand = g_strconcat("/bin/sh -c 'unrar -y x \"", path, "\" \"", outdir, "\" > /dev/null'", NULL); + if(system(unrarCommand) != 0) { + printf("Failed to unzip archive\n"); + returnValue = EXIT_FAILURE; + } + free(unrarCommand); + return returnValue; } -void un7z(const char * path, const char * outdir) { - char * un7zCommand = g_strconcat("/bin/sh -c 'yes | 7z x \"", path, "\" \"-o", outdir, "\" > /dev/null'", NULL); - if(system(un7zCommand) != 0) { - printf("Failed to unzip archive\n"); - exit(EXIT_FAILURE); - } - free(un7zCommand); +int un7z(const char * path, const char * outdir) { + int returnValue = EXIT_SUCCESS; + char * un7zCommand = g_strconcat("/bin/sh -c 'yes | 7z x \"", path, "\" \"-o", outdir, "\" > /dev/null'", NULL); + if(system(un7zCommand) != 0) { + printf("Failed to unzip archive\n"); + returnValue = EXIT_FAILURE; + } + free(un7zCommand); + return returnValue; } char * extractLastPart(const char * filePath, const char delimeter) { -int length = strlen(filePath); - int index = -1; - for(int i= length -1; i >= 0; i--) { - if(filePath[i] == delimeter) { - index = i + 1; - break; - } - } + int length = strlen(filePath); + int index = -1; + for(int i= length -1; i >= 0; i--) { + if(filePath[i] == delimeter) { + index = i + 1; + break; + } + } - if(index <= 0) return NULL; - char * extension = malloc((length - index) * sizeof(char)); - memcpy(extension, &filePath[index], (length - index)); - return extension; + if(index <= 0 || index == length) return NULL; + char * extension = malloc((length - index) * sizeof(char)); + memcpy(extension, &filePath[index], (length - index)); + return extension; } char * extractExtension(const char * filePath) { - return extractLastPart(filePath, '.'); + return extractLastPart(filePath, '.'); } char * extractFileName(const char * filePath) { - return extractLastPart(filePath, '/'); + return extractLastPart(filePath, '/'); } -void addMod(const char * filePath, int appId) { +int addMod(const char * filePath, int appId) { + int returnValue = EXIT_SUCCESS; + if (access(filePath, F_OK) != 0) { - printf("File not found\n"); - exit(EXIT_FAILURE); + printf("File not found\n"); + returnValue = EXIT_FAILURE; + goto exit; } - char * configFolder = g_build_filename(getenv("HOME"), MANAGER_FILES, NULL); + char * configFolder = g_build_filename(getenv("HOME"), MANAGER_FILES, NULL); if(g_mkdir_with_parents(configFolder, 0755) < 0) { - printf("Could not create mod folder"); - exit(EXIT_FAILURE); - } + printf("Could not create mod folder"); + returnValue = EXIT_FAILURE; + goto exit2; + } - char * filename = extractFileName(filePath); - char * extension = extractExtension(filename); - char * lowercaseExtension = g_ascii_strdown(extension, -1); - free(extension); + char * filename = extractFileName(filePath); + char * extension = extractExtension(filename); + char * lowercaseExtension = g_ascii_strdown(extension, -1); + free(extension); - char appIdStr[20]; - sprintf(appIdStr, "%d", appId); + char appIdStr[20]; - char * outdir = g_build_filename(configFolder, MOD_FOLDER_NAME, appIdStr, filename, NULL); + char * outdir = g_build_filename(configFolder, MOD_FOLDER_NAME, appIdStr, filename, NULL); - g_mkdir_with_parents(outdir, 0755); - printf("Adding mod, this process can be slow depending on your hardware\n"); - if(strcmp(lowercaseExtension, "rar") == 0) { - unrar(filePath, outdir); - } else if (strcmp(lowercaseExtension, "zip") == 0) { - unzip(filePath, outdir); - } else if (strcmp(lowercaseExtension, "7z") == 0) { - un7z(filePath, outdir); - } else { - printf("Unsupported format only zip/7z/rar are supported\n"); - exit(EXIT_FAILURE); - } + g_mkdir_with_parents(outdir, 0755); + printf("Adding mod, this process can be slow depending on your hardware\n"); + if(strcmp(lowercaseExtension, "rar") == 0) { + returnValue = unrar(filePath, outdir); + } else if (strcmp(lowercaseExtension, "zip") == 0) { + returnValue = unzip(filePath, outdir); + } else if (strcmp(lowercaseExtension, "7z") == 0) { + returnValue = un7z(filePath, outdir); + } else { + printf("Unsupported format only zip/7z/rar are supported\n"); + returnValue = EXIT_FAILURE; + } - printf("Done\n"); + printf("Done\n"); - free(lowercaseExtension); - free(filename); - free(outdir); + free(lowercaseExtension); + free(filename); + free(outdir); +exit2: + free(configFolder); +exit: + return returnValue; } diff --git a/src/install.h b/src/install.h index 5ec6138..abaaa4e 100644 --- a/src/install.h +++ b/src/install.h @@ -1,6 +1,6 @@ #ifndef __INSTALL_H__ #define __INSTALL_H__ #define INSTALLED_FLAG_FILE "__DO_NOT_REMOVE__" -void addMod(const char * filePath, int appId); +int addMod(const char * filePath, int appId); #endif diff --git a/src/main.c b/src/main.c index e71c012..1c4ae6c 100644 --- a/src/main.c +++ b/src/main.c @@ -365,17 +365,19 @@ int main(int argc, char ** argv) { } gamePaths = search_games(); - - - + int returnValue = EXIT_SUCCESS; char * configFolder = g_build_filename(getHome(), MANAGER_FILES, NULL); if(access(configFolder, F_OK) != 0) { + //check to NOT run this as root //creating folder as root will causes lots of headache + //such as problem with access rights and taking the risk of + //running system as root (wich is a big security issue) if(getuid() == 0) { printf("For the first please run without sudo\n"); - return EXIT_FAILURE; + returnValue = EXIT_FAILURE; + goto exit; } else { //leading 0 == octal int i = g_mkdir_with_parents(configFolder, 0755); @@ -389,37 +391,61 @@ int main(int argc, char ** argv) { free(chattrcommand); } } - free(configFolder); if(strcmp(argv[1], "--list-games") == 0 || strcmp(argv[1], "-l") == 0) { - if(isRoot()) return noRoot(); - return listGames(argc, argv); + if(isRoot()) + returnValue = noRoot(); + else + returnValue = listGames(argc, argv); + } else if(strcmp(argv[1], "--add") == 0 || strcmp(argv[1], "-a") == 0) { - if(isRoot()) return noRoot(); - return add(argc, argv); + if(isRoot()) + returnValue = noRoot(); + else + returnValue = add(argc, argv); + } else if(strcmp(argv[1], "--list-mods") == 0 || strcmp(argv[1], "-m") == 0) { - if(isRoot()) return noRoot(); - return listMods(argc, argv); + if(isRoot()) + returnValue = noRoot(); + else + returnValue = listMods(argc, argv); + } else if(strcmp(argv[1], "--install") == 0 || strcmp(argv[1], "-i") == 0) { - if(isRoot()) return noRoot(); - return installAndRemoveMod(argc, argv, true); + if(isRoot()) + returnValue = noRoot(); + else + returnValue = installAndRemoveMod(argc, argv, true); + } else if(strcmp(argv[1], "--remove") == 0 || strcmp(argv[1], "-r") == 0) { - if(isRoot()) return noRoot(); - return installAndRemoveMod(argc, argv, false); + if(isRoot()) + returnValue = noRoot(); + else + returnValue = installAndRemoveMod(argc, argv, false); + } else if(strcmp(argv[1], "--deploy") == 0 || strcmp(argv[1], "-d") == 0) { - if(!isRoot()) return needRoot(); - return deploy(argc, argv); + if(!isRoot()) + returnValue = needRoot(); + else + returnValue = deploy(argc, argv); + } else if(strcmp(argv[1], "--unbind") == 0 || strcmp(argv[1], "-u") == 0){ - if(!isRoot()) return needRoot(); - return unbind(argc, argv); + if(!isRoot()) + returnValue = needRoot(); + else + returnValue = unbind(argc, argv); + } else if(strcmp(argv[1], "--setup") == 0) { - if(isRoot()) return noRoot(); - return setup(argc, argv); + if(isRoot()) + returnValue = noRoot(); + else + returnValue = setup(argc, argv); } else { - return usage(); + usage(); + returnValue = EXIT_FAILURE; } - - return 0; +exit: + free(configFolder); + return returnValue; } diff --git a/src/steam.c b/src/steam.c index 3a908a1..92532fb 100644 --- a/src/steam.c +++ b/src/steam.c @@ -32,17 +32,17 @@ int getFiledId(const char * field) { return FIELD_APPS; } else { printf("unknown field"); - exit(EXIT_FAILURE); + return -1; } } -ValveLibraries_t * parseVDF(const char * path, size_t * size) { +ValveLibraries_t * parseVDF(const char * path, size_t * size, int * status) { FILE * fd = fopen(path, "r"); char * line = NULL; size_t len = 0; ssize_t read; - + *status = EXIT_SUCCESS; bool inQuotes = false; @@ -75,6 +75,11 @@ ValveLibraries_t * parseVDF(const char * path, size_t * size) { buffer[bufferIndex] = '\0'; if(nextFieldToFill == -1) { nextFieldToFill = getFiledId(buffer); + if(nextFieldToFill == -1) { + if(libraries != NULL) free(libraries); + libraries = NULL; + goto exit; + } } else { char * value = strndup(buffer, bufferIndex); @@ -137,7 +142,10 @@ ValveLibraries_t * parseVDF(const char * path, size_t * size) { case '}': if(inQuotes) { printf("Syntax error in VDF\n"); - exit(EXIT_FAILURE); + free(libraries); + libraries = NULL; + *status = EXIT_FAILURE; + goto exit; } if(nextFieldToFill == FIELD_APPS) { nextFieldToFill = -1; @@ -153,25 +161,47 @@ ValveLibraries_t * parseVDF(const char * path, size_t * size) { } } +exit: fclose(fd); return libraries; } -GHashTable* search_games() { +void freeLibraries(ValveLibraries_t * libraries, int size) { + for(int i = 0; i < size; i++) { + free(libraries[i].path); + free(libraries[i].label); + free(libraries[i].contentId); + free(libraries[i].update_clean_bytes_tally); + free(libraries[i].time_last_update_corruption); + free(libraries[i].apps); + } + free(libraries); +} + +GHashTable* search_games(int * status) { ValveLibraries_t * libraries = NULL; size_t size = 0; - const char * HOME = getHome(); + char * home = getHome(); + *status = EXIT_SUCCESS; for(int i = 0; i < LEN(steamLibraries); i++) { - char * path = g_build_filename(HOME, steamLibraries[i], "steamapps/libraryfolders.vdf", NULL); + char * path = g_build_filename(home, steamLibraries[i], "steamapps/libraryfolders.vdf", NULL); if (access(path, F_OK) == 0) { - libraries = parseVDF(path, &size); - break; + int parserStatus; + libraries = parseVDF(path, &size, &parserStatus); + if(parserStatus == EXIT_SUCCESS) + break; } g_free(path); } + free(home); + if(libraries == NULL) { + *status = EXIT_FAILURE; + return NULL; + } + GHashTable* table = g_hash_table_new(g_int_hash, g_int_equal); //fill the table @@ -186,17 +216,7 @@ GHashTable* search_games() { } } - //free used up memory - for(int i = 0; i < size; i++) { - free(libraries[i].path); - free(libraries[i].label); - free(libraries[i].contentId); - free(libraries[i].update_clean_bytes_tally); - free(libraries[i].time_last_update_corruption); - free(libraries[i].apps); - } - - if(libraries != NULL) free(libraries); + freeLibraries(libraries, size); return table; }