diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..a75378b --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,36 @@ +# This file is a template, and might need editing before it works on your project. +# To contribute improvements to CI/CD templates, please follow the Development guide at: +# https://docs.gitlab.com/ee/development/cicd/templates.html +# This specific template is located at: +# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml + +# This is a sample GitLab CI/CD configuration file that should run without any modifications. +# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts, +# it uses echo commands to simulate the pipeline execution. +# +# A pipeline is composed of independent jobs that run scripts, grouped into stages. +# Stages run in sequential order, but jobs within stages run in parallel. +# +# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages + +before_script: + - apt update -y + - apt install cmake libglib2.0-dev libgtk-4-dev make gcc git make clang libaudit-dev -y + + +stages: # List of stages for jobs, and their order of execution + - build + +build-job: # This job runs in the build stage, which runs first. + stage: build + script: + - mkdir build + - cd build + - cmake .. + - make + - echo "Build done" + artifacts: + paths: + - build/ModManager + expire_in: 1 week + diff --git a/CMakeLists.txt b/CMakeLists.txt index dfdbfd0..6c4d169 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,6 @@ project(ModManager) set(SOURCES - src/main.c src/steam.c src/install.c src/overlayfs.c @@ -24,7 +23,8 @@ set(SOURCES ) # add the executable -add_executable(ModManager ${SOURCES}) +add_executable(ModManager src/main.c ${SOURCES}) + add_compile_options(-Wall -Wextra -pedantic -Werror) find_package(PkgConfig REQUIRED) diff --git a/src/file.h b/src/file.h index 852dea6..3c1be0c 100644 --- a/src/file.h +++ b/src/file.h @@ -4,13 +4,44 @@ #ifndef __FILE_H__ #define __FILE_H__ + +//valid copy flags +#define cp_DEFAULT 0 #define CP_LINK 1 #define CP_RECURSIVE 2 #define CP_NO_TARGET_DIR 4 -int copy(const char * path, const char * dest, u_int32_t flags); +/** + * @brief execute the cp command from the source to the dest + * @param source path to the source files + * @param dest path to the destination folder + * @param flags refer to the "valid copy flags" use them like this CP_LINK | CP_RECURSIVE + * @return status code + */ +int copy(const char * source, const char * dest, u_int32_t flags); + +/** + * @brief execute the cp command from the source to the dest + * @param source path to the source files + * @param dest path to the destination folder +* @param bool enable recursive rm -r + * @return status code + */ int delete(const char * path, bool recursive); + +/** + * @brief Run the mv command + * @param source + * @param destination + * @return mv's exit value + */ int move(const char * source, const char * destination); + +/** + * @brief Recursively rename all file and folder to lowercase. + * + * @param folder + */ void casefold(const char * folder); #endif diff --git a/src/fomod.c b/src/fomod.c index 4fd07f0..3d5c2e8 100644 --- a/src/fomod.c +++ b/src/fomod.c @@ -1,4 +1,3 @@ -#include "fomod.h" #include #include #include @@ -8,11 +7,12 @@ #include #include #include -#include #include +#include + +#include "fomod.h" #include "file.h" #include "libxml/globals.h" -#include "fomod/parser.h" int getInputCount(const char * input) { char buff[2]; @@ -47,39 +47,6 @@ gint priorityCmp(gconstpointer a, gconstpointer b) { return fileA->priority - fileB->priority; } - -char * findFOModFolder(const char * modFolder) { - struct dirent * dir; - DIR *d = opendir(modFolder); - if (d) { - while ((dir = readdir(d)) != NULL) { - if(g_ascii_strcasecmp(dir->d_name, "fomod") == 0) { - char * fomodDir = g_build_path("/", modFolder, dir->d_name, NULL); - closedir(d); - return fomodDir; - } - } - closedir(d); - } - return NULL; -} - -char * findFOModFile(const char * fomodFolder) { - struct dirent * dir; - DIR *d = opendir(fomodFolder); - if (d) { - while ((dir = readdir(d)) != NULL) { - if(g_ascii_strcasecmp(dir->d_name, "moduleconfig.xml") == 0) { - char * fomodFile = g_build_filename(fomodFolder, dir->d_name, NULL); - closedir(d); - return fomodFile; - } - } - closedir(d); - } - return NULL; -} - void printfOptionsInOrder(FOModGroup_t group) { for(int i = 0; i < group.pluginCount; i++) { printf("%d, %s\n", i, group.plugins[i].name); @@ -152,18 +119,75 @@ void sortGroup(FOModGroup_t * group) { } } -//TODO: support priority -int installFOMod(const char * modFolder, const char * destination) { - char * fomodFolder = findFOModFolder(modFolder); - if(fomodFolder == NULL) { - fprintf(stderr, "Fomod folder not found, are you sure this is a fomod mod ?\n"); - return EXIT_FAILURE; - } +//TODO: handle error +int processFileOperations(GList * pendingFileOperations, const char * modFolder, const char * destination) { + pendingFileOperations = g_list_sort(pendingFileOperations, priorityCmp); + GList * currentFileOperation = pendingFileOperations; - char * fomodFile = findFOModFile(fomodFolder); - if(fomodFile == NULL) { + while(currentFileOperation != NULL) { + //TODO: support destination + //no using link since priority is made to override files and link is annoying to deal with when overriding files. + const FOModFile_t * file = (const FOModFile_t *)currentFileOperation->data; + char * source = g_build_path("/", modFolder, file->source, NULL); + + //fix the / and \ windows - unix paths + fixPath(source); + + int copyResult; + if(file->isFolder) { + copyResult = copy(source, destination, CP_NO_TARGET_DIR | CP_RECURSIVE); + } else { + copyResult = copy(source, destination, 0); + } + if(copyResult != EXIT_SUCCESS) { + fprintf(stderr, "Copy failed, some file might be corrupted\n"); + } + printf("source: %s, destination: %s\n", source, destination); + g_free(source); + + currentFileOperation = g_list_next(currentFileOperation); + } + return EXIT_SUCCESS; +} + +GList * processCondFiles(const FOMod_t * fomod, GList * flagList, GList * pendingFileOperations) { + for(int condId = 0; condId < fomod->condFilesCount; condId++) { + const FOModCondFile_t *condFile = &fomod->condFiles[condId]; + + bool areAllFlagsValid = true; + + //checking if all flags are valid + for(int flagId = 0; flagId < condFile->flagCount; flagId++) { + const GList * link = g_list_find_custom(flagList, &(condFile->requiredFlags[flagId]), (GCompareFunc)flagEqual); + if(link == NULL) { + areAllFlagsValid = false; + break; + } + } + + if(areAllFlagsValid) { + for(int fileId = 0; fileId < condFile->flagCount; fileId++) { + const FOModFile_t * file = &(condFile->files[fileId]); + + FOModFile_t * fileCopy = malloc(sizeof(*file)); + *fileCopy = *file; + + pendingFileOperations = g_list_append(pendingFileOperations, fileCopy); + } + } + } + return pendingFileOperations; +} + +int installFOMod(const char * modFolder, const char * destination) { + //everything should be lowercase since we use casefold() before calling any install function + char * fomodFolder = g_build_path("/", modFolder, "fomod", NULL); + char * fomodFile = g_build_filename(fomodFolder, "moduleconfig.xml", NULL); + + if(access(fomodFile, F_OK) != 0) { fprintf(stderr, "FOMod file not found, are you sure this is a fomod mod ?\n"); g_free(fomodFolder); + g_free(fomodFile); return EXIT_FAILURE; } @@ -172,6 +196,7 @@ int installFOMod(const char * modFolder, const char * destination) { if(returnValue != EXIT_SUCCESS) { return returnValue; } + g_free(fomodFile); GList * flagList = NULL; GList * pendingFileOperations = NULL; @@ -179,7 +204,7 @@ int installFOMod(const char * modFolder, const char * destination) { sortSteps(&fomod); for(int i = 0; i < fomod.stepCount; i++) { - FOModStep_t * step = &fomod.steps[i]; + const FOModStep_t * step = &fomod.steps[i]; bool validFlags = true; for(int flagId = 0; flagId < step->flagCount; flagId++) { @@ -280,66 +305,15 @@ int installFOMod(const char * modFolder, const char * destination) { } } - for(int condId = 0; condId < fomod.condFilesCount; condId++) { - const FOModCondFile_t *condFile = &fomod.condFiles[condId]; - - bool areAllFlagsValid = true; - - //checking if all flags are valid - for(int flagId = 0; flagId < condFile->flagCount; flagId++) { - const GList * link = g_list_find_custom(flagList, &(condFile->requiredFlags[flagId]), (GCompareFunc)flagEqual); - if(link == NULL) { - areAllFlagsValid = false; - break; - } - } - - if(areAllFlagsValid) { - for(int fileId = 0; fileId < condFile->flagCount; fileId++) { - const FOModFile_t * file = &(condFile->files[fileId]); - - FOModFile_t * fileCopy = malloc(sizeof(*file)); - *fileCopy = *file; - - pendingFileOperations = g_list_append(pendingFileOperations, fileCopy); - } - } - } - - - pendingFileOperations = g_list_sort(pendingFileOperations, priorityCmp); - GList * currentFileOperation = pendingFileOperations; - - while(currentFileOperation != NULL) { - //TODO: support destination - //TODO: handle error - //no using link since priority is made to override files and link is annoying to deal with when overriding files. - const FOModFile_t * file = (const FOModFile_t *)currentFileOperation->data; - char * source = g_build_path("/", modFolder, file->source, NULL); - - //fix the / and \ windows - unix paths - fixPath(source); - - int copyResult; - if(file->isFolder) { - copyResult = copy(source, destination, CP_NO_TARGET_DIR | CP_RECURSIVE); - } else { - copyResult = copy(source, destination, 0); - } - if(copyResult != EXIT_SUCCESS) { - fprintf(stderr, "Copy failed, some file might be corrupted\n"); - } - printf("source: %s, destination: %s\n", source, destination); - g_free(source); - - currentFileOperation = g_list_next(currentFileOperation); - } + pendingFileOperations = processCondFiles(&fomod, flagList, pendingFileOperations); + processFileOperations(pendingFileOperations, modFolder, destination); printf("FOMod successfully installed!\n"); g_list_free(flagList); g_list_free_full(pendingFileOperations, free); freeFOMod(&fomod); + g_free(fomodFolder); return EXIT_SUCCESS; } diff --git a/src/fomod.h b/src/fomod.h index 8f12725..368af57 100644 --- a/src/fomod.h +++ b/src/fomod.h @@ -2,9 +2,41 @@ #define __FOMOD_H__ #include +#include +#include "fomod/parser.h" + #include "fomod/group.h" #include "fomod/xmlUtil.h" +/** + * @brief Start a terminal based install process for fomod. + * + * @param modFolder folder of the fomod file. + * @param destination folder of the new mod that contains the result of the fomod process. + * @return int + */ int installFOMod(const char * modFolder, const char * destination); +/** + * @brief In fomod there is file operations which depends on multiple flags this function find the ones that mach our current flags and append them to a list. + * + * @param fomod a pointer to a fomod obtained by the parser + * @param flagList a FOModFlag_t list which contains all of the flag found. + * @param pendingFileOperations a list of pending FOModFile_t operation to which add the new ones. (can be null) + * @return a list of pendingFileOperations(FOModFile_t) + */ +GList * processCondFiles(const FOMod_t * fomod, GList * flagList, GList * pendingFileOperations) __attribute__((warn_unused_result)); + +/** + * @brief FOModFile_t have a priority option and this function execute the file operation while taking this into account. + * + * @param pendingFileOperations list of FOModFile_t to process + * @param modFolder folder of the fomod file. + * @param destination folder of the new mod that contains the result of the process. + * @return error code + */ +int processFileOperations(GList * pendingFileOperations, const char * modFolder, const char * destination); + + + #endif diff --git a/src/fomod/parser.c b/src/fomod/parser.c index 747ea76..fe8c437 100644 --- a/src/fomod/parser.c +++ b/src/fomod/parser.c @@ -2,6 +2,7 @@ #include "libxml/tree.h" #include "xmlUtil.h" #include +#include //Maybe integrate this into the rest of the code instead of freeing after the fact void freeFOMod(FOMod_t * fomod) { @@ -21,11 +22,10 @@ void freeFOMod(FOMod_t * fomod) { free(condFile->requiredFlags); } free(fomod->condFiles); - free(fomod->moduleImage); free(fomod->moduleName); - int size = countUntilNull(fomod->requiredInstallFiles); + int size = countUntilNull(fomod->requiredInstallFiles, sizeof(char **)); for(int i = 0; i < size; i++) { free(fomod->requiredInstallFiles[i]); } @@ -46,6 +46,9 @@ void freeFOMod(FOMod_t * fomod) { free(step->requiredFlags); free(step->name); } + + //set every counter to zero and every pointer to null + memset(fomod, 0, sizeof(FOMod_t)); } int parseVisibleNode(xmlNodePtr node, FOModStep_t * step) { @@ -285,7 +288,7 @@ int parseFOMod(const char * fomodFile, FOMod_t* fomod) { exit(EXIT_FAILURE); } - int size = countUntilNull(fomod->requiredInstallFiles) + 2; + int size = countUntilNull(fomod->requiredInstallFiles, sizeof(char **)) + 2; fomod->requiredInstallFiles = realloc(fomod->requiredInstallFiles, sizeof(char *) * size); //ensure it is null terminated fomod->requiredInstallFiles[size - 1] = NULL; diff --git a/src/fomod/parser.h b/src/fomod/parser.h index 1f665fc..6f08a5c 100644 --- a/src/fomod/parser.h +++ b/src/fomod/parser.h @@ -25,7 +25,19 @@ typedef struct FOMod { int condFilesCount; } FOMod_t; +/** + * @brief parse a fomod xml file (found inside the mod folder /fomod/moduleconfig.xml (everything should be lowercase)) + * + * @param fomodFile path to the moduleconfig.xml + * @param fomod pointer to a new FOMod_t + * @return error code. + */ int parseFOMod(const char * fomodFile, FOMod_t* fomod); + +/** + * @brief Free content of a fomod file. + * @param fomod + */ void freeFOMod(FOMod_t * fomod); #endif diff --git a/src/fomod/xmlUtil.c b/src/fomod/xmlUtil.c index 4cc149a..b7c0d3d 100644 --- a/src/fomod/xmlUtil.c +++ b/src/fomod/xmlUtil.c @@ -27,10 +27,10 @@ void fixPath(char * path) { } } -int countUntilNull(void * pointers) { +int countUntilNull(void * pointers, size_t typeSize) { int i = 0; while(pointers != NULL) { - pointers++; + pointers += typeSize; i++; } return i; diff --git a/src/fomod/xmlUtil.h b/src/fomod/xmlUtil.h index 95b637a..e09e236 100644 --- a/src/fomod/xmlUtil.h +++ b/src/fomod/xmlUtil.h @@ -8,9 +8,24 @@ typedef enum FOModOrder { ASC, DESC, ORD } FOModOrder_t; bool validateNode(xmlNodePtr * node, bool skipText, const char * names, ...); +/** + * @brief Free memory of and xmlChar and return a strdup version. just to make sure there is nothing remaining in libxml + */ char * freeAndDup(xmlChar * line); FOModOrder_t getFOModOrder(const char * order); +/** + * @brief replace / by \ + * @param path + */ void fixPath(char * path); -int countUntilNull(void * pointers); + +/** + * @brief Count the number of step before null + * + * @param pointers pointer to the list + * @param typeSize size of each element of the list + * @return size + */ +int countUntilNull(void * pointers, size_t typeSize); #endif diff --git a/src/getHome.h b/src/getHome.h index d242b54..141b34c 100644 --- a/src/getHome.h +++ b/src/getHome.h @@ -1 +1,8 @@ + + +/** + * @brief Get the user home dir regardless if he used sudo. + * + * @return char* path to the home dir + */ char * getHome(); diff --git a/src/install.h b/src/install.h index 9fb8a57..5a89ca6 100644 --- a/src/install.h +++ b/src/install.h @@ -1,6 +1,15 @@ #ifndef __INSTALL_H__ #define __INSTALL_H__ +#include #define INSTALLED_FLAG_FILE "__DO_NOT_REMOVE__" + +/** + * @brief Add a mod to the folder defined in main.h + * + * @param filePath path to the mod file + * @param appId game for which the mod is destined to be used with. + * @return EXIT_SUCCESS or EXIT_FAILURE + */ int addMod(char * filePath, int appId); #endif diff --git a/src/macro.h b/src/macro.h index 82803a9..10b43f7 100644 --- a/src/macro.h +++ b/src/macro.h @@ -1,7 +1,7 @@ #ifndef __MACRO_H__ #define __MACRO_H__ -//cannot be empty it's made for fixed size array +//cannot be empty it's made for fixed size array like the ones in steam.h #define LEN(array) sizeof(array) / sizeof(array[0]) #endif diff --git a/src/main.c b/src/main.c index 24521f1..0d1f95d 100644 --- a/src/main.c +++ b/src/main.c @@ -64,15 +64,12 @@ int usage() { printf("Use --deploy or -d to deploy the mods for the game\n"); printf("Use --unbind to rollback a deployment\n"); printf("Use --fomod to create a new mod using the result from the FOMod\n"); - //TODO: as bonus - //printf("Use --start-game to deploy the mods and launch the game through steam\n"); - //printf("Use --steam in team cmdline options to deploy directly on game startup\n"); return EXIT_FAILURE; } int validateAppId(const char * appIdStr) { //strtoul set EINVAL(after C99) if the string is invalid - u_int32_t appid = strtoul(appIdStr, NULL, 10); + unsigned long appid = strtoul(appIdStr, NULL, 10); if(errno == EINVAL) { printf("Appid has to be a valid number\n"); return -1; @@ -89,7 +86,8 @@ int validateAppId(const char * appIdStr) { return -1; } - return appid; + //no valid appid goes far enough to justify long + return (int)appid; } int listGames(int argc, char ** argv) { @@ -100,7 +98,7 @@ int listGames(int argc, char ** argv) { printf("No game found\n"); } else { while(gamesIds != NULL) { - int * gameIndex = (int*)gamesIds->data; + const int * gameIndex = (int*)gamesIds->data; printf("%d: %s\n", GAMES_APPIDS[*gameIndex], GAMES_NAMES[*gameIndex]); gamesIds = g_list_next(gamesIds); } @@ -111,9 +109,9 @@ int listGames(int argc, char ** argv) { int add(int argc, char ** argv) { if(argc != 4) return usage(); - char * appIdStr = argv[2]; + const char * appIdStr = argv[2]; - u_int32_t appid = validateAppId(appIdStr); + int appid = validateAppId(appIdStr); if(appid < 0) { return EXIT_FAILURE; } @@ -168,7 +166,7 @@ int listAllMods(int argc, char ** argv) { int installAndUninstallMod(int argc, char ** argv, bool install) { if(argc != 4) return usage(); char * appIdStr = argv[2]; - u_int32_t appid = validateAppId(appIdStr); + int appid = validateAppId(appIdStr); if(appid < 0) { return EXIT_FAILURE; } @@ -176,7 +174,7 @@ int installAndUninstallMod(int argc, char ** argv, bool install) { int returnValue = EXIT_SUCCESS; //strtoul set EINVAL if the string is invalid - u_int32_t modId = strtoul(argv[3], NULL, 10); + unsigned long modId = strtoul(argv[3], NULL, 10); if(errno == EINVAL) { printf("ModId has to be a valid number\n"); return -1; @@ -185,6 +183,7 @@ int installAndUninstallMod(int argc, char ** argv, bool install) { //might crash if no mods were installed char * home = getHome(); char * modFolder = g_build_filename(home, MANAGER_FILES, MOD_FOLDER_NAME, appIdStr, NULL); + free(home); GList * mods = listFilesInFolder(modFolder); GList * modsFirstPointer = mods; @@ -208,9 +207,14 @@ int installAndUninstallMod(int argc, char ** argv, bool install) { } //Create activated file - FILE * fd = fopen(modFlag, "w"); - fwrite("", 1, 1, fd); - fclose(fd); + FILE * fd = fopen(modFlag, "w+"); + if(fd != NULL) { + fwrite("", 1, 1, fd); + fclose(fd); + } else { + printf("Could not interact with the activation file\n"); + returnValue = EXIT_FAILURE; + } } else { if(access(modFlag, F_OK) != 0) { printf("The mod is not activated \n"); @@ -287,6 +291,8 @@ int deploy(int argc, char ** argv) { free(modFlag); } + g_free(modFolder); + //const char * data = "lowerdir=gameFolder,gameFolder2,gameFolder3..." modsToInstall[modCount] = gameFolder; modsToInstall[modCount + 1] = NULL; @@ -297,6 +303,7 @@ int deploy(int argc, char ** argv) { char * gameUpperDir = g_build_filename(home, MANAGER_FILES, GAME_UPPER_DIR_NAME, appIdStr, NULL); char * gameWorkDir = g_build_filename(home, MANAGER_FILES, GAME_WORK_DIR_NAME, appIdStr, NULL); + free(home); //unmount the game folder //DETACH + FORCE allow us to be sure it will be unload. @@ -317,12 +324,16 @@ int deploy(int argc, char ** argv) { return EXIT_FAILURE; } + g_free(steamGameFolder); + g_free(gameUpperDir); + g_free(gameWorkDir); + return EXIT_SUCCESS; } int setup(int argc, char ** argv) { if(argc != 3 ) return usage(); - char * appIdStr = argv[2]; + const char * appIdStr = argv[2]; int appid = validateAppId(appIdStr); if(appid < 0) { return EXIT_FAILURE; @@ -372,7 +383,7 @@ int setup(int argc, char ** argv) { int unbind(int argc, char ** argv) { if(argc != 3 ) return usage(); - char * appIdStr = argv[2]; + const char * appIdStr = argv[2]; int appid = validateAppId(appIdStr); if(appid < 0) { return EXIT_FAILURE; @@ -389,7 +400,7 @@ int unbind(int argc, char ** argv) { int removeMod(int argc, char ** argv) { if(argc != 4) return usage(); - char * appIdStr = argv[2]; + const char * appIdStr = argv[2]; int appid = validateAppId(appIdStr); if(appid < 0) { printf("Invalid appid"); @@ -424,6 +435,7 @@ int removeMod(int argc, char ** argv) { delete(filename, true); g_free(filename); + g_free(modFolder); g_list_free_full(modsFirstPointer, free); return EXIT_SUCCESS; } @@ -473,6 +485,9 @@ int fomod(int argc, char ** argv) { free(destination); g_list_free_full(modsFirstPointer, free); + g_free(modDestination); + g_free(modPath); + g_free(modFolder); return returnValue; } diff --git a/src/main.h b/src/main.h index 02a5edd..e63cd96 100644 --- a/src/main.h +++ b/src/main.h @@ -5,6 +5,9 @@ // in c "A" "B" is the same as "AB" #define MANAGER_FILES ".local/share/" APP_NAME #define MOD_FOLDER_NAME "MOD_FOLDER" +//the folder in which the games file will be linked or copied #define GAME_FOLDER_NAME "GAME_FOLDER" +//the director that will contain all modifications to game files while being deployed #define GAME_UPPER_DIR_NAME "UPPER_DIRS" +//overlayfs temporary dir. #define GAME_WORK_DIR_NAME "WORK_DIRS" diff --git a/src/order.c b/src/order.c index d4ef1de..0354585 100644 --- a/src/order.c +++ b/src/order.c @@ -96,6 +96,5 @@ void swapPlace(int appid, int modId, int modId2) { GList * list = listMods(appid); - g_list_free(list); } diff --git a/src/order.h b/src/order.h index 118381d..020b04d 100644 --- a/src/order.h +++ b/src/order.h @@ -15,6 +15,15 @@ * @return GList of char containing the name of the mod folder in order */ GList * listMods(int appid); + +/** + * @brief Change the mod order by swaping two mod + * + * @param appid the game + * index of the mod in the mod list. + * @param modId + * @param modId2 + */ void swapPlace(int appid, int modId, int modId2); #endif diff --git a/src/overlayfs.h b/src/overlayfs.h index 438335e..f9eb612 100644 --- a/src/overlayfs.h +++ b/src/overlayfs.h @@ -1,6 +1,15 @@ #ifndef __OVERLAY_H__ #define __OVERLAY_H__ +/** + * @brief Overlayfs is what make it possible to deploy to the game files without altering anything. + * it allows us to overlay multiple folder over the game files. like appling filters to an image. + * @param sources a null ended table of folder that will overlay of the game files + * @param dest the overlayed folder(the game data folder) + * @param upperdir the director that will store the changed files + * @param workdir a directory that will contains only temporary files. + * @return int error code + */ int overlayMount(char ** sources, const char * dest, const char * upperdir, const char * workdir); #endif diff --git a/src/steam.c b/src/steam.c index b26da3e..ee77166 100644 --- a/src/steam.c +++ b/src/steam.c @@ -223,9 +223,9 @@ GHashTable* search_games(int * status) { } -int getGameIdFromAppId(u_int32_t id) { +int getGameIdFromAppId(u_int32_t appid) { for(int k = 0; k < LEN(GAMES_APPIDS); k++) { - if(id == GAMES_APPIDS[k]) { + if(appid == GAMES_APPIDS[k]) { return k; } } diff --git a/src/steam.h b/src/steam.h index dedc2e7..983ce4a 100644 --- a/src/steam.h +++ b/src/steam.h @@ -36,14 +36,32 @@ const static char * steamLibraries[] = { // order has to be the same as in GAMES_NAMES const static u_int32_t GAMES_APPIDS[] = { 489830, + 22330, + 377160 }; //the name of the game in the steamapps/common folder const static char * GAMES_NAMES[] = { "Skyrim Special Edition", + "Oblivion", + "Fallout 4" }; +/** + * @brief list all installed games and the paths to the game's files + * + * @param status pointer to a status variable that will be modified to EXIT_SUCCESS or EXIT_FAILURE + * @return GHashTable* a map appid(int) => path(char *) + */ + //TODO: flip the return value and parameter GHashTable* search_games(int * status); -int getGameIdFromAppId(u_int32_t id); + +/** + * @brief search the index of the game inside GAMES_NAMES or GAMES_APPIDS + * + * @param appid + * @return -1 in case of failure or the index of the game. + */ +int getGameIdFromAppId(u_int32_t appid); #endif