Removed small memory leaks and improved error code path
at first when i create the proof of concept i didn't care at all about memory leak sine the kernel was cleaning that for me.
This commit is contained in:
+78
-66
@@ -9,97 +9,109 @@
|
|||||||
|
|
||||||
//TODO: replace ALL system call by execv / execl since it make my code into swiss cheese
|
//TODO: replace ALL system call by execv / execl since it make my code into swiss cheese
|
||||||
|
|
||||||
void unzip(const char * path, const char * outdir) {
|
int unzip(const char * path, const char * outdir) {
|
||||||
char * unzipCommand = g_strconcat("/bin/sh -c 'yes | unzip \"", path, "\" -d \"" , outdir, "\" > /dev/null'", NULL);
|
int returnValue = EXIT_SUCCESS;
|
||||||
if(system(unzipCommand) != 0) {
|
char * unzipCommand = g_strconcat("/bin/sh -c 'yes | unzip \"", path, "\" -d \"" , outdir, "\" > /dev/null'", NULL);
|
||||||
printf("\nFailed to unzip archive\n");
|
if(system(unzipCommand) != 0) {
|
||||||
exit(EXIT_FAILURE);
|
printf("\nFailed to unzip archive\n");
|
||||||
}
|
returnValue = EXIT_FAILURE;
|
||||||
free(unzipCommand);
|
}
|
||||||
|
free(unzipCommand);
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unrar(const char * path, const char * outdir) {
|
int unrar(const char * path, const char * outdir) {
|
||||||
char * unrarCommand = g_strconcat("/bin/sh -c 'unrar -y x \"", path, "\" \"", outdir, "\" > /dev/null'", NULL);
|
int returnValue = EXIT_SUCCESS;
|
||||||
if(system(unrarCommand) != 0) {
|
char * unrarCommand = g_strconcat("/bin/sh -c 'unrar -y x \"", path, "\" \"", outdir, "\" > /dev/null'", NULL);
|
||||||
printf("Failed to unzip archive\n");
|
if(system(unrarCommand) != 0) {
|
||||||
exit(EXIT_FAILURE);
|
printf("Failed to unzip archive\n");
|
||||||
}
|
returnValue = EXIT_FAILURE;
|
||||||
free(unrarCommand);
|
}
|
||||||
|
free(unrarCommand);
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void un7z(const char * path, const char * outdir) {
|
int un7z(const char * path, const char * outdir) {
|
||||||
char * un7zCommand = g_strconcat("/bin/sh -c 'yes | 7z x \"", path, "\" \"-o", outdir, "\" > /dev/null'", NULL);
|
int returnValue = EXIT_SUCCESS;
|
||||||
if(system(un7zCommand) != 0) {
|
char * un7zCommand = g_strconcat("/bin/sh -c 'yes | 7z x \"", path, "\" \"-o", outdir, "\" > /dev/null'", NULL);
|
||||||
printf("Failed to unzip archive\n");
|
if(system(un7zCommand) != 0) {
|
||||||
exit(EXIT_FAILURE);
|
printf("Failed to unzip archive\n");
|
||||||
}
|
returnValue = EXIT_FAILURE;
|
||||||
free(un7zCommand);
|
}
|
||||||
|
free(un7zCommand);
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * extractLastPart(const char * filePath, const char delimeter) {
|
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--) {
|
||||||
if(filePath[i] == delimeter) {
|
if(filePath[i] == delimeter) {
|
||||||
index = i + 1;
|
index = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index <= 0) return NULL;
|
if(index <= 0 || index == length) return NULL;
|
||||||
char * extension = malloc((length - index) * sizeof(char));
|
char * extension = malloc((length - index) * sizeof(char));
|
||||||
memcpy(extension, &filePath[index], (length - index));
|
memcpy(extension, &filePath[index], (length - index));
|
||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * extractExtension(const char * filePath) {
|
char * extractExtension(const char * filePath) {
|
||||||
return extractLastPart(filePath, '.');
|
return extractLastPart(filePath, '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
char * extractFileName(const char * filePath) {
|
char * extractFileName(const char * filePath) {
|
||||||
return extractLastPart(filePath, '/');
|
return extractLastPart(filePath, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void addMod(const char * filePath, int appId) {
|
int addMod(const char * filePath, int appId) {
|
||||||
|
int returnValue = EXIT_SUCCESS;
|
||||||
|
|
||||||
if (access(filePath, F_OK) != 0) {
|
if (access(filePath, F_OK) != 0) {
|
||||||
printf("File not found\n");
|
printf("File not found\n");
|
||||||
exit(EXIT_FAILURE);
|
returnValue = EXIT_FAILURE;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * configFolder = g_build_filename(getenv("HOME"), MANAGER_FILES, NULL);
|
char * configFolder = g_build_filename(getenv("HOME"), MANAGER_FILES, NULL);
|
||||||
if(g_mkdir_with_parents(configFolder, 0755) < 0) {
|
if(g_mkdir_with_parents(configFolder, 0755) < 0) {
|
||||||
printf("Could not create mod folder");
|
printf("Could not create mod folder");
|
||||||
exit(EXIT_FAILURE);
|
returnValue = EXIT_FAILURE;
|
||||||
}
|
goto exit2;
|
||||||
|
}
|
||||||
|
|
||||||
char * filename = extractFileName(filePath);
|
char * filename = extractFileName(filePath);
|
||||||
char * extension = extractExtension(filename);
|
char * extension = extractExtension(filename);
|
||||||
char * lowercaseExtension = g_ascii_strdown(extension, -1);
|
char * lowercaseExtension = g_ascii_strdown(extension, -1);
|
||||||
free(extension);
|
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);
|
||||||
printf("Adding mod, this process can be slow depending on your hardware\n");
|
printf("Adding mod, this process can be slow depending on your hardware\n");
|
||||||
if(strcmp(lowercaseExtension, "rar") == 0) {
|
if(strcmp(lowercaseExtension, "rar") == 0) {
|
||||||
unrar(filePath, outdir);
|
returnValue = unrar(filePath, outdir);
|
||||||
} else if (strcmp(lowercaseExtension, "zip") == 0) {
|
} else if (strcmp(lowercaseExtension, "zip") == 0) {
|
||||||
unzip(filePath, outdir);
|
returnValue = unzip(filePath, outdir);
|
||||||
} else if (strcmp(lowercaseExtension, "7z") == 0) {
|
} else if (strcmp(lowercaseExtension, "7z") == 0) {
|
||||||
un7z(filePath, outdir);
|
returnValue = un7z(filePath, outdir);
|
||||||
} else {
|
} else {
|
||||||
printf("Unsupported format only zip/7z/rar are supported\n");
|
printf("Unsupported format only zip/7z/rar are supported\n");
|
||||||
exit(EXIT_FAILURE);
|
returnValue = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
|
|
||||||
free(lowercaseExtension);
|
free(lowercaseExtension);
|
||||||
free(filename);
|
free(filename);
|
||||||
free(outdir);
|
free(outdir);
|
||||||
|
exit2:
|
||||||
|
free(configFolder);
|
||||||
|
exit:
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|||||||
+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__"
|
||||||
void addMod(const char * filePath, int appId);
|
int addMod(const char * filePath, int appId);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+50
-24
@@ -365,17 +365,19 @@ int main(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gamePaths = search_games();
|
gamePaths = search_games();
|
||||||
|
int returnValue = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char * configFolder = g_build_filename(getHome(), MANAGER_FILES, NULL);
|
char * configFolder = g_build_filename(getHome(), MANAGER_FILES, NULL);
|
||||||
if(access(configFolder, F_OK) != 0) {
|
if(access(configFolder, F_OK) != 0) {
|
||||||
|
|
||||||
//check to NOT run this as root
|
//check to NOT run this as root
|
||||||
//creating folder as root will causes lots of headache
|
//creating folder as root will causes lots of headache
|
||||||
|
//such as problem with access rights and taking the risk of
|
||||||
|
//running system as root (wich is a big security issue)
|
||||||
if(getuid() == 0) {
|
if(getuid() == 0) {
|
||||||
printf("For the first please run without sudo\n");
|
printf("For the first please run without sudo\n");
|
||||||
return EXIT_FAILURE;
|
returnValue = EXIT_FAILURE;
|
||||||
|
goto exit;
|
||||||
} else {
|
} else {
|
||||||
//leading 0 == octal
|
//leading 0 == octal
|
||||||
int i = g_mkdir_with_parents(configFolder, 0755);
|
int i = g_mkdir_with_parents(configFolder, 0755);
|
||||||
@@ -389,37 +391,61 @@ int main(int argc, char ** argv) {
|
|||||||
free(chattrcommand);
|
free(chattrcommand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(configFolder);
|
|
||||||
|
|
||||||
|
|
||||||
if(strcmp(argv[1], "--list-games") == 0 || strcmp(argv[1], "-l") == 0) {
|
if(strcmp(argv[1], "--list-games") == 0 || strcmp(argv[1], "-l") == 0) {
|
||||||
if(isRoot()) return noRoot();
|
if(isRoot())
|
||||||
return listGames(argc, argv);
|
returnValue = noRoot();
|
||||||
|
else
|
||||||
|
returnValue = listGames(argc, argv);
|
||||||
|
|
||||||
} else if(strcmp(argv[1], "--add") == 0 || strcmp(argv[1], "-a") == 0) {
|
} else if(strcmp(argv[1], "--add") == 0 || strcmp(argv[1], "-a") == 0) {
|
||||||
if(isRoot()) return noRoot();
|
if(isRoot())
|
||||||
return add(argc, argv);
|
returnValue = noRoot();
|
||||||
|
else
|
||||||
|
returnValue = add(argc, argv);
|
||||||
|
|
||||||
} else if(strcmp(argv[1], "--list-mods") == 0 || strcmp(argv[1], "-m") == 0) {
|
} else if(strcmp(argv[1], "--list-mods") == 0 || strcmp(argv[1], "-m") == 0) {
|
||||||
if(isRoot()) return noRoot();
|
if(isRoot())
|
||||||
return listMods(argc, argv);
|
returnValue = noRoot();
|
||||||
|
else
|
||||||
|
returnValue = listMods(argc, argv);
|
||||||
|
|
||||||
} else if(strcmp(argv[1], "--install") == 0 || strcmp(argv[1], "-i") == 0) {
|
} else if(strcmp(argv[1], "--install") == 0 || strcmp(argv[1], "-i") == 0) {
|
||||||
if(isRoot()) return noRoot();
|
if(isRoot())
|
||||||
return installAndRemoveMod(argc, argv, true);
|
returnValue = noRoot();
|
||||||
|
else
|
||||||
|
returnValue = installAndRemoveMod(argc, argv, true);
|
||||||
|
|
||||||
} else if(strcmp(argv[1], "--remove") == 0 || strcmp(argv[1], "-r") == 0) {
|
} else if(strcmp(argv[1], "--remove") == 0 || strcmp(argv[1], "-r") == 0) {
|
||||||
if(isRoot()) return noRoot();
|
if(isRoot())
|
||||||
return installAndRemoveMod(argc, argv, false);
|
returnValue = noRoot();
|
||||||
|
else
|
||||||
|
returnValue = installAndRemoveMod(argc, argv, false);
|
||||||
|
|
||||||
} else if(strcmp(argv[1], "--deploy") == 0 || strcmp(argv[1], "-d") == 0) {
|
} else if(strcmp(argv[1], "--deploy") == 0 || strcmp(argv[1], "-d") == 0) {
|
||||||
if(!isRoot()) return needRoot();
|
if(!isRoot())
|
||||||
return deploy(argc, argv);
|
returnValue = needRoot();
|
||||||
|
else
|
||||||
|
returnValue = deploy(argc, argv);
|
||||||
|
|
||||||
} else if(strcmp(argv[1], "--unbind") == 0 || strcmp(argv[1], "-u") == 0){
|
} else if(strcmp(argv[1], "--unbind") == 0 || strcmp(argv[1], "-u") == 0){
|
||||||
if(!isRoot()) return needRoot();
|
if(!isRoot())
|
||||||
return unbind(argc, argv);
|
returnValue = needRoot();
|
||||||
|
else
|
||||||
|
returnValue = unbind(argc, argv);
|
||||||
|
|
||||||
} else if(strcmp(argv[1], "--setup") == 0) {
|
} else if(strcmp(argv[1], "--setup") == 0) {
|
||||||
if(isRoot()) return noRoot();
|
if(isRoot())
|
||||||
return setup(argc, argv);
|
returnValue = noRoot();
|
||||||
|
else
|
||||||
|
returnValue = setup(argc, argv);
|
||||||
} else {
|
} else {
|
||||||
return usage();
|
usage();
|
||||||
|
returnValue = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
return 0;
|
free(configFolder);
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-20
@@ -32,17 +32,17 @@ int getFiledId(const char * field) {
|
|||||||
return FIELD_APPS;
|
return FIELD_APPS;
|
||||||
} else {
|
} else {
|
||||||
printf("unknown field");
|
printf("unknown field");
|
||||||
exit(EXIT_FAILURE);
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValveLibraries_t * parseVDF(const char * path, size_t * size) {
|
ValveLibraries_t * parseVDF(const char * path, size_t * size, int * status) {
|
||||||
FILE * fd = fopen(path, "r");
|
FILE * fd = fopen(path, "r");
|
||||||
char * line = NULL;
|
char * line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
|
|
||||||
|
*status = EXIT_SUCCESS;
|
||||||
|
|
||||||
bool inQuotes = false;
|
bool inQuotes = false;
|
||||||
|
|
||||||
@@ -75,6 +75,11 @@ ValveLibraries_t * parseVDF(const char * path, size_t * size) {
|
|||||||
buffer[bufferIndex] = '\0';
|
buffer[bufferIndex] = '\0';
|
||||||
if(nextFieldToFill == -1) {
|
if(nextFieldToFill == -1) {
|
||||||
nextFieldToFill = getFiledId(buffer);
|
nextFieldToFill = getFiledId(buffer);
|
||||||
|
if(nextFieldToFill == -1) {
|
||||||
|
if(libraries != NULL) free(libraries);
|
||||||
|
libraries = NULL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
char * value = strndup(buffer, bufferIndex);
|
char * value = strndup(buffer, bufferIndex);
|
||||||
@@ -137,7 +142,10 @@ ValveLibraries_t * parseVDF(const char * path, size_t * size) {
|
|||||||
case '}':
|
case '}':
|
||||||
if(inQuotes) {
|
if(inQuotes) {
|
||||||
printf("Syntax error in VDF\n");
|
printf("Syntax error in VDF\n");
|
||||||
exit(EXIT_FAILURE);
|
free(libraries);
|
||||||
|
libraries = NULL;
|
||||||
|
*status = EXIT_FAILURE;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
if(nextFieldToFill == FIELD_APPS) {
|
if(nextFieldToFill == FIELD_APPS) {
|
||||||
nextFieldToFill = -1;
|
nextFieldToFill = -1;
|
||||||
@@ -153,25 +161,47 @@ ValveLibraries_t * parseVDF(const char * path, size_t * size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
return libraries;
|
return libraries;
|
||||||
}
|
}
|
||||||
|
|
||||||
GHashTable* search_games() {
|
void freeLibraries(ValveLibraries_t * libraries, int size) {
|
||||||
|
for(int i = 0; i < size; i++) {
|
||||||
|
free(libraries[i].path);
|
||||||
|
free(libraries[i].label);
|
||||||
|
free(libraries[i].contentId);
|
||||||
|
free(libraries[i].update_clean_bytes_tally);
|
||||||
|
free(libraries[i].time_last_update_corruption);
|
||||||
|
free(libraries[i].apps);
|
||||||
|
}
|
||||||
|
free(libraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
GHashTable* search_games(int * status) {
|
||||||
ValveLibraries_t * libraries = NULL;
|
ValveLibraries_t * libraries = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
const char * HOME = getHome();
|
char * home = getHome();
|
||||||
|
*status = EXIT_SUCCESS;
|
||||||
|
|
||||||
for(int i = 0; i < LEN(steamLibraries); i++) {
|
for(int i = 0; i < LEN(steamLibraries); i++) {
|
||||||
char * path = g_build_filename(HOME, steamLibraries[i], "steamapps/libraryfolders.vdf", NULL);
|
char * path = g_build_filename(home, steamLibraries[i], "steamapps/libraryfolders.vdf", NULL);
|
||||||
if (access(path, F_OK) == 0) {
|
if (access(path, F_OK) == 0) {
|
||||||
libraries = parseVDF(path, &size);
|
int parserStatus;
|
||||||
break;
|
libraries = parseVDF(path, &size, &parserStatus);
|
||||||
|
if(parserStatus == EXIT_SUCCESS)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(path);
|
g_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(home);
|
||||||
|
if(libraries == NULL) {
|
||||||
|
*status = EXIT_FAILURE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
GHashTable* table = g_hash_table_new(g_int_hash, g_int_equal);
|
GHashTable* table = g_hash_table_new(g_int_hash, g_int_equal);
|
||||||
|
|
||||||
//fill the table
|
//fill the table
|
||||||
@@ -186,17 +216,7 @@ GHashTable* search_games() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//free used up memory
|
freeLibraries(libraries, size);
|
||||||
for(int i = 0; i < size; i++) {
|
|
||||||
free(libraries[i].path);
|
|
||||||
free(libraries[i].label);
|
|
||||||
free(libraries[i].contentId);
|
|
||||||
free(libraries[i].update_clean_bytes_tally);
|
|
||||||
free(libraries[i].time_last_update_corruption);
|
|
||||||
free(libraries[i].apps);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(libraries != NULL) free(libraries);
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user