From f432bd72fa30c75f215626abdaf9b41609c670df Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Thu, 20 Aug 2020 14:08:51 -0400 Subject: Refactor base dir functions to iterate over paths --- chat.h | 6 +++ xdg.c | 184 +++++++++++++++++++++++++++++++---------------------------------- 2 files changed, 94 insertions(+), 96 deletions(-) diff --git a/chat.h b/chat.h index 6e3d20f..60273bc 100644 --- a/chat.h +++ b/chat.h @@ -294,6 +294,12 @@ void logFormat(uint id, const time_t *time, const char *format, ...) __attribute__((format(printf, 3, 4))); void logClose(void); +const char *configPath( + char *buf, size_t cap, const char **dirs, const char *path +); +const char *dataPath( + char *buf, size_t cap, const char **dirs, const char *path +); FILE *configOpen(const char *path, const char *mode); FILE *dataOpen(const char *path, const char *mode); void dataMkdir(const char *path); diff --git a/xdg.c b/xdg.c index 2500bac..a92bc6d 100644 --- a/xdg.c +++ b/xdg.c @@ -37,121 +37,113 @@ #define SUBDIR "catgirl" -FILE *configOpen(const char *path, const char *mode) { - if (path[0] == '/' || path[0] == '.') goto local; +struct Base { + const char *envHome; + const char *envDirs; + const char *defHome; + const char *defDirs; +}; + +static const struct Base Config = { + .envHome = "XDG_CONFIG_HOME", + .envDirs = "XDG_CONFIG_DIRS", + .defHome = ".config", + .defDirs = "/etc/xdg", +}; + +static const struct Base Data = { + .envHome = "XDG_DATA_HOME", + .envDirs = "XDG_DATA_DIRS", + .defHome = ".local/share", + .defDirs = "/usr/local/share:/usr/share", +}; + +static const char *basePath( + struct Base base, + char *buf, size_t cap, const char **dirs, const char *path +) { + if (*dirs) { + if (!**dirs) return NULL; + size_t len = strcspn(*dirs, ":"); + snprintf(buf, cap, "%.*s/" SUBDIR "/%s", (int)len, *dirs, path); + *dirs += len; + if (**dirs) *dirs += 1; + return buf; + } - const char *home = getenv("HOME"); - const char *configHome = getenv("XDG_CONFIG_HOME"); - const char *configDirs = getenv("XDG_CONFIG_DIRS"); + if (path[0] == '/' || path[0] == '.') { + *dirs = ""; + return path; + } - char buf[PATH_MAX]; - if (configHome) { - snprintf(buf, sizeof(buf), "%s/" SUBDIR "/%s", configHome, path); + *dirs = getenv(base.envDirs); + if (!*dirs) *dirs = base.defDirs; + + const char *home = getenv("HOME"); + const char *baseHome = getenv(base.envHome); + if (baseHome) { + snprintf(buf, cap, "%s/" SUBDIR "/%s", baseHome, path); } else { - if (!home) goto local; - snprintf(buf, sizeof(buf), "%s/.config/" SUBDIR "/%s", home, path); + if (!home) return NULL; + snprintf(buf, cap, "%s/%s/" SUBDIR "/%s", home, base.defHome, path); } - FILE *file = fopen(buf, mode); - if (file) return file; - if (errno != ENOENT) warn("%s", buf); - - if (!configDirs) configDirs = "/etc/xdg"; - while (*configDirs) { - size_t len = strcspn(configDirs, ":"); - snprintf( - buf, sizeof(buf), "%.*s/" SUBDIR "/%s", - (int)len, configDirs, path - ); - file = fopen(buf, mode); + return buf; +} + +const char * +configPath(char *buf, size_t cap, const char **dirs, const char *path) { + return basePath(Config, buf, cap, dirs, path); +} + +const char * +dataPath(char *buf, size_t cap, const char **dirs, const char *path) { + return basePath(Data, buf, cap, dirs, path); +} + +FILE *configOpen(const char *path, const char *mode) { + const char *abs; + char buf[PATH_MAX]; + const char *dirs = NULL; + while (NULL != (abs = configPath(buf, sizeof(buf), &dirs, path))) { + FILE *file = fopen(abs, mode); if (file) return file; - if (errno != ENOENT) warn("%s", buf); - configDirs += len; - if (*configDirs) configDirs++; + if (errno != ENOENT) warn("%s", abs); } - -local: - file = fopen(path, mode); + FILE *file = fopen(path, mode); if (!file) warn("%s", path); return file; } -FILE *dataOpen(const char *path, const char *mode) { - if (path[0] == '/' || path[0] == '.') goto local; - - const char *home = getenv("HOME"); - const char *dataHome = getenv("XDG_DATA_HOME"); - const char *dataDirs = getenv("XDG_DATA_DIRS"); - - char homePath[PATH_MAX]; - if (dataHome) { - snprintf( - homePath, sizeof(homePath), - "%s/" SUBDIR "/%s", dataHome, path - ); - } else { - if (!home) goto local; - snprintf( - homePath, sizeof(homePath), - "%s/.local/share/" SUBDIR "/%s", home, path - ); - } - FILE *file = fopen(homePath, mode); - if (file) return file; - if (errno != ENOENT) warn("%s", homePath); +void dataMkdir(const char *path) { + char buf[PATH_MAX]; + const char *dirs = NULL; + const char *abs = dataPath(buf, sizeof(buf), &dirs, path); + int error = mkdir(abs, S_IRWXU); + if (error && errno != EEXIST) warn("%s", abs); +} +FILE *dataOpen(const char *path, const char *mode) { + const char *abs; char buf[PATH_MAX]; - if (!dataDirs) dataDirs = "/usr/local/share:/usr/share"; - while (*dataDirs) { - size_t len = strcspn(dataDirs, ":"); - snprintf( - buf, sizeof(buf), "%.*s/" SUBDIR "/%s", - (int)len, dataDirs, path - ); - file = fopen(buf, mode); + const char *dirs = NULL; + while (NULL != (abs = dataPath(buf, sizeof(buf), &dirs, path))) { + FILE *file = fopen(abs, mode); if (file) return file; - if (errno != ENOENT) warn("%s", buf); - dataDirs += len; - if (*dataDirs) dataDirs++; + if (errno != ENOENT) warn("%s", abs); } if (mode[0] != 'r') { - char *base = strrchr(homePath, '/'); - *base = '\0'; - int error = mkdir(homePath, S_IRWXU); - if (error && errno != EEXIST) { - warn("%s", homePath); - return NULL; - } - *base = '/'; - file = fopen(homePath, mode); - if (!file) warn("%s", homePath); + dirs = NULL; + abs = dataPath(buf, sizeof(buf), &dirs, path); + if (!abs) return NULL; + + dataMkdir(""); + FILE *file = fopen(abs, mode); + if (!file) warn("%s", abs); return file; } -local: - file = fopen(path, mode); + FILE *file = fopen(path, mode); if (!file) warn("%s", path); return file; } - -void dataMkdir(const char *path) { - const char *home = getenv("HOME"); - const char *dataHome = getenv("XDG_DATA_HOME"); - - char homePath[PATH_MAX]; - if (dataHome) { - snprintf( - homePath, sizeof(homePath), - "%s/" SUBDIR "/%s", dataHome, path - ); - } else { - if (!home) return; - snprintf( - homePath, sizeof(homePath), - "%s/.local/share/" SUBDIR "/%s", home, path - ); - } - - int error = mkdir(homePath, S_IRWXU); - if (error && errno != EEXIST) warn("%s", homePath); -} -- cgit 1.4.1 blish "Care"June McEnroe 2022-03-31Publish "Compassion"June McEnroe 2022-03-24Skip matches with ident chars on either sideJune McEnroe This fixes, for example, where the link gets placed on static regex_t regex(const char *pattern, int flags) in title.c. 2022-03-24Add The Invisible Life of Addie LaRueJune McEnroe So good, but so long. Reminded me of The Ten Thousand Doors of January at the beginning, and more of that N. K. Jemisin series about gods later. I like this interacting with gods and becoming something like one sort of thing. God, it took me a whole month (more?) to read and this is only my third book of the year :( I need some more novellas to read, but the other books I have from the library currently are also thick. 2022-03-22Source ~/.profile.local if it existsJune McEnroe 2022-03-18Publish "Addendum 2021"June McEnroe 2022-03-16Remove wcwidth portJune McEnroe DYLD_FORCE_FLAT_NAMESPACE no longer exists in macOS 12 so this approach doesn't work anymore. Moved to <https://git.causal.agency/jorts/tree/wcwidth> and compiled into <https://git.causal.agency/jorts/tree/ncurses>. 2022-03-16Remove -j4 from ./PlanJune McEnroe Plan learned to set this automatically! 2022-03-15Rewrite Linux install.sh for DebianJune McEnroe 2022-03-15Remove dashJune McEnroe