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 (2 or 3)
|
||||||
* Fuse-overlayfs
|
* 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:
|
## TODO:
|
||||||
1. we need a name for this.
|
1. we need a name for this.
|
||||||
2. allow to change mod priority.
|
2. allow to change mod priority.
|
||||||
|
|||||||
+37
-1
@@ -2,8 +2,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "file.h"
|
|
||||||
#include <stdio.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) {
|
u_int32_t countSetBits(u_int32_t n) {
|
||||||
// base case
|
// base case
|
||||||
@@ -83,3 +86,36 @@ int move(const char * source, const char * destination) {
|
|||||||
return returnValue;
|
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 copy(const char * path, const char * dest, u_int32_t flags);
|
||||||
int delete(const char * path, bool recursive);
|
int delete(const char * path, bool recursive);
|
||||||
int move(const char * source, const char * destination);
|
int move(const char * source, const char * destination);
|
||||||
|
void casefold(const char * folder);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+78
-23
@@ -2,45 +2,100 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "install.h"
|
#include "install.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
//TODO: replace ALL system call by execv / execl since it make my code into swiss cheese
|
int unzip(char * path, char * outdir) {
|
||||||
// we can imagine a milicious fomod with a simple shell code inside.
|
char * const args[] = {
|
||||||
|
"unzip",
|
||||||
|
"-LL", // to lowercase
|
||||||
|
"-q",
|
||||||
|
path,
|
||||||
|
"-d",
|
||||||
|
outdir,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
int unzip(const char * path, const char * outdir) {
|
pid_t pid = fork();
|
||||||
int returnValue = EXIT_SUCCESS;
|
|
||||||
char * unzipCommand = g_strconcat("/bin/sh -c 'yes | unzip \"", path, "\" -d \"" , outdir, "\" > /dev/null'", NULL);
|
if(pid == 0) {
|
||||||
if(system(unzipCommand) != 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");
|
printf("\nFailed to decompress archive\n");
|
||||||
returnValue = EXIT_FAILURE;
|
returnValue = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
free(unzipCommand);
|
return EXIT_SUCCESS;
|
||||||
return returnValue;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int unrar(const char * path, const char * outdir) {
|
int unrar(char * path, char * outdir) {
|
||||||
int returnValue = EXIT_SUCCESS;
|
char * const args[] = {
|
||||||
char * unrarCommand = g_strconcat("/bin/sh -c 'unrar -y x \"", path, "\" \"", outdir, "\" > /dev/null'", NULL);
|
"unrar",
|
||||||
if(system(unrarCommand) != 0) {
|
"x",
|
||||||
printf("Failed to decompress archive\n");
|
"-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;
|
returnValue = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
free(unrarCommand);
|
return EXIT_SUCCESS;
|
||||||
return returnValue;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int un7z(const char * path, const char * outdir) {
|
|
||||||
int returnValue = EXIT_SUCCESS;
|
int un7z(char * path, const char * outdir) {
|
||||||
char * un7zCommand = g_strconcat("/bin/sh -c 'yes | 7z x \"", path, "\" \"-o", outdir, "\" > /dev/null'", NULL);
|
gchar * outParameter = g_strjoin("", "-o", outdir, NULL);
|
||||||
if(system(un7zCommand) != 0) {
|
|
||||||
printf("Failed to decompress archive\n");
|
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;
|
returnValue = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
free(un7zCommand);
|
//make everything lowercase since 7z don't have an argument for that.
|
||||||
return returnValue;
|
casefold(outdir);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * extractLastPart(const char * filePath, const char delimeter) {
|
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;
|
int returnValue = EXIT_SUCCESS;
|
||||||
|
|
||||||
if (access(filePath, F_OK) != 0) {
|
if (access(filePath, F_OK) != 0) {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#ifndef __INSTALL_H__
|
#ifndef __INSTALL_H__
|
||||||
#define __INSTALL_H__
|
#define __INSTALL_H__
|
||||||
#define INSTALLED_FLAG_FILE "__DO_NOT_REMOVE__"
|
#define INSTALLED_FLAG_FILE "__DO_NOT_REMOVE__"
|
||||||
int addMod(const char * filePath, int appId);
|
int addMod(char * filePath, int appId);
|
||||||
|
|
||||||
#endif
|
#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.
|
//links don't conflict with overlayfs and avoid coping 17Gb of files.
|
||||||
//but links require the files to be on the same filesystem
|
//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);
|
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);
|
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(steamGameFolder);
|
||||||
free(gameFolder);
|
free(gameFolder);
|
||||||
@@ -382,7 +392,7 @@ int removeMod(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//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 EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -423,7 +433,7 @@ int fomod(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//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;
|
||||||
@@ -498,11 +508,6 @@ int main(int argc, char ** argv) {
|
|||||||
if(i < 0) {
|
if(i < 0) {
|
||||||
printf("Could not create configs, check access rights for this path: %s", configFolder);
|
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