Debuggin the fomod feature & adding the framework for basic error handling in the fomod code.
Still need to do proper error handling but at least we can easly catch the errors.
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
1.
|
1.
|
||||||
only support betheshda game for now, i spent enough time codding this.
|
only support betheshda game for now, i spent enough time codding this.
|
||||||
2.
|
2.
|
||||||
try alternatives to overlayfs
|
try alternatives to overlayfs (searching for casefold support)
|
||||||
|
3.
|
||||||
|
adding a hook for %command% in steam ?
|
||||||
|
should be easy to find the appid id this way and deploy.
|
||||||
|
|||||||
+3
-1
@@ -14,6 +14,7 @@ u_int32_t countSetBits(u_int32_t n) {
|
|||||||
return (n & 1) + countSetBits(n >> 1);
|
return (n & 1) + countSetBits(n >> 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: add interruption support
|
||||||
//simplest way to copy a file in c(linux)
|
//simplest way to copy a file in c(linux)
|
||||||
int copy(const char * path, const char * dest, u_int32_t flags) {
|
int copy(const char * path, const char * dest, u_int32_t flags) {
|
||||||
int flagCount = countSetBits(flags);
|
int flagCount = countSetBits(flags);
|
||||||
@@ -23,7 +24,6 @@ int copy(const char * path, const char * dest, u_int32_t flags) {
|
|||||||
}
|
}
|
||||||
//flags + cp + path + dest
|
//flags + cp + path + dest
|
||||||
const char * args[flagCount + 4];
|
const char * args[flagCount + 4];
|
||||||
memset(args, 0, (flagCount + 4) * sizeof(char *));
|
|
||||||
args[0] = "/bin/cp";
|
args[0] = "/bin/cp";
|
||||||
args[1] = path;
|
args[1] = path;
|
||||||
args[2] = dest;
|
args[2] = dest;
|
||||||
@@ -42,6 +42,8 @@ int copy(const char * path, const char * dest, u_int32_t flags) {
|
|||||||
argIndex += 1;
|
argIndex += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args[argIndex] = NULL;
|
||||||
|
|
||||||
|
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if(pid == 0) {
|
if(pid == 0) {
|
||||||
|
|||||||
+250
-50
@@ -9,11 +9,22 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "libxml/globals.h"
|
#include "libxml/globals.h"
|
||||||
|
|
||||||
//TODO:cleanup prop
|
//TODO:cleanup prop
|
||||||
//and other strings
|
//and other strings
|
||||||
|
//TODO: protect every access to a node's child to avoid reading the wrong node
|
||||||
|
|
||||||
|
|
||||||
|
//replace \ in the path by /
|
||||||
|
void fixPath(char * path) {
|
||||||
|
while(*path != '\0') {
|
||||||
|
if(*path == '\\')*path = '/';
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int countUntilNull(void * pointers) {
|
int countUntilNull(void * pointers) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -41,12 +52,12 @@ GroupType_t getGroupType(const char * type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FOModOrder_t getFOModOrder(const char * order) {
|
FOModOrder_t getFOModOrder(const char * order) {
|
||||||
if(strcmp(order, "Explicit") == 0) {
|
if(order == NULL || strcmp(order, "Ascending") == 0) {
|
||||||
|
return ASC;
|
||||||
|
} else if(strcmp(order, "Explicit") == 0) {
|
||||||
return ORD;
|
return ORD;
|
||||||
} else if(strcmp(order, "Descending") == 0) {
|
} else if(strcmp(order, "Descending") == 0) {
|
||||||
return DESC;
|
return DESC;
|
||||||
} else if(strcmp(order, "Ascending") == 0) {
|
|
||||||
return ASC;
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -67,6 +78,44 @@ TypeDescriptor_t getDescriptor(const char * descriptor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//names cannot contain false
|
||||||
|
//need to be null terminated
|
||||||
|
bool validateNode(xmlNodePtr * node, bool skipText, const char * names, ...) {
|
||||||
|
va_list namesPtr;
|
||||||
|
|
||||||
|
while(*node != NULL && xmlStrcmp((*node)->name, (const xmlChar *)"text") == 0) {
|
||||||
|
if(skipText) {
|
||||||
|
(*node) = (*node)->next;
|
||||||
|
} else {
|
||||||
|
//could not skip and the node was a text node.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: chose a proper return value
|
||||||
|
if(*node == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(namesPtr, names);
|
||||||
|
|
||||||
|
const char * validName = names;
|
||||||
|
while(validName != NULL) {
|
||||||
|
if(xmlStrcmp((*node)->name, (const xmlChar *)validName) == 0) {
|
||||||
|
va_end(namesPtr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
validName = va_arg(namesPtr, char *);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(namesPtr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char * freeAndDup(xmlChar * line) {
|
char * freeAndDup(xmlChar * line) {
|
||||||
char * free = strdup((const char *) line);
|
char * free = strdup((const char *) line);
|
||||||
xmlFree(line);
|
xmlFree(line);
|
||||||
@@ -75,6 +124,14 @@ char * freeAndDup(xmlChar * line) {
|
|||||||
|
|
||||||
FOModGroup_t parseGroup(xmlNodePtr groupNode) {
|
FOModGroup_t parseGroup(xmlNodePtr groupNode) {
|
||||||
xmlNodePtr pluginsNode = groupNode->children;
|
xmlNodePtr pluginsNode = groupNode->children;
|
||||||
|
|
||||||
|
if(!validateNode(&pluginsNode, true, "plugins", NULL)) {
|
||||||
|
//TODO handle error;
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FOModGroup_t group;
|
FOModGroup_t group;
|
||||||
group.name = freeAndDup(xmlGetProp( groupNode, (const xmlChar *) "name"));
|
group.name = freeAndDup(xmlGetProp( groupNode, (const xmlChar *) "name"));
|
||||||
|
|
||||||
@@ -91,9 +148,20 @@ FOModGroup_t parseGroup(xmlNodePtr groupNode) {
|
|||||||
|
|
||||||
xmlNodePtr currentPlugin = pluginsNode->children;
|
xmlNodePtr currentPlugin = pluginsNode->children;
|
||||||
while(currentPlugin != NULL) {
|
while(currentPlugin != NULL) {
|
||||||
|
if(!validateNode(¤tPlugin, true, "plugin", NULL)) {
|
||||||
|
//TODO handle error;
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentPlugin == NULL)continue;
|
||||||
|
|
||||||
|
|
||||||
pluginCount += 1;
|
pluginCount += 1;
|
||||||
plugins = realloc(plugins, pluginCount * sizeof(FOModPlugin_t));
|
plugins = realloc(plugins, pluginCount * sizeof(FOModPlugin_t));
|
||||||
FOModPlugin_t * plugin = &plugins[pluginCount - 1];
|
FOModPlugin_t * plugin = &plugins[pluginCount - 1];
|
||||||
|
//initialise everything to 0 and null pointers
|
||||||
|
memset(plugin, 0, sizeof(FOModPlugin_t));
|
||||||
|
|
||||||
plugin->name = freeAndDup(xmlGetProp(currentPlugin, (const xmlChar *) "name"));
|
plugin->name = freeAndDup(xmlGetProp(currentPlugin, (const xmlChar *) "name"));
|
||||||
|
|
||||||
@@ -108,40 +176,71 @@ FOModGroup_t parseGroup(xmlNodePtr groupNode) {
|
|||||||
int flagCount = 0;
|
int flagCount = 0;
|
||||||
xmlNodePtr flagNode = nodeElement->children;
|
xmlNodePtr flagNode = nodeElement->children;
|
||||||
while(flagNode != NULL) {
|
while(flagNode != NULL) {
|
||||||
|
if(!validateNode(&flagNode, true, "flag", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(flagNode == NULL)continue;
|
||||||
|
|
||||||
flagCount += 1;
|
flagCount += 1;
|
||||||
flags = realloc(flags, flagCount * sizeof(FOModFlag_t));
|
flags = realloc(flags, flagCount * sizeof(FOModFlag_t));
|
||||||
|
|
||||||
flags[flagCount - 1].name = freeAndDup(xmlGetProp(nodeElement, (const xmlChar *) "name"));
|
flags[flagCount - 1].name = freeAndDup(xmlGetProp(flagNode, (const xmlChar *) "name"));
|
||||||
flags[flagCount - 1].value = freeAndDup(xmlNodeGetContent(nodeElement));
|
flags[flagCount - 1].value = freeAndDup(xmlNodeGetContent(flagNode));
|
||||||
|
|
||||||
flagNode = flagNode->next;
|
flagNode = flagNode->next;
|
||||||
}
|
}
|
||||||
plugin->flags = flags;
|
plugin->flags = flags;
|
||||||
|
plugin->flagCount = flagCount;
|
||||||
} else if(xmlStrcmp(nodeElement->name, (const xmlChar *) "files") == 0) {
|
} else if(xmlStrcmp(nodeElement->name, (const xmlChar *) "files") == 0) {
|
||||||
FOModFile_t * files = NULL;
|
FOModFile_t * files = NULL;
|
||||||
int filesCount = 0;
|
int filesCount = 0;
|
||||||
xmlNodePtr flagNode = nodeElement->children;
|
xmlNodePtr fileNode = nodeElement->children;
|
||||||
while(flagNode != NULL) {
|
while(fileNode != NULL) {
|
||||||
|
if(!validateNode(&fileNode, true, "folder", "file", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fileNode == NULL)continue;
|
||||||
|
|
||||||
|
|
||||||
filesCount += 1;
|
filesCount += 1;
|
||||||
|
|
||||||
files = realloc(files, (filesCount + 1) * sizeof(FOModFile_t));
|
files = realloc(files, (filesCount + 1) * sizeof(FOModFile_t));
|
||||||
files[filesCount - 1].destination = freeAndDup(xmlGetProp(nodeElement, (const xmlChar *) "destination"));
|
files[filesCount - 1].destination = freeAndDup(xmlGetProp(fileNode, (const xmlChar *) "destination"));
|
||||||
files[filesCount - 1].source = freeAndDup(xmlGetProp(nodeElement, (const xmlChar *) "source"));
|
files[filesCount - 1].source = freeAndDup(xmlGetProp(fileNode, (const xmlChar *) "source"));
|
||||||
//TODO: test if it's a number
|
//TODO: test if it's a number
|
||||||
//TODO: test if props is present and default to 0
|
//TODO: test if props is present and default to 0
|
||||||
xmlChar * priority = xmlGetProp(nodeElement, (const xmlChar *) "priority");
|
xmlChar * priority = xmlGetProp(fileNode, (const xmlChar *) "priority");
|
||||||
|
if(priority == NULL) {
|
||||||
|
files[filesCount - 1].priority = 0;
|
||||||
|
} else {
|
||||||
files[filesCount - 1].priority = atoi((char *)priority);
|
files[filesCount - 1].priority = atoi((char *)priority);
|
||||||
|
}
|
||||||
xmlFree(priority);
|
xmlFree(priority);
|
||||||
files[filesCount - 1].isFolder = xmlStrcmp(nodeElement->name, (const xmlChar *) "folder") == 0;
|
files[filesCount - 1].isFolder = xmlStrcmp(fileNode->name, (const xmlChar *) "folder") == 0;
|
||||||
|
|
||||||
flagNode = flagNode->next;
|
fileNode = fileNode->next;
|
||||||
}
|
}
|
||||||
plugin->files = files;
|
plugin->files = files;
|
||||||
|
plugin->fileCount = filesCount;
|
||||||
} else if(xmlStrcmp(nodeElement->name, (const xmlChar *) "typeDescriptor") == 0) {
|
} else if(xmlStrcmp(nodeElement->name, (const xmlChar *) "typeDescriptor") == 0) {
|
||||||
xmlChar * name = xmlGetProp(nodeElement->children, (const xmlChar *) "name");
|
xmlNodePtr typeNode = nodeElement->children;
|
||||||
|
if(!validateNode(&typeNode, true, "type", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
xmlChar * name = xmlGetProp(typeNode, (const xmlChar *) "name");
|
||||||
plugin->type = getDescriptor((char *) name);
|
plugin->type = getDescriptor((char *) name);
|
||||||
xmlFree(name);
|
xmlFree(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeElement = nodeElement->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -159,7 +258,16 @@ FOModStep_t * parseInstallSteps(xmlNodePtr installStepsNode, int * stepCount) {
|
|||||||
|
|
||||||
xmlNodePtr stepNode = installStepsNode->children;
|
xmlNodePtr stepNode = installStepsNode->children;
|
||||||
while(stepNode != NULL) {
|
while(stepNode != NULL) {
|
||||||
stepCount += 1;
|
//skipping the text node
|
||||||
|
if(!validateNode(&stepNode, true, "installStep", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stepNode == NULL)break;
|
||||||
|
|
||||||
|
*stepCount += 1;
|
||||||
steps = realloc(steps, *stepCount * sizeof(FOModStep_t));
|
steps = realloc(steps, *stepCount * sizeof(FOModStep_t));
|
||||||
|
|
||||||
FOModStep_t * step = &steps[*stepCount - 1];
|
FOModStep_t * step = &steps[*stepCount - 1];
|
||||||
@@ -167,6 +275,7 @@ FOModStep_t * parseInstallSteps(xmlNodePtr installStepsNode, int * stepCount) {
|
|||||||
step->requiredFlags = NULL;
|
step->requiredFlags = NULL;
|
||||||
step->flagCount = 0;
|
step->flagCount = 0;
|
||||||
step->groupCount = 0;
|
step->groupCount = 0;
|
||||||
|
step->groups = NULL;
|
||||||
|
|
||||||
xmlNodePtr stepchildren = stepNode->children;
|
xmlNodePtr stepchildren = stepNode->children;
|
||||||
|
|
||||||
@@ -175,6 +284,15 @@ FOModStep_t * parseInstallSteps(xmlNodePtr installStepsNode, int * stepCount) {
|
|||||||
xmlNodePtr requiredFlagsNode = stepchildren->children;
|
xmlNodePtr requiredFlagsNode = stepchildren->children;
|
||||||
|
|
||||||
while (requiredFlagsNode != NULL) {
|
while (requiredFlagsNode != NULL) {
|
||||||
|
|
||||||
|
if(!validateNode(&requiredFlagsNode, true, "flagDependency", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(requiredFlagsNode == NULL)break;
|
||||||
|
|
||||||
step->flagCount += 1;
|
step->flagCount += 1;
|
||||||
step->requiredFlags = realloc(step->requiredFlags, step->flagCount * sizeof(FOModFlag_t));
|
step->requiredFlags = realloc(step->requiredFlags, step->flagCount * sizeof(FOModFlag_t));
|
||||||
FOModFlag_t * flag = &(step->requiredFlags[step->flagCount - 1]);
|
FOModFlag_t * flag = &(step->requiredFlags[step->flagCount - 1]);
|
||||||
@@ -185,14 +303,26 @@ FOModStep_t * parseInstallSteps(xmlNodePtr installStepsNode, int * stepCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if(xmlStrcmp(stepchildren->name, (const xmlChar *) "optionalFileGroups") == 0) {
|
} else if(xmlStrcmp(stepchildren->name, (const xmlChar *) "optionalFileGroups") == 0) {
|
||||||
if(stepchildren != NULL) {
|
|
||||||
xmlChar * optionOrder = xmlGetProp(stepchildren, (const xmlChar *)"order");
|
xmlChar * optionOrder = xmlGetProp(stepchildren, (const xmlChar *)"order");
|
||||||
step->optionOrder = getFOModOrder((char *)optionOrder);
|
step->optionOrder = getFOModOrder((char *)optionOrder);
|
||||||
xmlFree(optionOrder);
|
xmlFree(optionOrder);
|
||||||
|
//skipping the text node;
|
||||||
xmlNodePtr group = stepchildren->children;
|
xmlNodePtr group = stepchildren->children;
|
||||||
|
while(group != NULL) {
|
||||||
|
if(!validateNode(&group, true, "group", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(group == NULL)break;
|
||||||
|
|
||||||
step->groupCount += 1;
|
step->groupCount += 1;
|
||||||
step->groups = realloc(step->groups, step->groupCount * sizeof(FOModGroup_t));
|
step->groups = realloc(step->groups, step->groupCount * sizeof(FOModGroup_t));
|
||||||
step->groups[step->groupCount - 1] = parseGroup(group);
|
step->groups[step->groupCount - 1] = parseGroup(group);
|
||||||
|
|
||||||
|
group = group->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +336,7 @@ FOModStep_t * parseInstallSteps(xmlNodePtr installStepsNode, int * stepCount) {
|
|||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
int parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlNodePtr cur;
|
xmlNodePtr cur;
|
||||||
|
|
||||||
@@ -222,8 +352,8 @@ void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
|||||||
doc = xmlParseFile(fomodFile);
|
doc = xmlParseFile(fomodFile);
|
||||||
|
|
||||||
if(doc == NULL) {
|
if(doc == NULL) {
|
||||||
fprintf(stderr, "Document not parsed successfully");
|
fprintf(stderr, "Document is not a valid xml file\n");
|
||||||
return;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -231,11 +361,12 @@ void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
|||||||
if(cur == NULL) {
|
if(cur == NULL) {
|
||||||
fprintf(stderr, "emptyDocument");
|
fprintf(stderr, "emptyDocument");
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
return;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xmlStrcmp(cur->name, (const xmlChar *) "config") == 0) {
|
if(xmlStrcmp(cur->name, (const xmlChar *) "config") != 0) {
|
||||||
fprintf(stderr, "document of the wrong type, root node != config");
|
fprintf(stderr, "document of the wrong type, root node is '%s' instead of config\n", cur->name);
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = cur->children;
|
cur = cur->children;
|
||||||
@@ -249,15 +380,17 @@ void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
|||||||
//TODO: support non empty destination.
|
//TODO: support non empty destination.
|
||||||
xmlNodePtr requiredInstallFile = cur->children;
|
xmlNodePtr requiredInstallFile = cur->children;
|
||||||
while(requiredInstallFile != NULL) {
|
while(requiredInstallFile != NULL) {
|
||||||
|
if(validateNode(&requiredInstallFile, true, "folder", "file", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
int size = countUntilNull(fomod->requiredInstallFiles) + 2;
|
int size = countUntilNull(fomod->requiredInstallFiles) + 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;
|
||||||
|
fomod->requiredInstallFiles[size - 2] = freeAndDup(xmlGetProp(requiredInstallFile, (const xmlChar *)"source"));
|
||||||
//we remove all link with libxml2
|
|
||||||
xmlChar * source = xmlGetProp(requiredInstallFile, (const xmlChar *)"source");
|
|
||||||
fomod->requiredInstallFiles[size - 2] = strdup((const char *)source);
|
|
||||||
xmlFree(source);
|
|
||||||
|
|
||||||
requiredInstallFile = cur->children;
|
requiredInstallFile = cur->children;
|
||||||
}
|
}
|
||||||
@@ -269,9 +402,11 @@ void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
|||||||
int stepCount = 0;
|
int stepCount = 0;
|
||||||
FOModStep_t * steps = parseInstallSteps(cur, &stepCount);
|
FOModStep_t * steps = parseInstallSteps(cur, &stepCount);
|
||||||
|
|
||||||
if(fomod->steps == NULL) {
|
if(steps == NULL) {
|
||||||
//TODO: manage the error
|
fprintf(stderr, "Failed to parse the install steps\n");
|
||||||
exit(1);
|
|
||||||
|
//TODO: manage the error properly
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fomod->steps = steps;
|
fomod->steps = steps;
|
||||||
@@ -279,11 +414,21 @@ void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
|||||||
} else if(xmlStrcmp(cur->name, (const xmlChar *) "conditionalFileInstalls") == 0) {
|
} else if(xmlStrcmp(cur->name, (const xmlChar *) "conditionalFileInstalls") == 0) {
|
||||||
xmlNodePtr patterns = cur->children;
|
xmlNodePtr patterns = cur->children;
|
||||||
if(patterns != NULL) {
|
if(patterns != NULL) {
|
||||||
|
if(!validateNode(&patterns, true, "patterns", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
xmlNodePtr currentPattern = patterns->children;
|
xmlNodePtr currentPattern = patterns->children;
|
||||||
|
|
||||||
while(currentPattern != NULL) {
|
while(currentPattern != NULL) {
|
||||||
xmlNodePtr patternChild = currentPattern->children;
|
xmlNodePtr patternChild = currentPattern->children;
|
||||||
|
|
||||||
|
if(!validateNode(&patternChild, true, "pattern", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
while(patternChild != NULL) {
|
while(patternChild != NULL) {
|
||||||
fomod->condFilesCount += 1;
|
fomod->condFilesCount += 1;
|
||||||
fomod->condFiles = realloc(fomod->condFiles, fomod->condFilesCount * sizeof(FOModCondFile_t));
|
fomod->condFiles = realloc(fomod->condFiles, fomod->condFilesCount * sizeof(FOModCondFile_t));
|
||||||
@@ -297,6 +442,12 @@ void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
|||||||
if(xmlStrcmp(patternChild->name, (xmlChar *)"dependencies") == 0) {
|
if(xmlStrcmp(patternChild->name, (xmlChar *)"dependencies") == 0) {
|
||||||
xmlNodePtr flagNode = patternChild->children;
|
xmlNodePtr flagNode = patternChild->children;
|
||||||
|
|
||||||
|
if(!validateNode(&flagNode, true, "flagDependency", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
while(flagNode != NULL) {
|
while(flagNode != NULL) {
|
||||||
condFile->flagCount += 1;
|
condFile->flagCount += 1;
|
||||||
condFile->requiredFlags = realloc(condFile->requiredFlags, condFile->flagCount * sizeof(FOModFlag_t));
|
condFile->requiredFlags = realloc(condFile->requiredFlags, condFile->flagCount * sizeof(FOModFlag_t));
|
||||||
@@ -311,7 +462,14 @@ void parseFOMod(const char * fomodFile, FOMod_t* fomod) {
|
|||||||
} else if(xmlStrcmp(patternChild->name, (xmlChar *)"files") == 0) {
|
} else if(xmlStrcmp(patternChild->name, (xmlChar *)"files") == 0) {
|
||||||
xmlNodePtr filesNode = patternChild->children;
|
xmlNodePtr filesNode = patternChild->children;
|
||||||
|
|
||||||
|
|
||||||
while(filesNode != NULL) {
|
while(filesNode != NULL) {
|
||||||
|
if(!validateNode(&filesNode, true, "folder", "file", NULL)) {
|
||||||
|
//TODO: handle error
|
||||||
|
printf("%d\n", __LINE__);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
condFile->fileCount += 1;
|
condFile->fileCount += 1;
|
||||||
condFile->files = realloc(condFile->files, condFile->fileCount * sizeof(FOModFile_t));
|
condFile->files = realloc(condFile->files, condFile->fileCount * sizeof(FOModFile_t));
|
||||||
FOModFile_t * flag = &(condFile->files[condFile->fileCount - 1]);
|
FOModFile_t * flag = &(condFile->files[condFile->fileCount - 1]);
|
||||||
@@ -340,12 +498,18 @@ int getInputCount(const char * input) {
|
|||||||
buff[1] = '\0';
|
buff[1] = '\0';
|
||||||
|
|
||||||
int elementCount = 0;
|
int elementCount = 0;
|
||||||
|
bool prevWasValue = false;
|
||||||
|
|
||||||
for(int i = 0; input[i] != '\0'; i++) {
|
for(int i = 0; input[i] != '\0' && input[i] != '\n'; i++) {
|
||||||
buff[0] = input[i];
|
buff[0] = input[i];
|
||||||
|
|
||||||
//if the character is a valid character
|
//if the character is a valid character
|
||||||
if(strstr("0123456789 ", buff) != NULL) {
|
if(strstr("0123456789 ", buff) != NULL) {
|
||||||
if(input[i] == ' ') elementCount += 1;
|
if(input[i] == ' ') prevWasValue = false;
|
||||||
|
else if(!prevWasValue) {
|
||||||
|
prevWasValue = true;
|
||||||
|
elementCount++;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -361,7 +525,7 @@ char * findFOModFolder(const char * modFolder) {
|
|||||||
if (d) {
|
if (d) {
|
||||||
while ((dir = readdir(d)) != NULL) {
|
while ((dir = readdir(d)) != NULL) {
|
||||||
if(g_ascii_strcasecmp(dir->d_name, "fomod") == 0) {
|
if(g_ascii_strcasecmp(dir->d_name, "fomod") == 0) {
|
||||||
char * fomodDir = g_build_path(modFolder, dir->d_name, NULL);
|
char * fomodDir = g_build_path("/", modFolder, dir->d_name, NULL);
|
||||||
closedir(d);
|
closedir(d);
|
||||||
return fomodDir;
|
return fomodDir;
|
||||||
}
|
}
|
||||||
@@ -471,14 +635,28 @@ void freeFOMod(FOMod_t * fomod) {
|
|||||||
|
|
||||||
//TODO: support order parameters
|
//TODO: support order parameters
|
||||||
//TODO: support priority
|
//TODO: support priority
|
||||||
void installFOMod(const char * modFolder, const char * destination) {
|
//TODO: error support
|
||||||
|
int installFOMod(const char * modFolder, const char * destination) {
|
||||||
char * fomodFolder = findFOModFolder(modFolder);
|
char * fomodFolder = findFOModFolder(modFolder);
|
||||||
|
if(fomodFolder == NULL) {
|
||||||
|
fprintf(stderr, "Fomod folder not found, are you sure this is a fomod mod ?\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
char * fomodFile = findFOModFile(fomodFolder);
|
char * fomodFile = findFOModFile(fomodFolder);
|
||||||
|
if(fomodFile == NULL) {
|
||||||
|
fprintf(stderr, "Fomod file not found, are you sure this is a fomod mod ?\n");
|
||||||
|
g_free(fomodFolder);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
FOMod_t fomod;
|
FOMod_t fomod;
|
||||||
parseFOMod(fomodFile, &fomod);
|
int returnValue = parseFOMod(fomodFile, &fomod);
|
||||||
|
if(returnValue != EXIT_SUCCESS) {
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
GList * flagList = g_list_alloc();
|
GList * flagList = NULL;
|
||||||
|
|
||||||
for(int i = 0; i < fomod.stepCount; i++) {
|
for(int i = 0; i < fomod.stepCount; i++) {
|
||||||
FOModStep_t * step = &fomod.steps[i];
|
FOModStep_t * step = &fomod.steps[i];
|
||||||
@@ -497,10 +675,12 @@ void installFOMod(const char * modFolder, const char * destination) {
|
|||||||
for(int groupId = 0; groupId < step->groupCount; groupId++ ) {
|
for(int groupId = 0; groupId < step->groupCount; groupId++ ) {
|
||||||
FOModGroup_t group = step->groups[groupId];
|
FOModGroup_t group = step->groups[groupId];
|
||||||
|
|
||||||
int min;
|
u_int8_t min;
|
||||||
int max;
|
u_int8_t max;
|
||||||
int inputCount = 0;
|
int inputCount = 0;
|
||||||
char *inputBuffer = NULL;
|
char *inputBuffer = NULL;
|
||||||
|
size_t bufferSize = 0;
|
||||||
|
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
printfOptionsInOrder(group);
|
printfOptionsInOrder(group);
|
||||||
@@ -537,13 +717,16 @@ void installFOMod(const char * modFolder, const char * destination) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(scanf( "%ms", &inputBuffer) == 1) {
|
|
||||||
|
if(getline(&inputBuffer, &bufferSize, stdin) > 0) {
|
||||||
inputCount = getInputCount(inputBuffer);
|
inputCount = getInputCount(inputBuffer);
|
||||||
if(inputCount <= max && inputCount >= min) {
|
if(inputCount <= max && inputCount >= min) {
|
||||||
|
printf("Continuing\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Invalid input");
|
fprintf(stderr, "Invalid input\n");
|
||||||
free(inputBuffer);
|
if(inputBuffer != NULL)free(inputBuffer);
|
||||||
|
inputBuffer = NULL;
|
||||||
} else {
|
} else {
|
||||||
//TODO: handle error
|
//TODO: handle error
|
||||||
}
|
}
|
||||||
@@ -551,6 +734,7 @@ void installFOMod(const char * modFolder, const char * destination) {
|
|||||||
|
|
||||||
GRegex* regex = g_regex_new("\\s*", 0, 0, NULL);
|
GRegex* regex = g_regex_new("\\s*", 0, 0, NULL);
|
||||||
char ** choices = g_regex_split(regex, inputBuffer, 0);
|
char ** choices = g_regex_split(regex, inputBuffer, 0);
|
||||||
|
g_regex_unref(regex);
|
||||||
|
|
||||||
for(int choiceId = 0; choices[choiceId] != NULL; choiceId++) {
|
for(int choiceId = 0; choices[choiceId] != NULL; choiceId++) {
|
||||||
int choice = atoi(choices[choiceId]);
|
int choice = atoi(choices[choiceId]);
|
||||||
@@ -564,19 +748,27 @@ void installFOMod(const char * modFolder, const char * destination) {
|
|||||||
FOModFile_t * file = &plugin.files[i];
|
FOModFile_t * file = &plugin.files[i];
|
||||||
|
|
||||||
//TODO: support file->destination
|
//TODO: support file->destination
|
||||||
//using link to save disk space.
|
|
||||||
//TODO: check for copy success
|
//TODO: check for copy success
|
||||||
|
//no using link since priority is made to override files and link is annoying to deal with when overriding files.
|
||||||
|
char * source = (char *) g_build_path("/", modFolder, file->source, NULL);
|
||||||
|
fixPath(source);
|
||||||
|
int returnValue = EXIT_SUCCESS;
|
||||||
if(file->isFolder) {
|
if(file->isFolder) {
|
||||||
copy(file->source, destination, CP_NO_TARGET_DIR | CP_RECURSIVE | CP_LINK);
|
returnValue = copy(source, destination, CP_NO_TARGET_DIR | CP_RECURSIVE);
|
||||||
} else {
|
} else {
|
||||||
copy(file->source, destination, CP_LINK);
|
returnValue = copy(source, destination, 0);
|
||||||
|
}
|
||||||
|
printf("source: %s, destination: %s\n", source, destination);
|
||||||
|
g_free(source);
|
||||||
|
if(returnValue != EXIT_SUCCESS) {
|
||||||
|
fprintf(stderr, "Copy failed, some file might be corrupted\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_strfreev(choices);
|
g_strfreev(choices);
|
||||||
g_regex_unref(regex);
|
if(inputBuffer != NULL)free(inputBuffer);
|
||||||
free(inputBuffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,15 +791,23 @@ void installFOMod(const char * modFolder, const char * destination) {
|
|||||||
FOModFile_t * file = &(condfile->files[fileId]);
|
FOModFile_t * file = &(condfile->files[fileId]);
|
||||||
//TODO: support destination
|
//TODO: support destination
|
||||||
//TODO: handle error
|
//TODO: handle error
|
||||||
|
char * source = (char *) g_build_path("/", modFolder, file->source, NULL);
|
||||||
|
fixPath(source);
|
||||||
|
int returnValue;
|
||||||
if(file->isFolder) {
|
if(file->isFolder) {
|
||||||
copy(file->source, destination, CP_NO_TARGET_DIR | CP_RECURSIVE | CP_LINK);
|
returnValue = copy(source, destination, CP_NO_TARGET_DIR | CP_RECURSIVE | CP_LINK);
|
||||||
} else {
|
} else {
|
||||||
copy(file->source, destination, CP_LINK);
|
returnValue = copy(source, destination, CP_LINK);
|
||||||
}
|
}
|
||||||
|
if(returnValue != EXIT_SUCCESS) {
|
||||||
|
fprintf(stderr, "Copy failed, some file might be corrupted\n");
|
||||||
|
}
|
||||||
|
printf("source: %s, destination: %s\n", source, destination);
|
||||||
|
g_free(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("FOMod successfully installed!\n");
|
||||||
g_list_free(flagList);
|
g_list_free(flagList);
|
||||||
freeFOMod(&fomod);
|
freeFOMod(&fomod);
|
||||||
//TODO: properly free
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -67,6 +67,6 @@ typedef struct FOMod {
|
|||||||
int condFilesCount;
|
int condFilesCount;
|
||||||
} FOMod_t;
|
} FOMod_t;
|
||||||
|
|
||||||
void freeFOMod(FOMod_t * fomod);
|
int installFOMod(const char * modFolder, const char * destination);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+7
-11
@@ -42,7 +42,7 @@ int un7z(const char * path, const char * outdir) {
|
|||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * extractLastPart(const char * filePath, const char delimeter) {
|
const char * extractLastPart(const char * filePath, const char delimeter) {
|
||||||
int length = strlen(filePath);
|
int length = strlen(filePath);
|
||||||
int index = -1;
|
int index = -1;
|
||||||
for(int i= length -1; i >= 0; i--) {
|
for(int i= length -1; i >= 0; i--) {
|
||||||
@@ -53,16 +53,14 @@ char * extractLastPart(const char * filePath, const char delimeter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(index <= 0 || index == length) return NULL;
|
if(index <= 0 || index == length) return NULL;
|
||||||
char * extension = malloc((length - index) * sizeof(char));
|
return &filePath[index];
|
||||||
memcpy(extension, &filePath[index], (length - index));
|
|
||||||
return extension;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char * extractExtension(const char * filePath) {
|
const char * extractExtension(const char * filePath) {
|
||||||
return extractLastPart(filePath, '.');
|
return extractLastPart(filePath, '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
char * extractFileName(const char * filePath) {
|
const char * extractFileName(const char * filePath) {
|
||||||
return extractLastPart(filePath, '/');
|
return extractLastPart(filePath, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,13 +81,12 @@ int addMod(const char * filePath, int appId) {
|
|||||||
goto exit2;
|
goto exit2;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * filename = extractFileName(filePath);
|
const char * filename = extractFileName(filePath);
|
||||||
char * extension = extractExtension(filename);
|
const char * extension = extractExtension(filename);
|
||||||
char * lowercaseExtension = g_ascii_strdown(extension, -1);
|
char * lowercaseExtension = g_ascii_strdown(extension, -1);
|
||||||
free(extension);
|
|
||||||
|
|
||||||
char appIdStr[20];
|
char appIdStr[20];
|
||||||
|
sprintf(appIdStr, "%d", appId);
|
||||||
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);
|
g_mkdir_with_parents(outdir, 0755);
|
||||||
@@ -108,7 +105,6 @@ int addMod(const char * filePath, int appId) {
|
|||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
|
|
||||||
free(lowercaseExtension);
|
free(lowercaseExtension);
|
||||||
free(filename);
|
|
||||||
free(outdir);
|
free(outdir);
|
||||||
exit2:
|
exit2:
|
||||||
free(configFolder);
|
free(configFolder);
|
||||||
|
|||||||
+63
-4
@@ -15,6 +15,7 @@
|
|||||||
#include "steam.h"
|
#include "steam.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "fomod.h"
|
||||||
|
|
||||||
GHashTable * gamePaths;
|
GHashTable * gamePaths;
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ int usage() {
|
|||||||
printf("Use --remove or -r <APPID> <MODID> to remove a mod from a game\n");
|
printf("Use --remove or -r <APPID> <MODID> to remove a mod from a game\n");
|
||||||
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 or -u <APPID> to rollback a deployment\n");
|
printf("Use --unbind or -u <APPID> to rollback a deployment\n");
|
||||||
|
printf("Use --fomod <APPID> <MODID> to create a new mod using the result from the FOMod\n");
|
||||||
//TODO: as bonus
|
//TODO: as bonus
|
||||||
//printf("Use --start-game <APPID> to deploy the mods and launch the game through steam\n");
|
//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");
|
//printf("Use --steam in team cmdline options to deploy directly on game startup\n");
|
||||||
@@ -124,7 +126,9 @@ int listMods(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//might crash if no mods were installed
|
//might crash if no mods were installed
|
||||||
char * modFolder = g_build_filename(getenv("HOME"), MANAGER_FILES, MOD_FOLDER_NAME, appIdStr, NULL);
|
char * home = getHome();
|
||||||
|
char * modFolder = g_build_filename(home, MANAGER_FILES, MOD_FOLDER_NAME, appIdStr, NULL);
|
||||||
|
free(home);
|
||||||
GList * mods = listFilesInFolder(modFolder);
|
GList * mods = listFilesInFolder(modFolder);
|
||||||
unsigned short index = 0;
|
unsigned short index = 0;
|
||||||
|
|
||||||
@@ -165,15 +169,16 @@ int installAndRemoveMod(int argc, char ** argv, bool install) {
|
|||||||
|
|
||||||
int returnValue = EXIT_SUCCESS;
|
int returnValue = EXIT_SUCCESS;
|
||||||
|
|
||||||
//strtoul set EINVAL(after C99) if the string is invalid
|
//strtoul set EINVAL if the string is invalid
|
||||||
u_int32_t modId = strtoul(argv[3], NULL, 10);
|
u_int32_t modId = strtoul(argv[3], NULL, 10);
|
||||||
if(errno == EINVAL) {
|
if(errno == EINVAL) {
|
||||||
printf("Appid has to be a valid number\n");
|
printf("ModId has to be a valid number\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//might crash if no mods were installed
|
//might crash if no mods were installed
|
||||||
char * modFolder = g_build_filename(getenv("HOME"), MANAGER_FILES, MOD_FOLDER_NAME, appIdStr, NULL);
|
char * home = getHome();
|
||||||
|
char * modFolder = g_build_filename(home, MANAGER_FILES, MOD_FOLDER_NAME, appIdStr, NULL);
|
||||||
GList * mods = listFilesInFolder(modFolder);
|
GList * mods = listFilesInFolder(modFolder);
|
||||||
GList * modsFirstPointer = mods;
|
GList * modsFirstPointer = mods;
|
||||||
|
|
||||||
@@ -366,6 +371,54 @@ int unbind(int argc, char ** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fomod(int argc, char ** argv) {
|
||||||
|
if(argc != 4) return usage();
|
||||||
|
char * appIdStr = argv[2];
|
||||||
|
u_int32_t appid = validateAppId(appIdStr);
|
||||||
|
if(appid < 0) {
|
||||||
|
printf("Invalid appid");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//strtoul set EINVAL if the string is invalid
|
||||||
|
u_int32_t modId = strtoul(argv[3], NULL, 10);
|
||||||
|
if(errno == EINVAL) {
|
||||||
|
printf("Modid has to be a valid number\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
for(int i = 0; i < modId; i++) {
|
||||||
|
mods = g_list_next(mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mods == NULL) {
|
||||||
|
printf("Mod not found\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * destination = g_strconcat(mods->data, "__FOMOD", NULL);
|
||||||
|
|
||||||
|
if(access(destination, F_OK) == 0) {
|
||||||
|
delete(destination, true);
|
||||||
|
}
|
||||||
|
char * modDestination = g_build_filename(modFolder, destination, NULL);
|
||||||
|
char * modPath = g_build_filename(modFolder, mods->data, NULL);
|
||||||
|
|
||||||
|
//TODO: add error handling
|
||||||
|
int returnValue = installFOMod(modPath, modDestination);
|
||||||
|
|
||||||
|
free(destination);
|
||||||
|
g_list_free_full(modsFirstPointer, free);
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
if(argc < 2 ) return usage();
|
if(argc < 2 ) return usage();
|
||||||
|
|
||||||
@@ -459,6 +512,12 @@ int main(int argc, char ** argv) {
|
|||||||
returnValue = noRoot();
|
returnValue = noRoot();
|
||||||
else
|
else
|
||||||
returnValue = setup(argc, argv);
|
returnValue = setup(argc, argv);
|
||||||
|
} else if(strcmp(argv[1], "--fomod") == 0){
|
||||||
|
if(isRoot())
|
||||||
|
returnValue = noRoot();
|
||||||
|
else
|
||||||
|
returnValue = fomod(argc, argv);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
usage();
|
usage();
|
||||||
returnValue = EXIT_FAILURE;
|
returnValue = EXIT_FAILURE;
|
||||||
|
|||||||
Reference in New Issue
Block a user