diff options
Diffstat (limited to 'libdwfl/dbgserver-client.c')
-rw-r--r-- | libdwfl/dbgserver-client.c | 109 |
1 files changed, 86 insertions, 23 deletions
diff --git a/libdwfl/dbgserver-client.c b/libdwfl/dbgserver-client.c index 2864d866..5ae8765c 100644 --- a/libdwfl/dbgserver-client.c +++ b/libdwfl/dbgserver-client.c @@ -1,12 +1,16 @@ #include "dbgserver-client.h" #include <assert.h> +#include <dirent.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <errno.h> #include <fcntl.h> +#include <fts.h> #include <string.h> #include <stdbool.h> #include <linux/limits.h> +#include <time.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/stat.h> @@ -15,12 +19,21 @@ #define MAX_BUILD_ID_BYTES 64 #define _(Str) "dbgserver-client: "Str"\n" -const char *url_delim = " "; +/* URLs of dbgservers, separated by url_delim. + This env var must be set for dbgserver-client to run. */ const char *server_urls_envvar = "DBGSERVER_URLS"; +const char *url_delim = " "; + +/* Location of the cache of files downloaded from dbgservers. + The default parent directory is $HOME, or '/' if $HOME doesn't exist. */ const char *cache_path_envvar = "DBGSERVER_CACHE_PATH"; -const char *cache_clean_interval_envvar = "DBGSERVER_CACHE_CLEAN_INTERVAL"; const char *cache_default_name = ".dbgserver_client_cache"; +/* Files will be removed from the cache when the number of seconds + since their st_mtime is greater than or equal to this env var. */ +const char *cache_clean_interval_envvar = "DBGSERVER_CACHE_CLEAN_INTERVAL_S"; +const unsigned long cache_clean_interval_default = 86400; /* 1 day */ + int dbgserver_enabled (void) { @@ -81,38 +94,81 @@ add_file_to_cache (char *cache_path, return fd; } +/* Delete any files that have been unmodied for a period + longer than $DBGSERVER_CACHE_CLEAN_INTERVAL_S. */ void clean_cache(char *cache_path) { - (void) cache_path; - return; + char * const dirs[] = { cache_path, NULL, }; + + FTS *fts = fts_open(dirs, 0, NULL); + if (fts == NULL) + { + if (errno == ENOENT) + { + errno = 0; + return; + } + + fprintf(stderr, _("error cleaning cache, cannot fts_open")); + return; + } + + time_t clean_interval; + const char *interval_str = getenv(cache_clean_interval_envvar); + if (interval_str == NULL + || sscanf(interval_str, "%ld", &clean_interval) != 1) + clean_interval = cache_clean_interval_default; + + FTSENT *f; + DIR *d; + while ((f = fts_read(fts)) != NULL) + { + switch (f->fts_info) + { + case FTS_F: + /* delete file if cache clean interval has been met or exceeded. */ + if (time(NULL) - f->fts_statp->st_mtime >= clean_interval) + remove(f->fts_path); + break; + + case FTS_DP: + d = opendir(f->fts_path); + /* delete directory if it doesn't contain files besides . and .. */ + (void) readdir(d); + (void) readdir(d); + if (readdir(d) == NULL) + remove(f->fts_path); + closedir(d); + break; + + default: + ; + } + } + + fts_close(fts); } int query_server (char *build_id, char *type) { - int fd = -1; - bool success = false; - long resp_code = -1; - long timeout = 5; - char *envvar; - char *server_url; + char *urls_envvar; char *server_urls; char cache_path[PATH_MAX]; char target_cache_dir[PATH_MAX]; char target_cache_path[PATH_MAX]; - CURL *session; - CURLcode curl_res; - envvar = getenv(server_urls_envvar); - if (envvar == NULL) + urls_envvar = getenv(server_urls_envvar); + if (urls_envvar == NULL) { fprintf(stderr, _("cannot find server urls environment variable")); return -1; } - server_urls = malloc(strlen(envvar) + 1); - strcpy(server_urls, envvar); + /* make a copy of the envvar so it can be safely modified. */ + server_urls = malloc(strlen(urls_envvar) + 1); + strcpy(server_urls, urls_envvar); if (server_urls == NULL) { fprintf(stderr, _("out of memory")); @@ -125,7 +181,7 @@ query_server (char *build_id, char *type) return -1; } - session = curl_easy_init(); + CURL *session = curl_easy_init(); if (session == NULL) { fprintf(stderr, _("unable to begin curl session")); @@ -133,7 +189,7 @@ query_server (char *build_id, char *type) return -1; } - /* set paths needed to perform query + /* set paths needed to perform the query example format cache_path: $HOME/.dbgserver_cache @@ -158,7 +214,9 @@ query_server (char *build_id, char *type) strncat(target_cache_path, "/", PATH_MAX - strlen(target_cache_dir)); strncat(target_cache_path, type, PATH_MAX - strlen(target_cache_dir)); - fd = get_file_from_cache(target_cache_path); + clean_cache(cache_path); + + int fd = get_file_from_cache(target_cache_path); if (fd >= 0) return fd; @@ -167,10 +225,13 @@ query_server (char *build_id, char *type) /* encountered an error adding file to cache. */ return -1; - /* query servers until we find the target or run out of urls to try. */ - server_url = strtok(server_urls, url_delim); + long timeout = 5; /* XXX grab from env var. */ + bool success = false; + char *server_url = strtok(server_urls, url_delim); while (! success && server_url != NULL) { + /* query servers until we find the target or run out of urls to try. */ + long resp_code; char *url = malloc(strlen(server_url) + strlen("/buildid//") + strlen(build_id) @@ -190,7 +251,8 @@ query_server (char *build_id, char *type) curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(session, CURLOPT_WRITEDATA, (void*)&fd); curl_easy_setopt(session, CURLOPT_TIMEOUT, timeout); - curl_res = curl_easy_perform(session); + + CURLcode curl_res = curl_easy_perform(session); curl_easy_getinfo(session, CURLINFO_RESPONSE_CODE, &resp_code); if (curl_res == CURLE_OK) @@ -215,10 +277,11 @@ query_server (char *build_id, char *type) { close(fd); remove(target_cache_path); + /* remove any unnecessary directories that were just created. */ + clean_cache(cache_path); return -1; } - clean_cache(cache_path); return fd; } |