Build redirect paths for all known Steam Paths

This will ensure that if Steam is located on another disk, we're still
able to locate the LibraryFolders stanza in `libraryfolders.vdf` and
add all applicable rules given the realpath()'d resolved paths.

Signed-off-by: Ikey Doherty <ikey@solus-project.com>
This commit is contained in:
Ikey Doherty
2017-10-23 03:02:30 +01:00
parent a2502c1ec7
commit c5bb4ca040
3 changed files with 140 additions and 17 deletions
+95
View File
@@ -11,6 +11,7 @@
#define _GNU_SOURCE
#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -20,7 +21,12 @@
#include "common.h"
#include "files.h"
#include "log.h"
#include "nica/array.h"
#include "nica/util.h"
#include "vdf.h"
DEF_AUTOFREE(VdfFile, vdf_file_close)
bool lsi_file_exists(const char *path)
{
@@ -98,6 +104,95 @@ char *lsi_get_process_name(void)
return strdup(basep);
}
/**
* Quickly determine if a string is numeric..
*/
static inline bool lsi_is_string_numeric(char *p)
{
char *s;
for (s = p; *s; s++) {
if (!isdigit(*s)) {
return false;
}
}
/* Didn't wind, empty string */
if (s == p) {
return false;
}
return true;
}
char **lsi_get_steam_paths(void)
{
autofree(char) *steam_root = NULL;
autofree(char) *lib_conf = NULL;
autofree(VdfFile) *vdf = NULL;
VdfNode *root = NULL;
VdfNode *node = NULL;
NcArray *array = NULL;
steam_root = lsi_get_steam_dir();
if (!steam_root) {
return NULL;
}
array = nc_array_new();
if (!nc_array_add(array, strdup(steam_root))) {
goto bail;
}
if (asprintf(&lib_conf, "%s/steamapps/libraryfolders.vdf", steam_root) < 0) {
return NULL;
}
vdf = vdf_file_open(lib_conf);
if (!vdf) {
goto fallback;
}
if (!vdf_file_parse(vdf)) {
goto fallback;
}
/* Look up LibraryFolders under root */
root = vdf_file_get_root(vdf);
node = vdf_node_get(root, "LibraryFolders", NULL);
if (!node) {
goto fallback;
}
/* Walk all nodes immediately within LibraryFolders and ignore sections */
for (VdfNode *n = node->child; n; n = n->sibling) {
if (!n->value) {
continue;
}
if (lsi_is_string_numeric(n->key)) {
if (!nc_array_add(array, strdup(n->value))) {
goto bail;
}
lsi_log_debug("vdf: discovered LibraryFolders: %s", n->value);
}
}
fallback:
/* Trick nica into storing empty value to so we can terminate the array */
if (!nc_array_add(array, (void *)(long)1)) {
goto bail;
}
/* Steal the blob straight out of the array */
char **data = (char **)array->data;
data[array->len - 1] = NULL;
free(array);
return data;
bail:
nc_array_free(&array, free);
return NULL;
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
+5
View File
@@ -31,6 +31,11 @@ char *lsi_get_user_config_dir(void);
*/
char *lsi_get_steam_dir(void);
/**
* Grab all the valid steam installation directories
*/
char **lsi_get_steam_paths(void);
/**
* Quick helper to determine if the path exists
*/
+40 -17
View File
@@ -134,13 +134,12 @@ failed:
/**
* Testing: Create profile for ARK: Survival Evolved
*/
static LsiRedirectProfile *lsi_redirect_profile_new_ark(void)
static LsiRedirectProfile *lsi_redirect_profile_new_ark(char **steam_paths)
{
LsiRedirectProfile *p = NULL;
LsiRedirect *redirect = NULL;
#define ARK_BASE "steamapps/common/ARK/ShooterGame/Content"
autofree(char) *steam_dir = NULL;
autofree(char) *mic_source = NULL;
autofree(char) *mic_target = NULL;
static const char *def_mic_source =
@@ -155,19 +154,28 @@ static LsiRedirectProfile *lsi_redirect_profile_new_ark(void)
return NULL;
}
steam_dir = lsi_get_steam_dir();
if (asprintf(&mic_source, "%s/%s", steam_dir, def_mic_source) < 0) {
goto failed;
}
if (asprintf(&mic_target, "%s/%s", steam_dir, def_mic_target) < 0) {
goto failed;
/* For each steam path, try to create a rule for it */
while (*steam_paths) {
char *steam_dir = *steam_paths;
if (asprintf(&mic_source, "%s/%s", steam_dir, def_mic_source) < 0) {
goto failed;
}
if (asprintf(&mic_target, "%s/%s", steam_dir, def_mic_target) < 0) {
goto failed;
}
/* Don't add a redirect if the paths don't exist. */
redirect = lsi_redirect_new_path_replacement(mic_source, mic_target);
if (!redirect) {
goto next;
}
lsi_redirect_profile_insert_rule(p, redirect);
next:
++steam_paths;
}
redirect = lsi_redirect_new_path_replacement(mic_source, mic_target);
if (!redirect) {
goto failed;
}
lsi_redirect_profile_insert_rule(p, redirect);
return p;
failed:
@@ -189,6 +197,7 @@ __attribute__((constructor)) static void lsi_redirect_init(void)
/* Ensure we're open. */
lsi_redirect_init_tables();
autofree(char) *process_name = NULL;
char **paths = NULL;
process_name = lsi_get_process_name();
@@ -197,19 +206,33 @@ __attribute__((constructor)) static void lsi_redirect_init(void)
return;
}
/* Grab the stam installation directories */
paths = lsi_get_steam_paths();
/* Temporary hack, we'll make this more generic later */
if (strcmp(process_name, "ShooterGame") == 0) {
if (strcmp(process_name, "ShooterGame") != 0) {
lsi_log_set_id("ShooterGame");
lsi_profile = lsi_redirect_profile_new_ark();
lsi_profile = lsi_redirect_profile_new_ark(paths);
}
if (!lsi_profile) {
return;
goto clean_array;
}
lsi_override = true;
lsi_log_debug("Enable lsi_redirect for '%s'", lsi_profile->name);
clean_array:
/* Free them again */
if (paths) {
char **orig = paths;
while (*paths) {
free(*paths);
++paths;
}
free(orig);
}
}
_nica_public_ int open(const char *p, int flags, ...)