switch (uri_get_type(url)) {
case UT_RSYNC:
error = config_get_rsync_enabled()
- ? rsync_download(url)
+ ? rsync_download(uri_get_global(url), uri_get_local(url), true)
: cache_check(url);
break;
case UT_HTTPS:
#include "print_file.h"
#include <errno.h>
+#include <stdlib.h>
+
#include "common.h"
#include "config.h"
#include "file.h"
#include "asn1/content_info.h"
#include "asn1/asn1c/Certificate.h"
#include "asn1/asn1c/CRL.h"
+#include "data_structure/path_builder.h"
+#include "rsync/rsync.h"
#include "types/bio_seq.h"
+#include "types/uri.h"
#define HDRSIZE 32
+static BIO *
+__rsync2bio(char const *src, char const *dst)
+{
+ int error;
+
+ error = rsync_download(src, dst, false);
+ if (error) {
+ pr_op_err("rysnc download failed: %s", strerror(abs(error)));
+ return NULL;
+ }
+
+ return BIO_new_file(dst, "rb");
+}
+
+static BIO *
+rsync2bio_tmpdir(char const *src)
+{
+#define TMPDIR "/tmp/fort-XXXXXX"
+
+ struct path_builder pb;
+ char buf[strlen(TMPDIR) + 1];
+ char *tmpdir;
+ BIO *result = NULL;
+ int error;
+
+ strcpy(buf, TMPDIR);
+ tmpdir = mkdtemp(buf);
+ if (tmpdir == NULL) {
+ pr_op_err("Unable to create " TMPDIR ": %s", strerror(errno));
+ return NULL;
+ }
+
+ pb_init(&pb);
+ error = pb_append(&pb, tmpdir);
+ if (error)
+ goto end;
+ error = pb_append(&pb, strrchr(src, '/') + 1);
+ if (error)
+ goto end;
+
+ result = __rsync2bio(src, pb.string);
+
+end: pb_cleanup(&pb);
+ return result;
+}
+
+static BIO *
+rsync2bio_cache(char const *src)
+{
+ char const *tal;
+ struct rpki_uri *uri;
+ BIO *bio;
+ int error;
+
+ tal = strrchr(config_get_tal(), '/');
+ tal = (tal != NULL) ? (tal + 1) : config_get_tal();
+ uri = NULL;
+
+ error = uri_create(&uri, tal, UT_RSYNC, false, NULL, src);
+ if (error) {
+ pr_op_err("Unparseable rsync URI: %s", strerror(abs(error)));
+ return NULL;
+ }
+
+ bio = __rsync2bio(uri_get_global(uri), uri_get_local(uri));
+
+ uri_refput(uri);
+ return bio;
+}
+
+static BIO *
+rsync2bio(char const *src)
+{
+ return (config_get_tal() && config_get_local_repository())
+ ? rsync2bio_cache(src)
+ : rsync2bio_tmpdir(src);
+}
+
+static BIO *
+filename2bio(char const *filename)
+{
+ if (filename == NULL || strcmp(filename, "-") == 0)
+ return BIO_new_fp(stdin, BIO_NOCLOSE);
+
+ if (str_starts_with(filename, "rsync://"))
+ return rsync2bio(filename);
+
+ return BIO_new_file(filename, "rb");
+}
+
static unsigned char *
skip_sequence(unsigned char *buf, unsigned char *cursor)
{
static int
__print_file(void)
{
- char const *filename;
BIO *bio;
unsigned char hdrbuf[HDRSIZE];
json_t *json = NULL;
int error;
- filename = config_get_payload();
- bio = (filename == NULL || strcmp(filename, "-") == 0)
- ? BIO_new_fp(stdin, BIO_NOCLOSE)
- : BIO_new_file(filename, "rb");
+ bio = filename2bio(config_get_payload());
if (bio == NULL)
return pr_op_err("BIO_new_*() returned NULL.");
}
static void
-prepare_rsync(struct rpki_uri *uri, char ***args, size_t *args_len)
+prepare_rsync(char const *src, char const *dst, char ***args, size_t *args_len)
{
struct string_array const *config_args;
char **copy_args;
for (i = 0; i < config_args->length; i++) {
if (strcmp(config_args->array[i], "$REMOTE") == 0)
- copy_args[i + 1] = pstrdup(uri_get_global(uri));
+ copy_args[i + 1] = pstrdup(src);
else if (strcmp(config_args->array[i], "$LOCAL") == 0)
- copy_args[i + 1] = pstrdup(uri_get_local(uri));
+ copy_args[i + 1] = pstrdup(dst);
else
copy_args[i + 1] = pstrdup(config_args->array[i]);
}
}
/*
- * Downloads the @uri->global file into the @uri->local path.
+ * Downloads @src @dst. @src is supposed to be an rsync URL, and @dst is
+ * supposed to be a filesystem path.
*/
int
-rsync_download(struct rpki_uri *uri)
+rsync_download(char const *src, char const *dst, bool is_directory)
{
char **args;
size_t args_len;
/* Prepare everything for the child exec */
args = NULL;
args_len = 0;
- prepare_rsync(uri, &args, &args_len);
+ prepare_rsync(src, dst, &args, &args_len);
- pr_val_info("rsync: %s", uri_get_global(uri));
+ pr_val_info("rsync: %s", src);
if (log_val_enabled(LOG_DEBUG)) {
pr_val_debug("Executing rsync:");
for (i = 0; i < args_len + 1; i++)
pr_val_debug(" %s", args[i]);
}
- error = mkdir_p(uri_get_local(uri), true);
+ error = mkdir_p(dst, is_directory);
if (error)
goto release_args;
if (retries == config_get_rsync_retry_count()) {
if (retries > 0)
pr_val_warn("Max RSYNC retries (%u) reached on '%s', won't retry again.",
- retries, uri_get_global(uri));
+ retries, src);
error = EIO;
goto release_args;
}
pr_val_warn("Retrying RSYNC '%s' in %u seconds, %u attempts remaining.",
- uri_get_global(uri),
+ src,
config_get_rsync_retry_interval(),
config_get_rsync_retry_count() - retries);
retries++;
#ifndef SRC_RSYNC_RSYNC_H_
#define SRC_RSYNC_RSYNC_H_
-#include "types/uri.h"
+#include <stdbool.h>
-int rsync_download(struct rpki_uri *);
+int rsync_download(char const *, char const *, bool);
#endif /* SRC_RSYNC_RSYNC_H_ */