From 6586ea650597ae0563c4234a7658499ce1e0117b Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 12 Jul 2020 14:04:40 +0200 Subject: Teach minecproxy to use same dirs as minecctl, step 1 --- shared/config-parser.c | 1 - shared/systemd.c | 1 - shared/utils.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++ shared/utils.h | 44 ++++++++++++- 4 files changed, 219 insertions(+), 3 deletions(-) (limited to 'shared') diff --git a/shared/config-parser.c b/shared/config-parser.c index 4dc446c..909c558 100644 --- a/shared/config-parser.c +++ b/shared/config-parser.c @@ -14,7 +14,6 @@ #include "config-parser.h" #include "server-config-options.h" #include "server-properties-options.h" -#include "config.h" static bool handle_addrinfo_results(struct addrinfo *results, struct list_head *target_list, diff --git a/shared/systemd.c b/shared/systemd.c index c45c7c5..4edc055 100644 --- a/shared/systemd.c +++ b/shared/systemd.c @@ -7,7 +7,6 @@ #include "utils.h" #include "config-parser.h" #include "systemd.h" -#include "config.h" static sd_bus *bus = NULL; static bool bus_failed = false; diff --git a/shared/utils.c b/shared/utils.c index 99fcaa3..f41a8a1 100644 --- a/shared/utils.c +++ b/shared/utils.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,11 +15,156 @@ #include #include #include +#include #include "utils.h" unsigned debug_mask = 0; +static const char *get_homedir() +{ + const char *e; + struct passwd *passwd; + uid_t uid; + + e = getenv("HOME"); + if (e && e[0] == '/') + return e; + + uid = getuid(); + if (uid == 0) + return "/root"; + + passwd = getpwuid(uid); + if (passwd && passwd->pw_dir[0] == '/') + return passwd->pw_dir; + + return NULL; +} + +int open_subdir(int dfd, const char *subdir, bool nofail) +{ + int sfd; + + if (nofail && mkdirat(dfd, subdir, 0777) < 0 && errno != EEXIST) { + error("Unable to create subdirectory %s: %m", subdir); + return -1; + } + + sfd = openat(dfd, subdir, O_PATH | O_CLOEXEC | O_DIRECTORY); + if (sfd < 0 && nofail) + error("Unable to open subdirectory %s: %m", subdir); + + return sfd; +} + +int open_xdg_dir(const char *envname, const char *altpath, bool nofail, + char **rpath) +{ + const char *e; + const char *h; + int dfd, hfd; + + e = getenv(envname); + if (e && e[0] == '/') { + dfd = open(e, O_PATH | O_CLOEXEC | O_DIRECTORY); + if (dfd < 0) + error("Unable to open $%s(%s): %m", envname, e); + else if (rpath) { + *rpath = xstrdup(e); + if (!rpath) { + error("xstrdup: %m"); + close(dfd); + return -1; + } + } + return dfd; + } + + h = get_homedir(); + if (!h) { + error("Unable to determine home directory"); + return -1; + } + + hfd = open(h, O_PATH | O_CLOEXEC | O_DIRECTORY); + if (hfd < 0) { + error("Unable to open $HOME(%s): %m", h); + return -1; + } + + dfd = open_subdir(hfd, altpath, nofail); + close(hfd); + + if (dfd >= 0 && rpath) { + *rpath = xstrcat(h, "/", altpath, NULL); + if (!*rpath) { + error("xstrcat: %m"); + close(dfd); + return -1; + } + } + return dfd; +} + +DIR *__open_dir(const char *user_override, + int (*base_dir)(bool nofail, char **rpath), + const char *fallback, char **rpath) +{ + _cleanup_close_ int xfd = -1; + _cleanup_close_ int mfd = -1; + _cleanup_free_ char *tmp = NULL; + DIR *dir; + + /* First, use explicitly set path... */ + if (user_override) { + dir = opendir(user_override); + if (dir && rpath) { + *rpath = xstrdup(user_override); + if (!*rpath) { + closedir(dir); + return NULL; + } + } + return dir; + } + + /* ...second, attempt per-user config dir... */ + xfd = base_dir(false, &tmp); + if (xfd < 0) + goto fallback; + + mfd = openat(xfd, "minecproxy", O_CLOEXEC | O_DIRECTORY | O_RDONLY); + if (mfd < 0) + goto fallback; + + dir = fdopendir(mfd); + if (dir) + mfd = -1; + + if (rpath) { + *rpath = xstrcat(tmp, "/minecproxy", NULL); + if (!*rpath) { + closedir(dir); + return NULL; + } + } + + return dir; + + /* ...third, fallback on the system dir */ +fallback: + dir = opendir(fallback); + if (dir && rpath) { + *rpath = xstrdup(fallback); + if (!*rpath) { + closedir(dir); + return NULL; + } + } + return dir; +} + const char *ansi_red = ""; const char *ansi_green = ""; const char *ansi_yellow = ""; @@ -252,3 +398,33 @@ char *xsprintf(size_t *rlen, const char *fmt, ...) return str; } + +char *xstrcat(const char *a, ...) { + size_t len; + const char *b; + char *str; + char *to; + va_list ap; + + if (!a) + return NULL; + + len = strlen(a) + 1; + + va_start(ap, a); + while ((b = va_arg(ap, const char *))) + len += strlen(b); + va_end(ap); + + str = zmalloc(len); + if (!str) + return NULL; + + to = stpcpy(str, a); + va_start(ap, a); + while ((b = va_arg(ap, const char *))) + to = stpcpy(to, b); + va_end(ap); + + return str; +} diff --git a/shared/utils.h b/shared/utils.h index 1291d21..b6bf51c 100644 --- a/shared/utils.h +++ b/shared/utils.h @@ -8,9 +8,11 @@ #include #include #include +#include #include #include #include +#include extern unsigned debug_mask; @@ -42,6 +44,7 @@ extern unsigned debug_mask; #include "list.h" #include "debug.h" #include "external.h" +#include "config.h" #include "ansi-colors.h" /* Length of longest DNS name = 253 + trailing dot */ @@ -68,6 +71,37 @@ struct saddr { struct list_head list; }; +int open_subdir(int dfd, const char *subdir, bool nofail); + +int open_xdg_dir(const char *envname, const char *altpath, bool nofail, + char **rpath); + +static inline int open_xdg_data_dir(bool nofail, char **rpath) +{ + return open_xdg_dir("XDG_DATA_HOME", ".local/share", nofail, rpath); +} + +static inline int open_xdg_cfg_dir(bool nofail, char **rpath) +{ + return open_xdg_dir("XDG_CONFIG_HOME", ".config", nofail, rpath); +} + +DIR *__open_dir(const char *user_override, + int (*base_dir)(bool nofail, char **rpath), + const char *fallback, char **rpath); + +static inline DIR *open_cfg_dir(const char *user_override, char **rpath) +{ + return __open_dir(user_override, open_xdg_cfg_dir, DEFAULT_CFG_DIR, + rpath); +} + +static inline DIR *open_data_dir(const char *user_override, char **rpath) +{ + return __open_dir(user_override, open_xdg_data_dir, DEFAULT_DATA_DIR, + rpath); +} + void enable_colors(); void free_password(char **password); @@ -91,6 +125,8 @@ int strtou16_strict(const char *str, uint16_t *result); char *xsprintf(size_t *rlen, const char *fmt, ...) _printf_(2, 3); +char *xstrcat(const char *a, ...); + static inline bool empty_str(const char *str) { if (!str || str[0] == '\0') @@ -136,7 +172,7 @@ static inline bool strcaseeq(const char *a, const char *b) static inline void closep(int *fd) { - if (*fd && *fd >= 0) + if (fd && *fd >= 0) close(*fd); } #define _cleanup_close_ _cleanup_(closep) @@ -146,4 +182,10 @@ static inline void freep(void *p) { } #define _cleanup_free_ _cleanup_(freep) +static inline void fclosep(FILE **f) { + if (f && *f) + fclose(*f); +} +#define _cleanup_fclose_ _cleanup_(fclosep) + #endif -- cgit v1.2.3