summaryrefslogtreecommitdiff
path: root/libdwfl/dbgserver-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwfl/dbgserver-client.c')
-rw-r--r--libdwfl/dbgserver-client.c109
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;
}