From 09ebc823f928e71b5b8e2ea75bf29f73d21a12e8 Mon Sep 17 00:00:00 2001 From: EyitopeIO Date: Thu, 29 Aug 2024 01:07:20 +0100 Subject: [PATCH] Fix segfault when HOME is not set --- README.md | 14 +++++++++++-- src/cache.c | 59 ++++++++++++++++++++++++++++++++++------------------- src/cache.h | 9 ++++++-- src/main.c | 45 ++++++++++++++++++++++++++++------------ 4 files changed, 89 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 4b4726b..ad3cb04 100644 --- a/README.md +++ b/README.md @@ -181,10 +181,20 @@ This feature was implemented due to Github ## Permanent cache system You can cache the files you have accessed permanently on your hard drive by -using the ``--cache`` flag. The file it caches persist across sessions. +using the ``--cache`` flag. The file it caches persist across sessions, but +can clear the cache using ``--cache-clear`` + +> [!WARNING] +> If ``--cache-location `` appears before ``--cache-clear``, the entire +> directory ```` will be deleted instead. Take caution when specifying +> non-empty directories to be used as cache. By default, the cache files are stored under ``${XDG_CACHE_HOME}/httpdirfs``, -which by default is ``${HOME}/.cache/httpdirfs``. Each HTTP directory gets its +``${HOME}/.cache/httpdirfs``, or the current working directory ``./.cache``, +whichever is found first. By default, ``${XDG_CACHE_HOME}/httpdirfs`` is +normally ``${HOME}/.cache/httpdirfs``. + +Each HTTP directory gets its own cache folder, they are named using the escaped URL of the HTTP directory. Once a segment of the file has been downloaded once, it won't be downloaded diff --git a/src/cache.c b/src/cache.c index 9942943..4c0c2ea 100644 --- a/src/cache.c +++ b/src/cache.c @@ -35,18 +35,38 @@ static pthread_mutex_t cf_lock; */ static char *DATA_DIR; -static char *CacheSystem_get_cache_home() + +char *CacheSystem_get_cache_dir() { if (CONFIG.cache_dir) { return CONFIG.cache_dir; } - char *xdg_cache_home = getenv("XDG_CACHE_HOME"); - if (!xdg_cache_home) { - char *home = getenv("HOME"); - char *xdg_cache_home_default = "/.cache"; - xdg_cache_home = path_append(home, xdg_cache_home_default); + + const char *default_cache_subdir = "/.cache"; + char *cache_dir = NULL; + + const char *xdg_cache_home = getenv("XDG_CACHE_HOME"); + if (xdg_cache_home) { + cache_dir = strndup(xdg_cache_home, MAX_PATH_LEN); + } else { + const char *user_home = getenv("HOME"); + if (user_home) { + cache_dir = path_append(user_home, default_cache_subdir); + } else { + lprintf(warning, "$HOME is unset\n"); + /* + * XDG_CACHE_HOME and HOME already are full paths. Not relying + * on environment PWD since it too may be undefined. + */ + const char *cur_dir = realpath("./", NULL); + if (cur_dir) { + cache_dir = path_append(cur_dir, default_cache_subdir); + } else { + lprintf(fatal, "Could not create cache directory\n"); + } + } } - return xdg_cache_home; + return cache_dir; } /** @@ -54,7 +74,7 @@ static char *CacheSystem_get_cache_home() */ static char *CacheSystem_calc_dir(const char *url) { - char *cache_home = CacheSystem_get_cache_home(); + char *cache_home = CacheSystem_get_cache_dir(); if (mkdir (cache_home, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) @@ -92,6 +112,7 @@ static char *CacheSystem_calc_dir(const char *url) lprintf(fatal, "mkdir(): %s\n", strerror(errno)); } FREE(fn); + FREE(cache_home); FREE(cache_dir_root); curl_free(escaped_url); curl_easy_cleanup(c); @@ -163,22 +184,18 @@ static int ntfw_cb(const char *fpath, const struct stat *sb, int typeflag, struc return remove(fpath); } -void CacheSystem_clear(const char *path) +void CacheSystem_clear() { - char *cache_root_dir; - if (path) { - cache_root_dir = strdup(path); + char *cache_home = CacheSystem_get_cache_dir(); + const char *cache_del; + lprintf(debug, "%s\n", cache_home); + if (CONFIG.cache_dir) { + cache_del = cache_home; } else { - char *cache_home = CacheSystem_get_cache_home(); - cache_root_dir = path_append(cache_home, "/httpdirfs/"); - FREE(cache_home); + cache_del = path_append(cache_home, "/httpdirfs/"); } - - lprintf(debug, "%s\n", path); - - nftw(cache_root_dir, ntfw_cb, 64, FTW_DEPTH | FTW_PHYS | FTW_MOUNT); - FREE(cache_root_dir); - + nftw(cache_del, ntfw_cb, 64, FTW_DEPTH | FTW_PHYS | FTW_MOUNT); + FREE(cache_home); exit(EXIT_SUCCESS); } diff --git a/src/cache.h b/src/cache.h index fc38726..979953d 100644 --- a/src/cache.h +++ b/src/cache.h @@ -95,7 +95,12 @@ void CacheSystem_init(const char *path, int url_supplied); /** * \brief clear the content of the cache directory */ -void CacheSystem_clear(const char *path); +void CacheSystem_clear(); + +/** + * \brief Return the fullpath to the cache directory + */ +char *CacheSystem_get_cache_dir(); /** * \brief Create directories under the cache directory structure, if they do @@ -148,4 +153,4 @@ void Cache_delete(const char *fn); */ long Cache_read(Cache *cf, char *const output_buf, const off_t len, const off_t offset_start); -#endif +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index dca2995..e021563 100644 --- a/src/main.c +++ b/src/main.c @@ -114,17 +114,38 @@ activate Sonic mode.\n"); return 0; } +static char *get_XDG_CONFIG_HOME() +{ + const char *default_config_subdir = "/.config"; + char *config_dir = NULL; + + const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); + if (xdg_config_home) { + config_dir = strndup(xdg_config_home, MAX_PATH_LEN); + } else { + const char *user_home = getenv("HOME"); + if (user_home) { + config_dir = path_append(user_home, default_config_subdir); + } else { + lprintf(warning, "$HOME is unset\n"); + const char *cur_dir = realpath("./", NULL); + if (cur_dir) { + config_dir = path_append(cur_dir, default_config_subdir); + } else { + lprintf(warning, "Could not get config directory\n"); + } + } + } + return config_dir; +} + void parse_config_file(char ***argv, int *argc) { char *full_path; if (!config_path) { - char *xdg_config_home = getenv("XDG_CONFIG_HOME"); - if (!xdg_config_home) { - char *home = getenv("HOME"); - char *xdg_config_home_default = "/.config"; - xdg_config_home = path_append(home, xdg_config_home_default); - } + char *xdg_config_home = get_XDG_CONFIG_HOME(); full_path = path_append(xdg_config_home, "/httpdirfs/config"); + FREE(xdg_config_home); } else { full_path = config_path; } @@ -316,11 +337,7 @@ parse_arg_list(int argc, char **argv, char ***fuse_argv, int *fuse_argc) curl_slist_append(CONFIG.http_headers, strdup(optarg)); break; case 27: - if (CONFIG.cache_dir) { - CacheSystem_clear(CONFIG.cache_dir); - } else { - CacheSystem_clear(NULL); - } + CacheSystem_clear(); break; default: fprintf(stderr, "see httpdirfs -h for usage\n"); @@ -377,7 +394,9 @@ HTTPDirFS options:\n\ --cache Enable cache (default: off)\n\ --cache-location Set a custom cache location\n\ (default: \"${XDG_CACHE_HOME}/httpdirfs\")\n\ - --cache-clear Clear cache directory and exit\n\ + --cache-clear Delete the cache directory or the custom location\n\ + specifid with `--cache-location`, if the option is\n\ + seen first. Then exit in either case.\n\ --cacert Certificate authority for the server\n\ --dl-seg-size Set cache download segment size, in MB (default: 8)\n\ Note: this setting is ignored if previously\n\ @@ -412,4 +431,4 @@ HTTPDirFS options:\n\ using the insecure username / hex encoded password\n\ scheme\n\ \n"); -} +} \ No newline at end of file