From 6d1d4d0a5506dce90c833ef8dd141058fea3c33a Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Mon, 25 Dec 2023 06:05:40 -0600 Subject: [WIP] Add instances still need to do the following: - check if the folder exists - try and find some way to canonicalize the path name --- src/launcherutil.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/launcherutil.c (limited to 'src/launcherutil.c') diff --git a/src/launcherutil.c b/src/launcherutil.c new file mode 100644 index 0000000..8df4a71 --- /dev/null +++ b/src/launcherutil.c @@ -0,0 +1,157 @@ +#include "macros.h" +#include "l2su.h" + +#include +#include +#include +#include +#include +#include + +/* handcoded string functions + * + * NOTE: I am aware that this is inefficient but since these are used only a handful of times + * during initialization, I don't think performance is really a huge deal here. + * + * remember that this is a Minecraft launcher, so the PC has to meet the minimum specs of that, + * which are well above the minimum specs of this launcher */ + +char *l2_launcher_strapp(char *buf, const char *src) +{ + size_t buflen = strlen(buf); + size_t srclen = strlen(src); + + char *ret = realloc(buf, buflen + srclen + 1); + if (!ret) return NULL; + + memcpy(ret + buflen, src, srclen); + ret[buflen + srclen] = '\0'; /* realloc does not initialize like calloc does */ + + return ret; +} + +char *l2_launcher_find_config_path(void) +{ + /* check for $L2SU_CONFIG */ + char *config = getenv(PROJECT_NAME_UPPER "_CONFIG"); + if (config) { + return strdup(config); + } + + /* check for $XDG_CONFIG_HOME */ + config = getenv("XDG_CONFIG_HOME"); + if (config) { + /* want to append '"/" PROJECT_NAME' to our string */ + char *ret = strdup(config); + if (!ret) return NULL; + + return l2_launcher_strapp(ret, "/" PROJECT_NAME); + } + + /* check for $HOME/.config */ + config = getenv("HOME"); + if (config) { + char *ret = strdup(config); + if (!ret) return NULL; + + return l2_launcher_strapp(ret, "/.config/" PROJECT_NAME); + } + + /* fail (do NOT attempt to find home directory from passwd */ + return NULL; +} + +char *l2_launcher_find_data_path(void) +{ + /* check for $L2SU_DATA */ + char *config = getenv(PROJECT_NAME_UPPER "_DATA"); + if (config) { + return strdup(config); + } + + /* check for $XDG_DATA_HOME */ + config = getenv("XDG_DATA_HOME"); + if (config) { + char *ret = strdup(config); + if (!ret) return NULL; + + return l2_launcher_strapp(ret, "/" PROJECT_NAME); + } + + /* check for $HOME/.local/share */ + config = getenv("HOME"); + if (config) { + char *ret = strdup(config); + if (!ret) return NULL; + + return l2_launcher_strapp(ret, "/.local/share/" PROJECT_NAME); + } + + return NULL; +} + +int l2_launcher_open_config(const char *path, int flags, mode_t mode) +{ + int conffd = open(l2_state.paths.config, O_RDONLY | O_DIRECTORY); + if (conffd < 0) return INSTANCE_ERRNO; + + int instfd = openat(conffd, path, flags, mode); + int en = errno; /* back up errno because close can fail */ + + close(conffd); + + errno = en; + return instfd; +} + +/* NOTE: There's no portable (or otherwise - see open(2) BUGS) way to do this without race conditions. */ +int l2_launcher_mkdir_parents(const char *path) +{ + if (*path != '/') return -1; + + int reserrno = 0; + + char *pathbuf = strdup(path); + char *pcurelem = pathbuf; + if (!pathbuf) return -1; + + struct stat stbuf = { 0 }; + + do { /* strtok is off-limits because it smells bad */ + *pcurelem = '/'; + pcurelem = strchr(pcurelem + 1, '/'); + + if (pcurelem) { + *pcurelem = '\0'; + } + + /* now pathbuf contains our truncated path name which may or may not exist */ + if (mkdir(pathbuf, 0755) < 0) { + if (errno == EEXIST) { + /* racy: stat the file and continue if it is a directory */ + if (stat(pathbuf, &stbuf) < 0) { + reserrno = errno; + goto mdcleanup; + } + + if (!S_ISDIR(stbuf.st_mode)) { + reserrno = ENOTDIR; + goto mdcleanup; + } + } else { + reserrno = errno; + goto mdcleanup; + } + } + } while (pcurelem); + +mdcleanup: + + free(pathbuf); + if (reserrno != 0) { + errno = reserrno; + return -1; + } + + return 0; +} -- cgit v1.2.3-70-g09d2