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 8726d5e..368af57 100644 --- a/src/fomod.h +++ b/src/fomod.h @@ -2,10 +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