Merged master into interface

This commit is contained in:
Sean Bogosavac
2022-10-04 11:56:07 +02:00
19 changed files with 302 additions and 130 deletions
+36
View File
@@ -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
+2 -2
View File
@@ -9,7 +9,6 @@ project(ModManager)
set(SOURCES set(SOURCES
src/main.c
src/steam.c src/steam.c
src/install.c src/install.c
src/overlayfs.c src/overlayfs.c
@@ -24,7 +23,8 @@ set(SOURCES
) )
# add the executable # add the executable
add_executable(ModManager ${SOURCES}) add_executable(ModManager src/main.c ${SOURCES})
add_compile_options(-Wall -Wextra -pedantic -Werror) add_compile_options(-Wall -Wextra -pedantic -Werror)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
+32 -1
View File
@@ -4,13 +4,44 @@
#ifndef __FILE_H__ #ifndef __FILE_H__
#define __FILE_H__ #define __FILE_H__
//valid copy flags
#define cp_DEFAULT 0
#define CP_LINK 1 #define CP_LINK 1
#define CP_RECURSIVE 2 #define CP_RECURSIVE 2
#define CP_NO_TARGET_DIR 4 #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); 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); int move(const char * source, const char * destination);
/**
* @brief Recursively rename all file and folder to lowercase.
*
* @param folder
*/
void casefold(const char * folder); void casefold(const char * folder);
#endif #endif
+74 -100
View File
@@ -1,4 +1,3 @@
#include "fomod.h"
#include <libxml/tree.h> #include <libxml/tree.h>
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/xmlstring.h> #include <libxml/xmlstring.h>
@@ -8,11 +7,12 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#include <glib.h>
#include <stdarg.h> #include <stdarg.h>
#include <unistd.h>
#include "fomod.h"
#include "file.h" #include "file.h"
#include "libxml/globals.h" #include "libxml/globals.h"
#include "fomod/parser.h"
int getInputCount(const char * input) { int getInputCount(const char * input) {
char buff[2]; char buff[2];
@@ -47,39 +47,6 @@ gint priorityCmp(gconstpointer a, gconstpointer b) {
return fileA->priority - fileB->priority; 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) { void printfOptionsInOrder(FOModGroup_t group) {
for(int i = 0; i < group.pluginCount; i++) { for(int i = 0; i < group.pluginCount; i++) {
printf("%d, %s\n", i, group.plugins[i].name); printf("%d, %s\n", i, group.plugins[i].name);
@@ -152,18 +119,75 @@ void sortGroup(FOModGroup_t * group) {
} }
} }
//TODO: support priority //TODO: handle error
int installFOMod(const char * modFolder, const char * destination) { int processFileOperations(GList * pendingFileOperations, const char * modFolder, const char * destination) {
char * fomodFolder = findFOModFolder(modFolder); pendingFileOperations = g_list_sort(pendingFileOperations, priorityCmp);
if(fomodFolder == NULL) { GList * currentFileOperation = pendingFileOperations;
fprintf(stderr, "Fomod folder not found, are you sure this is a fomod mod ?\n");
return EXIT_FAILURE;
}
char * fomodFile = findFOModFile(fomodFolder); while(currentFileOperation != NULL) {
if(fomodFile == 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"); fprintf(stderr, "FOMod file not found, are you sure this is a fomod mod ?\n");
g_free(fomodFolder); g_free(fomodFolder);
g_free(fomodFile);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -172,6 +196,7 @@ int installFOMod(const char * modFolder, const char * destination) {
if(returnValue != EXIT_SUCCESS) { if(returnValue != EXIT_SUCCESS) {
return returnValue; return returnValue;
} }
g_free(fomodFile);
GList * flagList = NULL; GList * flagList = NULL;
GList * pendingFileOperations = NULL; GList * pendingFileOperations = NULL;
@@ -179,7 +204,7 @@ int installFOMod(const char * modFolder, const char * destination) {
sortSteps(&fomod); sortSteps(&fomod);
for(int i = 0; i < fomod.stepCount; i++) { for(int i = 0; i < fomod.stepCount; i++) {
FOModStep_t * step = &fomod.steps[i]; const FOModStep_t * step = &fomod.steps[i];
bool validFlags = true; bool validFlags = true;
for(int flagId = 0; flagId < step->flagCount; flagId++) { 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"); printf("FOMod successfully installed!\n");
g_list_free(flagList); g_list_free(flagList);
g_list_free_full(pendingFileOperations, free); g_list_free_full(pendingFileOperations, free);
freeFOMod(&fomod); freeFOMod(&fomod);
g_free(fomodFolder);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
+32
View File
@@ -2,9 +2,41 @@
#define __FOMOD_H__ #define __FOMOD_H__
#include <stdbool.h> #include <stdbool.h>
#include <glib.h>
#include "fomod/parser.h"
#include "fomod/group.h" #include "fomod/group.h"
#include "fomod/xmlUtil.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); 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 #endif
+6 -3
View File
@@ -2,6 +2,7 @@
#include "libxml/tree.h" #include "libxml/tree.h"
#include "xmlUtil.h" #include "xmlUtil.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
//Maybe integrate this into the rest of the code instead of freeing after the fact //Maybe integrate this into the rest of the code instead of freeing after the fact
void freeFOMod(FOMod_t * fomod) { void freeFOMod(FOMod_t * fomod) {
@@ -21,11 +22,10 @@ void freeFOMod(FOMod_t * fomod) {
free(condFile->requiredFlags); free(condFile->requiredFlags);
} }
free(fomod->condFiles); free(fomod->condFiles);
free(fomod->moduleImage); free(fomod->moduleImage);
free(fomod->moduleName); free(fomod->moduleName);
int size = countUntilNull(fomod->requiredInstallFiles); int size = countUntilNull(fomod->requiredInstallFiles, sizeof(char **));
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
free(fomod->requiredInstallFiles[i]); free(fomod->requiredInstallFiles[i]);
} }
@@ -46,6 +46,9 @@ void freeFOMod(FOMod_t * fomod) {
free(step->requiredFlags); free(step->requiredFlags);
free(step->name); 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) { int parseVisibleNode(xmlNodePtr node, FOModStep_t * step) {
@@ -285,7 +288,7 @@ int parseFOMod(const char * fomodFile, FOMod_t* fomod) {
exit(EXIT_FAILURE); 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); fomod->requiredInstallFiles = realloc(fomod->requiredInstallFiles, sizeof(char *) * size);
//ensure it is null terminated //ensure it is null terminated
fomod->requiredInstallFiles[size - 1] = NULL; fomod->requiredInstallFiles[size - 1] = NULL;
+12
View File
@@ -25,7 +25,19 @@ typedef struct FOMod {
int condFilesCount; int condFilesCount;
} FOMod_t; } 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); int parseFOMod(const char * fomodFile, FOMod_t* fomod);
/**
* @brief Free content of a fomod file.
* @param fomod
*/
void freeFOMod(FOMod_t * fomod); void freeFOMod(FOMod_t * fomod);
#endif #endif
+2 -2
View File
@@ -27,10 +27,10 @@ void fixPath(char * path) {
} }
} }
int countUntilNull(void * pointers) { int countUntilNull(void * pointers, size_t typeSize) {
int i = 0; int i = 0;
while(pointers != NULL) { while(pointers != NULL) {
pointers++; pointers += typeSize;
i++; i++;
} }
return i; return i;
+16 -1
View File
@@ -8,9 +8,24 @@
typedef enum FOModOrder { ASC, DESC, ORD } FOModOrder_t; typedef enum FOModOrder { ASC, DESC, ORD } FOModOrder_t;
bool validateNode(xmlNodePtr * node, bool skipText, const char * names, ...); 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); char * freeAndDup(xmlChar * line);
FOModOrder_t getFOModOrder(const char * order); FOModOrder_t getFOModOrder(const char * order);
/**
* @brief replace / by \
* @param path
*/
void fixPath(char * 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 #endif
+7
View File
@@ -1 +1,8 @@
/**
* @brief Get the user home dir regardless if he used sudo.
*
* @return char* path to the home dir
*/
char * getHome(); char * getHome();
+9
View File
@@ -1,6 +1,15 @@
#ifndef __INSTALL_H__ #ifndef __INSTALL_H__
#define __INSTALL_H__ #define __INSTALL_H__
#include <stdlib.h>
#define INSTALLED_FLAG_FILE "__DO_NOT_REMOVE__" #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); int addMod(char * filePath, int appId);
#endif #endif
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef __MACRO_H__ #ifndef __MACRO_H__
#define __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]) #define LEN(array) sizeof(array) / sizeof(array[0])
#endif #endif
+31 -16
View File
@@ -64,15 +64,12 @@ int usage() {
printf("Use --deploy or -d <APPID> to deploy the mods for the game\n"); printf("Use --deploy or -d <APPID> to deploy the mods for the game\n");
printf("Use --unbind <APPID> to rollback a deployment\n"); printf("Use --unbind <APPID> to rollback a deployment\n");
printf("Use --fomod <APPID> <MODID> to create a new mod using the result from the FOMod\n"); printf("Use --fomod <APPID> <MODID> to create a new mod using the result from the FOMod\n");
//TODO: as bonus
//printf("Use --start-game <APPID> 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; return EXIT_FAILURE;
} }
int validateAppId(const char * appIdStr) { int validateAppId(const char * appIdStr) {
//strtoul set EINVAL(after C99) if the string is invalid //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) { if(errno == EINVAL) {
printf("Appid has to be a valid number\n"); printf("Appid has to be a valid number\n");
return -1; return -1;
@@ -89,7 +86,8 @@ int validateAppId(const char * appIdStr) {
return -1; return -1;
} }
return appid; //no valid appid goes far enough to justify long
return (int)appid;
} }
int listGames(int argc, char ** argv) { int listGames(int argc, char ** argv) {
@@ -100,7 +98,7 @@ int listGames(int argc, char ** argv) {
printf("No game found\n"); printf("No game found\n");
} else { } else {
while(gamesIds != NULL) { while(gamesIds != NULL) {
int * gameIndex = (int*)gamesIds->data; const int * gameIndex = (int*)gamesIds->data;
printf("%d: %s\n", GAMES_APPIDS[*gameIndex], GAMES_NAMES[*gameIndex]); printf("%d: %s\n", GAMES_APPIDS[*gameIndex], GAMES_NAMES[*gameIndex]);
gamesIds = g_list_next(gamesIds); gamesIds = g_list_next(gamesIds);
} }
@@ -111,9 +109,9 @@ int listGames(int argc, char ** argv) {
int add(int argc, char ** argv) { int add(int argc, char ** argv) {
if(argc != 4) return usage(); 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) { if(appid < 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -168,7 +166,7 @@ int listAllMods(int argc, char ** argv) {
int installAndUninstallMod(int argc, char ** argv, bool install) { int installAndUninstallMod(int argc, char ** argv, bool install) {
if(argc != 4) return usage(); if(argc != 4) return usage();
char * appIdStr = argv[2]; char * appIdStr = argv[2];
u_int32_t appid = validateAppId(appIdStr); int appid = validateAppId(appIdStr);
if(appid < 0) { if(appid < 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -176,7 +174,7 @@ int installAndUninstallMod(int argc, char ** argv, bool install) {
int returnValue = EXIT_SUCCESS; int returnValue = EXIT_SUCCESS;
//strtoul set EINVAL if the string is invalid //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) { if(errno == EINVAL) {
printf("ModId has to be a valid number\n"); printf("ModId has to be a valid number\n");
return -1; return -1;
@@ -185,6 +183,7 @@ int installAndUninstallMod(int argc, char ** argv, bool install) {
//might crash if no mods were installed //might crash if no mods were installed
char * home = getHome(); char * home = getHome();
char * modFolder = g_build_filename(home, MANAGER_FILES, MOD_FOLDER_NAME, appIdStr, NULL); char * modFolder = g_build_filename(home, MANAGER_FILES, MOD_FOLDER_NAME, appIdStr, NULL);
free(home);
GList * mods = listFilesInFolder(modFolder); GList * mods = listFilesInFolder(modFolder);
GList * modsFirstPointer = mods; GList * modsFirstPointer = mods;
@@ -208,9 +207,14 @@ int installAndUninstallMod(int argc, char ** argv, bool install) {
} }
//Create activated file //Create activated file
FILE * fd = fopen(modFlag, "w"); FILE * fd = fopen(modFlag, "w+");
fwrite("", 1, 1, fd); if(fd != NULL) {
fclose(fd); fwrite("", 1, 1, fd);
fclose(fd);
} else {
printf("Could not interact with the activation file\n");
returnValue = EXIT_FAILURE;
}
} else { } else {
if(access(modFlag, F_OK) != 0) { if(access(modFlag, F_OK) != 0) {
printf("The mod is not activated \n"); printf("The mod is not activated \n");
@@ -287,6 +291,8 @@ int deploy(int argc, char ** argv) {
free(modFlag); free(modFlag);
} }
g_free(modFolder);
//const char * data = "lowerdir=gameFolder,gameFolder2,gameFolder3..." //const char * data = "lowerdir=gameFolder,gameFolder2,gameFolder3..."
modsToInstall[modCount] = gameFolder; modsToInstall[modCount] = gameFolder;
modsToInstall[modCount + 1] = NULL; 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 * 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); char * gameWorkDir = g_build_filename(home, MANAGER_FILES, GAME_WORK_DIR_NAME, appIdStr, NULL);
free(home);
//unmount the game folder //unmount the game folder
//DETACH + FORCE allow us to be sure it will be unload. //DETACH + FORCE allow us to be sure it will be unload.
@@ -317,12 +324,16 @@ int deploy(int argc, char ** argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
g_free(steamGameFolder);
g_free(gameUpperDir);
g_free(gameWorkDir);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int setup(int argc, char ** argv) { int setup(int argc, char ** argv) {
if(argc != 3 ) return usage(); if(argc != 3 ) return usage();
char * appIdStr = argv[2]; const char * appIdStr = argv[2];
int appid = validateAppId(appIdStr); int appid = validateAppId(appIdStr);
if(appid < 0) { if(appid < 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
@@ -372,7 +383,7 @@ int setup(int argc, char ** argv) {
int unbind(int argc, char ** argv) { int unbind(int argc, char ** argv) {
if(argc != 3 ) return usage(); if(argc != 3 ) return usage();
char * appIdStr = argv[2]; const char * appIdStr = argv[2];
int appid = validateAppId(appIdStr); int appid = validateAppId(appIdStr);
if(appid < 0) { if(appid < 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
@@ -389,7 +400,7 @@ int unbind(int argc, char ** argv) {
int removeMod(int argc, char ** argv) { int removeMod(int argc, char ** argv) {
if(argc != 4) return usage(); if(argc != 4) return usage();
char * appIdStr = argv[2]; const char * appIdStr = argv[2];
int appid = validateAppId(appIdStr); int appid = validateAppId(appIdStr);
if(appid < 0) { if(appid < 0) {
printf("Invalid appid"); printf("Invalid appid");
@@ -424,6 +435,7 @@ int removeMod(int argc, char ** argv) {
delete(filename, true); delete(filename, true);
g_free(filename); g_free(filename);
g_free(modFolder);
g_list_free_full(modsFirstPointer, free); g_list_free_full(modsFirstPointer, free);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@@ -473,6 +485,9 @@ int fomod(int argc, char ** argv) {
free(destination); free(destination);
g_list_free_full(modsFirstPointer, free); g_list_free_full(modsFirstPointer, free);
g_free(modDestination);
g_free(modPath);
g_free(modFolder);
return returnValue; return returnValue;
} }
+3
View File
@@ -5,6 +5,9 @@
// in c "A" "B" is the same as "AB" // in c "A" "B" is the same as "AB"
#define MANAGER_FILES ".local/share/" APP_NAME #define MANAGER_FILES ".local/share/" APP_NAME
#define MOD_FOLDER_NAME "MOD_FOLDER" #define MOD_FOLDER_NAME "MOD_FOLDER"
//the folder in which the games file will be linked or copied
#define GAME_FOLDER_NAME "GAME_FOLDER" #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" #define GAME_UPPER_DIR_NAME "UPPER_DIRS"
//overlayfs temporary dir.
#define GAME_WORK_DIR_NAME "WORK_DIRS" #define GAME_WORK_DIR_NAME "WORK_DIRS"
-1
View File
@@ -96,6 +96,5 @@ void swapPlace(int appid, int modId, int modId2) {
GList * list = listMods(appid); GList * list = listMods(appid);
g_list_free(list); g_list_free(list);
} }
+9
View File
@@ -15,6 +15,15 @@
* @return GList of char containing the name of the mod folder in order * @return GList of char containing the name of the mod folder in order
*/ */
GList * listMods(int appid); 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); void swapPlace(int appid, int modId, int modId2);
#endif #endif
+9
View File
@@ -1,6 +1,15 @@
#ifndef __OVERLAY_H__ #ifndef __OVERLAY_H__
#define __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); int overlayMount(char ** sources, const char * dest, const char * upperdir, const char * workdir);
#endif #endif
+2 -2
View File
@@ -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++) { for(int k = 0; k < LEN(GAMES_APPIDS); k++) {
if(id == GAMES_APPIDS[k]) { if(appid == GAMES_APPIDS[k]) {
return k; return k;
} }
} }
+19 -1
View File
@@ -36,14 +36,32 @@ const static char * steamLibraries[] = {
// order has to be the same as in GAMES_NAMES // order has to be the same as in GAMES_NAMES
const static u_int32_t GAMES_APPIDS[] = { const static u_int32_t GAMES_APPIDS[] = {
489830, 489830,
22330,
377160
}; };
//the name of the game in the steamapps/common folder //the name of the game in the steamapps/common folder
const static char * GAMES_NAMES[] = { const static char * GAMES_NAMES[] = {
"Skyrim Special Edition", "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); 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 #endif