mirror of
https://github.com/clearlinux/linux-steam-integration.git
synced 2026-10-03 15:41:34 +00:00
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:
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
@@ -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, ...)
|
||||
|
||||
Reference in New Issue
Block a user