Improved safety and reliability of the --add option
This commit is contained in:
@@ -30,13 +30,6 @@ Use --fomod <APPID> <MODID> to create a new mod using the result from the FOMod
|
||||
* Fuse (2 or 3)
|
||||
* Fuse-overlayfs
|
||||
|
||||
## instructions and warnings about casefold:
|
||||
Casefold is and options in some linux filesystem that will make a folder (not the whole filesystem) case insensitive, this is really good for proton since it gives a small file lookup performance boost and allow us to install mods without fearing having two file with the same name.
|
||||
|
||||
sadly i don't think overlayfs support it, but it might still be worth a try. currently i haven't tested without casefold and mods will probably break because of that.
|
||||
|
||||
|
||||
|
||||
## TODO:
|
||||
1. we need a name for this.
|
||||
2. allow to change mod priority.
|
||||
|
||||
+37
-1
@@ -2,8 +2,11 @@
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include "file.h"
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <glib.h>
|
||||
#include "file.h"
|
||||
|
||||
u_int32_t countSetBits(u_int32_t n) {
|
||||
// base case
|
||||
@@ -83,3 +86,36 @@ int move(const char * source, const char * destination) {
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//rename a folder and all subfolder and files to lowercase
|
||||
//TODO: error handling
|
||||
void casefold(const char * folder) {
|
||||
DIR * d = opendir(folder);
|
||||
struct dirent *dir;
|
||||
if (d) {
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
//removes .. & . from the list
|
||||
if(strcmp(dir->d_name, "..") != 0 && strcmp(dir->d_name, ".") != 0) {
|
||||
//only look at ascii and hope for the best.
|
||||
gchar * file = g_build_path("/", folder, dir->d_name, NULL);
|
||||
|
||||
gchar * destinationName = g_ascii_strdown(dir->d_name, -1);
|
||||
gchar * destination = g_build_path("/", folder,destinationName, NULL);
|
||||
|
||||
int result = move(file, destination);
|
||||
if(result != EXIT_SUCCESS) {
|
||||
printf("Move failed: %s => %s \n", dir->d_name, destinationName);
|
||||
}
|
||||
g_free(destinationName);
|
||||
g_free(destination);
|
||||
|
||||
if(dir->d_type == DT_DIR) {
|
||||
casefold(file);
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,6 @@
|
||||
int copy(const char * path, const char * dest, u_int32_t flags);
|
||||
int delete(const char * path, bool recursive);
|
||||
int move(const char * source, const char * destination);
|
||||
void casefold(const char * folder);
|
||||
|
||||
#endif
|
||||
|
||||
+78
-23
@@ -2,45 +2,100 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <glib.h>
|
||||
#include "install.h"
|
||||
#include "main.h"
|
||||
#include "file.h"
|
||||
|
||||
//TODO: replace ALL system call by execv / execl since it make my code into swiss cheese
|
||||
// we can imagine a milicious fomod with a simple shell code inside.
|
||||
int unzip(char * path, char * outdir) {
|
||||
char * const args[] = {
|
||||
"unzip",
|
||||
"-LL", // to lowercase
|
||||
"-q",
|
||||
path,
|
||||
"-d",
|
||||
outdir,
|
||||
NULL
|
||||
};
|
||||
|
||||
int unzip(const char * path, const char * outdir) {
|
||||
int returnValue = EXIT_SUCCESS;
|
||||
char * unzipCommand = g_strconcat("/bin/sh -c 'yes | unzip \"", path, "\" -d \"" , outdir, "\" > /dev/null'", NULL);
|
||||
if(system(unzipCommand) != 0) {
|
||||
pid_t pid = fork();
|
||||
|
||||
if(pid == 0) {
|
||||
execv("/usr/bin/unzip", args);
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
int returnValue;
|
||||
waitpid(pid, &returnValue, 0);
|
||||
|
||||
if(returnValue != 0) {
|
||||
printf("\nFailed to decompress archive\n");
|
||||
returnValue = EXIT_FAILURE;
|
||||
}
|
||||
free(unzipCommand);
|
||||
return returnValue;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int unrar(const char * path, const char * outdir) {
|
||||
int returnValue = EXIT_SUCCESS;
|
||||
char * unrarCommand = g_strconcat("/bin/sh -c 'unrar -y x \"", path, "\" \"", outdir, "\" > /dev/null'", NULL);
|
||||
if(system(unrarCommand) != 0) {
|
||||
printf("Failed to decompress archive\n");
|
||||
int unrar(char * path, char * outdir) {
|
||||
char * const args[] = {
|
||||
"unrar",
|
||||
"x",
|
||||
"-y", //assume yes
|
||||
"-cl", // to lowercase
|
||||
path,
|
||||
outdir,
|
||||
NULL
|
||||
};
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if(pid == 0) {
|
||||
execv("/usr/bin/unrar", args);
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
int returnValue;
|
||||
waitpid(pid, &returnValue, 0);
|
||||
|
||||
if(returnValue != 0) {
|
||||
printf("\nFailed to decompress archive\n");
|
||||
returnValue = EXIT_FAILURE;
|
||||
}
|
||||
free(unrarCommand);
|
||||
return returnValue;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int un7z(const char * path, const char * outdir) {
|
||||
int returnValue = EXIT_SUCCESS;
|
||||
char * un7zCommand = g_strconcat("/bin/sh -c 'yes | 7z x \"", path, "\" \"-o", outdir, "\" > /dev/null'", NULL);
|
||||
if(system(un7zCommand) != 0) {
|
||||
printf("Failed to decompress archive\n");
|
||||
|
||||
int un7z(char * path, const char * outdir) {
|
||||
gchar * outParameter = g_strjoin("", "-o", outdir, NULL);
|
||||
|
||||
char * const args[] = {
|
||||
"7z",
|
||||
"-y", //assume yes
|
||||
"x",
|
||||
path,
|
||||
outParameter,
|
||||
NULL
|
||||
};
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if(pid == 0) {
|
||||
execv("/usr/bin/7z", args);
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
g_free(outParameter);
|
||||
int returnValue;
|
||||
waitpid(pid, &returnValue, 0);
|
||||
|
||||
if(returnValue != 0) {
|
||||
printf("\nFailed to decompress archive\n");
|
||||
returnValue = EXIT_FAILURE;
|
||||
}
|
||||
free(un7zCommand);
|
||||
return returnValue;
|
||||
//make everything lowercase since 7z don't have an argument for that.
|
||||
casefold(outdir);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
const char * extractLastPart(const char * filePath, const char delimeter) {
|
||||
@@ -66,7 +121,7 @@ const char * extractFileName(const char * filePath) {
|
||||
}
|
||||
|
||||
|
||||
int addMod(const char * filePath, int appId) {
|
||||
int addMod(char * filePath, int appId) {
|
||||
int returnValue = EXIT_SUCCESS;
|
||||
|
||||
if (access(filePath, F_OK) != 0) {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#ifndef __INSTALL_H__
|
||||
#define __INSTALL_H__
|
||||
#define INSTALLED_FLAG_FILE "__DO_NOT_REMOVE__"
|
||||
int addMod(const char * filePath, int appId);
|
||||
int addMod(char * filePath, int appId);
|
||||
|
||||
#endif
|
||||
|
||||
+14
-9
@@ -345,8 +345,18 @@ int setup(int argc, char ** argv) {
|
||||
|
||||
//links don't conflict with overlayfs and avoid coping 17Gb of files.
|
||||
//but links require the files to be on the same filesystem
|
||||
const int returnValue = copy(steamGameFolder, gameFolder, CP_RECURSIVE | CP_NO_TARGET_DIR | CP_LINK);
|
||||
if(returnValue < 0) copy(steamGameFolder, gameFolder, CP_RECURSIVE | CP_NO_TARGET_DIR);
|
||||
int returnValue = copy(steamGameFolder, gameFolder, CP_RECURSIVE | CP_NO_TARGET_DIR | CP_LINK);
|
||||
if(returnValue < 0) {
|
||||
printf("Coping game files. HINT: having the game on the same partition as you home director will make this operation use zero extra space");
|
||||
returnValue = copy(steamGameFolder, gameFolder, CP_RECURSIVE | CP_NO_TARGET_DIR);
|
||||
if(returnValue < 0) {
|
||||
fprintf(stderr, "Copy failed make sure you have enough space on your device.");
|
||||
free(steamGameFolder);
|
||||
free(gameFolder);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
casefold(gameFolder);
|
||||
|
||||
free(steamGameFolder);
|
||||
free(gameFolder);
|
||||
@@ -382,7 +392,7 @@ int removeMod(int argc, char ** argv) {
|
||||
}
|
||||
|
||||
//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 EXIT_FAILURE;
|
||||
@@ -423,7 +433,7 @@ int fomod(int argc, char ** argv) {
|
||||
}
|
||||
|
||||
//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;
|
||||
@@ -498,11 +508,6 @@ int main(int argc, char ** argv) {
|
||||
if(i < 0) {
|
||||
printf("Could not create configs, check access rights for this path: %s", configFolder);
|
||||
}
|
||||
//try to enable casefold
|
||||
//failure would have no impact
|
||||
char * chattrcommand = g_strjoin("", "chattr +F ",configFolder, " 2> /dev/null", NULL);
|
||||
system(chattrcommand);
|
||||
g_free(chattrcommand);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user