diff options
author | David Härdeman <david@hardeman.nu> | 2020-07-12 14:04:40 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2020-07-12 14:04:40 +0200 |
commit | 6586ea650597ae0563c4234a7658499ce1e0117b (patch) | |
tree | be99b63c29a21b2492a35d0bc9cd2ade93388405 /shared | |
parent | 714c267f5e4af98fd986c3563fc0e8e82a3dae1f (diff) |
Teach minecproxy to use same dirs as minecctl, step 1
Diffstat (limited to 'shared')
-rw-r--r-- | shared/config-parser.c | 1 | ||||
-rw-r--r-- | shared/systemd.c | 1 | ||||
-rw-r--r-- | shared/utils.c | 176 | ||||
-rw-r--r-- | shared/utils.h | 44 |
4 files changed, 219 insertions, 3 deletions
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 <limits.h> #include <arpa/inet.h> #include <string.h> +#include <sys/stat.h> #include <sys/types.h> #include <dirent.h> #include <fcntl.h> @@ -14,11 +15,156 @@ #include <netinet/tcp.h> #include <inttypes.h> #include <stdarg.h> +#include <pwd.h> #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 <stdlib.h> #include <linux/if_packet.h> #include <sys/socket.h> +#include <sys/types.h> #include <netinet/in.h> #include <netinet/ip.h> #include <unistd.h> +#include <dirent.h> 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 |