From: Alberto Leiva Popper Date: Tue, 23 Jul 2024 22:52:20 +0000 (-0600) Subject: Tuesday X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=4a97a408865f4f5637bc1c7208cb6d19e8ad0d4b;p=thirdparty%2FFORT-validator.git Tuesday --- diff --git a/src/cache/cachent.c b/src/cache/cachent.c index 190414e9..7e122724 100644 --- a/src/cache/cachent.c +++ b/src/cache/cachent.c @@ -7,76 +7,57 @@ #include "types/url.h" struct cache_node * -cachent_create_root(char const *schema) +cachent_create_root(bool https) { struct cache_node *root; root = pzalloc(sizeof(struct cache_node)); - root->url = pstrdup(schema); - root->name = root->url; + root->url = pstrdup(https ? "https://" : "rsync://"); + root->path = join_paths(config_get_local_repository(), + https ? "https" : "rsync"); + root->name = strrchr(root->path, '/') + 1; return root; } /* Preorder. @cb returns whether the children should be traversed. */ int -cachent_traverse(struct cache_node *root, - bool (*cb)(struct cache_node *, char const *)) +cachent_traverse(struct cache_node *root, bool (*cb)(struct cache_node *)) { struct cache_node *iter_start; struct cache_node *parent, *child; struct cache_node *tmp; - struct path_builder pb; int error; if (!root) return 0; - pb_init(&pb); - - error = pb_append(&pb, config_get_local_repository()); - if (error) - goto end; - - error = pb_append(&pb, root->name); - if (error) - goto end; - if (!cb(root, pb.string)) - goto end; + if (!cb(root)) + return error; parent = root; iter_start = parent->children; if (iter_start == NULL) - goto end; + return error; reloop: /* iter_start must not be NULL */ HASH_ITER(hh, iter_start, child, tmp) { - error = pb_append(&pb, child->name); - if (error) - goto end; - - if (cb(child, pb.string) && (child->children != NULL)) { + if (cb(child) && (child->children != NULL)) { parent = child; iter_start = parent->children; goto reloop; } - - pb_pop(&pb, true); } parent = iter_start->parent; do { if (parent == NULL) - goto end; - pb_pop(&pb, true); + return error; iter_start = parent->hh.next; parent = parent->parent; } while (iter_start == NULL); goto reloop; - -end: pb_cleanup(&pb); - return error; } static struct cache_node * @@ -124,6 +105,7 @@ provide(struct cache_node *parent, char const *url, char const *name, size_t namelen) { struct cache_node *child; + size_t pathlen; child = find_child(parent, name, namelen); if (child != NULL) @@ -131,6 +113,12 @@ provide(struct cache_node *parent, char const *url, child = pzalloc(sizeof(struct cache_node)); child->url = pstrndup(url, name - url + namelen); + + pathlen = strlen(parent->path) + namelen + 2; + child->path = pmalloc(pathlen); + if (snprintf(child->path, pathlen, "%s/%.*s", parent->path, (int)namelen, name) >= pathlen) + pr_crit("aaaaaa"); // XXX + child->name = child->url + (name - url); if ((parent->flags & RSYNC_INHERIT) == RSYNC_INHERIT) child->flags = RSYNC_INHERIT; @@ -168,7 +156,7 @@ cachent_provide(struct cache_node *ancestor, char const *url) for (i = 0; ancestor->url[i] != 0; i++) if (ancestor->url[i] != normal[i]) goto fail; - if (normal[i] != '/' && normal[i] != '\0') + if (i != RPKI_SCHEMA_LEN && normal[i] != '/' && normal[i] != '\0') goto fail; token_init(&tkn, normal + i); @@ -185,9 +173,11 @@ fail: free(normal); static void __delete_node_cb(struct cache_node const *); #endif -static void +static int __delete_node(struct cache_node *node) { + int valid = node->flags & CNF_VALID; + #ifdef UNIT_TESTING __delete_node_cb(node); #endif @@ -195,17 +185,23 @@ __delete_node(struct cache_node *node) if (node->parent != NULL) HASH_DEL(node->parent->children, node); free(node->url); - free(node->tmpdir); + free(node->path); + free(node->tmppath); free(node); + + return valid; } -void +int cachent_delete(struct cache_node *node) { struct cache_node *parent; + int valid; if (!node) - return; + return 0; + + valid = node->flags & CNF_VALID; parent = node->parent; if (parent != NULL) { @@ -218,9 +214,11 @@ cachent_delete(struct cache_node *node) node = node->children; parent = node->parent; - __delete_node(node); + valid |= __delete_node(node); node = parent; } while (node != NULL); + + return valid; } static void @@ -241,7 +239,7 @@ print_node(struct cache_node *node, unsigned int tabs) printf("%s", (node->flags & CNF_VALID) ? "valid " : ""); printf("%s", (node->flags & CNF_NOTIFICATION) ? "notification " : ""); printf("%s", (node->flags & CNF_WITHDRAWN) ? "withdrawn " : ""); - printf(" -- %s", node->tmpdir); + printf(" -- %s", node->tmppath); printf("\n"); HASH_ITER(hh, node->children, child, tmp) diff --git a/src/cache/cachent.h b/src/cache/cachent.h index 94beb66e..26c514e5 100644 --- a/src/cache/cachent.h +++ b/src/cache/cachent.h @@ -31,6 +31,8 @@ * Did it validate successfully (at least once) during the current cycle? * (It's technically possible for two different repositories to map to the same * cache node. One of them is likely going to fail validation.) + * This only refers to the tmp path; The final path, if it exists, always + * contains valid objects (until expiration). */ #define CNF_VALID (1 << 5) /* Is the node an RRDP Update Notification? */ @@ -47,24 +49,23 @@ // XXX rename to cache_entity or cachent struct cache_node { - char const *name; /* Points to the last component of @url XXX redundant */ - char *url; /* Normalized */ - int flags; + char *url; /* rsync://a.b.c/d/e (normalized) */ + char *path; /* path/to/cache/rsync/a.b.c/d/e */ + char const *name; /* Points to the last component of @url or @path XXX redundant */ + int flags; /* CNF_* */ int dlerr; /* Result code of recent download attempt */ time_t mtim; /* Last successful download time, or zero */ /* - * If flags & CNF_FRESH, path to the temporal directory where we - * downloaded the latest refresh. + * If download attempted, path to the temporal directory where the + * refresh was dumped. * (See --compare-dest at rsync(1). RRDP is basically the same.) - * Otherwise undefined. - * - * XXX this is not always a directory; rename to "tmppath" + * Otherwise NULL. */ - char *tmpdir; + char *tmppath; /* path/to/cache/tmp/1234 */ - /* Only if flags & CNF_NOTIFICATION */ +// /* Only if flags & CNF_NOTIFICATION */ // struct cachefile_notification notif; struct cache_node *parent; /* Tree parent */ @@ -73,15 +74,14 @@ struct cache_node { UT_hash_handle hh; /* Hash table hook */ }; -struct cache_node *cachent_create_root(char const *); +struct cache_node *cachent_create_root(bool); -int cachent_traverse(struct cache_node *, - bool (*cb)(struct cache_node *, char const *)); +int cachent_traverse(struct cache_node *, bool (*cb)(struct cache_node *)); struct cache_node *cachent_find(struct cache_node *, char const *, struct cache_node **); struct cache_node *cachent_provide(struct cache_node *, char const *); -void cachent_delete(struct cache_node *); +int cachent_delete(struct cache_node *); /* Recursive; tests only. */ void cachent_print(struct cache_node *); diff --git a/src/cache/local_cache.c b/src/cache/local_cache.c index d64ada59..716d705c 100644 --- a/src/cache/local_cache.c +++ b/src/cache/local_cache.c @@ -339,8 +339,8 @@ cache_tmpfile(char **filename) static void load_tal_json(void) { - cache.rsync = cachent_create_root("rsync"); - cache.https = cachent_create_root("https"); + cache.rsync = cachent_create_root(false); + cache.https = cachent_create_root(true); // char *filename; // json_t *root; @@ -525,7 +525,7 @@ static int dl_rsync(struct cache_node *rpp) { struct cache_node *module, *node; - char *path; + char *tmppath; int error; if (!config_get_rsync_enabled()) { @@ -537,20 +537,20 @@ dl_rsync(struct cache_node *rpp) if (module == NULL) return -EINVAL; // XXX - error = cache_tmpfile(&path); + error = cache_tmpfile(&tmppath); if (error) return error; - // XXX looks like the third argument is redundant now. - error = rsync_download(module->url, path, true); + error = rsync_download(module->url, tmppath, + (module->flags & CNF_CACHED) ? module->path : NULL); if (error) { - free(path); + free(tmppath); return error; } module->flags |= CNF_RSYNC | CNF_CACHED | CNF_FRESH; module->mtim = time(NULL); // XXX catch -1 - module->tmpdir = path; + module->tmppath = tmppath; for (node = rpp; node != module; node = node->parent) { node->flags |= RSYNC_INHERIT; @@ -563,7 +563,7 @@ dl_rsync(struct cache_node *rpp) static int dl_http(struct cache_node *node) { - char *path; + char *tmppath; bool changed; int error; @@ -572,13 +572,13 @@ dl_http(struct cache_node *node) return 1; } - error = cache_tmpfile(&path); + error = cache_tmpfile(&tmppath); if (error) return error; - error = http_download(node->url, path, node->mtim, &changed); + error = http_download(node->url, tmppath, node->mtim, &changed); if (error) { - free(path); + free(tmppath); return error; } @@ -587,7 +587,7 @@ dl_http(struct cache_node *node) node->flags |= CNF_CHANGED; node->mtim = time(NULL); // XXX catch -1 } - node->tmpdir = path; + node->tmppath = tmppath; return 0; } @@ -727,7 +727,7 @@ prune_rsync(void) HASH_ITER(hh, domain->children, module, tmp2) HASH_ITER(hh, module->children, child, tmp3) { pr_op_debug("Removing leftover: %s", child->url); - cachent_delete(child); + module->flags |= cachent_delete(child); } } @@ -736,7 +736,7 @@ prune_rsync(void) * XXX result is redundant */ static bool -commit_rpp_delta(struct cache_node *node, char const *path) +commit_rpp_delta(struct cache_node *node) { struct cache_node *child, *tmp; int error; @@ -748,7 +748,7 @@ commit_rpp_delta(struct cache_node *node, char const *path) goto branch; } - if (node->tmpdir == NULL) { + if (node->tmppath == NULL) { if (node->children) { pr_op_debug("Branch."); goto branch; @@ -760,7 +760,7 @@ commit_rpp_delta(struct cache_node *node, char const *path) if (node->flags & CNF_VALID) { pr_op_debug("Validation successful; committing."); - error = file_merge_into(node->tmpdir, path); + error = file_merge_into(node->tmppath, node->path); if (error) printf("rename errno: %d\n", error); // XXX /* XXX Think more about the implications of this. */ @@ -769,17 +769,17 @@ commit_rpp_delta(struct cache_node *node, char const *path) } else { pr_op_debug("Validation unsuccessful; rollbacking."); /* XXX just do remove()? */ - file_rm_f(node->tmpdir); + file_rm_f(node->tmppath); } - free(node->tmpdir); - node->tmpdir = NULL; + free(node->tmppath); + node->tmppath = NULL; return true; branch: node->flags = 0; - if (node->tmpdir) { - free(node->tmpdir); - node->tmpdir = NULL; + if (node->tmppath) { + free(node->tmppath); + node->tmppath = NULL; } return true; } @@ -1024,10 +1024,10 @@ remove_abandoned(void) } static bool -remove_orphaned(struct cache_node *node, char const *path) +remove_orphaned(struct cache_node *node) { - if (file_exists(path) == ENOENT) { - pr_op_debug("Missing file; deleting node: %s", path); + if (file_exists(node->path) == ENOENT) { + pr_op_debug("Missing file; deleting node: %s", node->path); cachent_delete(node); return false; } diff --git a/src/config.c b/src/config.c index eb4d5e2d..700677d6 100644 --- a/src/config.c +++ b/src/config.c @@ -88,10 +88,7 @@ struct rpki_config { unsigned int interval; } retry; char *program; - struct { - struct string_array flat; /* Deprecated */ - struct string_array recursive; - } args; + struct string_array args; } rsync; struct { @@ -489,20 +486,17 @@ static const struct option_field options[] = { .id = 3006, .name = "rsync.arguments-recursive", .type = >_string_array, - .offset = offsetof(struct rpki_config, rsync.args.recursive), - .doc = "RSYNC program arguments", + .offset = offsetof(struct rpki_config, rsync.args), + .doc = "Deprecated; does nothing.", .availability = AVAILABILITY_JSON, - /* Unlimited */ - .max = 0, + .deprecated = true, }, { .id = 3007, .name = "rsync.arguments-flat", .type = >_string_array, - .offset = offsetof(struct rpki_config, rsync.args.flat), + .offset = offsetof(struct rpki_config, rsync.args), .doc = "Deprecated; does nothing.", .availability = AVAILABILITY_JSON, - /* Unlimited */ - .max = 0, .deprecated = true, }, @@ -929,18 +923,7 @@ print_config(void) static void set_default_values(void) { - static char const *recursive_rsync_args[] = { - "-rtz", "--delete", "--omit-dir-times", - - "--contimeout=20", "--max-size=20MB", "--timeout=15", - - "--include=*/", "--include=*.cer", "--include=*.crl", - "--include=*.gbr", "--include=*.mft", "--include=*.roa", - "--exclude=*", - - "$REMOTE", "$LOCAL", - }; - static char const *flat_rsync_args[] = { "" }; + static char const *trash[] = { "" }; static char const *addrs[] = { #ifdef __linux__ "::" @@ -978,10 +961,7 @@ set_default_values(void) rpki_config.rsync.retry.count = 1; rpki_config.rsync.retry.interval = 4; rpki_config.rsync.program = pstrdup("rsync"); - string_array_init(&rpki_config.rsync.args.flat, - flat_rsync_args, ARRAY_LEN(flat_rsync_args)); - string_array_init(&rpki_config.rsync.args.recursive, - recursive_rsync_args, ARRAY_LEN(recursive_rsync_args)); + string_array_init(&rpki_config.rsync.args, trash, ARRAY_LEN(trash)); rpki_config.http.enabled = true; /* Higher priority than rsync by default */ @@ -1382,12 +1362,6 @@ config_get_rsync_program(void) return rpki_config.rsync.program; } -struct string_array const * -config_get_rsync_args(void) -{ - return &rpki_config.rsync.args.recursive; -} - bool config_get_http_enabled(void) { diff --git a/src/config.h b/src/config.h index 6f14fc40..719bf541 100644 --- a/src/config.h +++ b/src/config.h @@ -48,7 +48,6 @@ unsigned int config_get_rsync_priority(void); unsigned int config_get_rsync_retry_count(void); unsigned int config_get_rsync_retry_interval(void); char *config_get_rsync_program(void); -struct string_array const *config_get_rsync_args(void); bool config_get_http_enabled(void); unsigned int config_get_http_priority(void); unsigned int config_get_http_retry_count(void); diff --git a/src/print_file.c b/src/print_file.c index 8e8e6e0a..3a80a158 100644 --- a/src/print_file.c +++ b/src/print_file.c @@ -21,7 +21,8 @@ __rsync2bio(char const *src, char const *dst) { int error; - error = rsync_download(src, dst, false); + // XXX use the cache + error = rsync_download(src, dst, NULL); if (error) { pr_op_err("rysnc download failed: %s", strerror(abs(error))); return NULL; diff --git a/src/rrdp.c b/src/rrdp.c index 2dc024ce..3983176c 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -13,7 +13,7 @@ #include "log.h" #include "thread_var.h" #include "http/http.h" -#include "cache/cache_entity.h" +#include "cache/cachent.h" #include "crypto/base64.h" #include "crypto/hash.h" #include "xml/relax_ng.h" @@ -768,13 +768,13 @@ xml_read_notif(xmlTextReaderPtr reader, void *arg) } static int -parse_notification(struct cache_node *node, struct update_notification *result) +parse_notification(struct cache_node *notif, struct update_notification *result) { int error; - update_notification_init(result, node->url); + update_notification_init(result, notif->url); - error = relax_ng_parse(node->tmpdir, xml_read_notif, result); + error = relax_ng_parse(notif->tmppath, xml_read_notif, result); if (error) update_notification_cleanup(result); @@ -1086,6 +1086,34 @@ update_notif(struct cachefile_notification *old, struct update_notification *new return 0; } +static int +dl_notif(struct cache_node *notif) +{ + char *tmppath; + bool changed; + int error; + + error = cache_tmpfile(&tmppath); + if (error) + return error; + + error = http_download(notif->url, tmppath, notif->mtim, &changed); + if (error) { + free(tmppath); + return error; + } + + // XXX notif->flags |= CNF_CACHED | CNF_FRESH; + if (changed) { + notif->mtim = time(NULL); // XXX + notif->tmppath = tmppath; + } else { + free(tmppath); + } + + return 0; +} + /* * Downloads the Update Notification @notif, and updates the cache accordingly. * @@ -1095,7 +1123,6 @@ update_notif(struct cachefile_notification *old, struct update_notification *new int rrdp_update(struct cache_node *notif) { - char *path = NULL; struct cachefile_notification *old; struct update_notification new; int serial_cmp; @@ -1104,25 +1131,37 @@ rrdp_update(struct cache_node *notif) fnstack_push(notif->url); pr_val_debug("Processing notification."); - error = http_download_cache_node(notif); + /////////////////////////////////////////////////////////////////////// + + error = dl_notif(notif); if (error) goto end; - if (!(notif->flags & CNF_CHANGED)) { + if (!notif->tmppath) { pr_val_debug("The Notification has not changed."); - rpp->flags |= CNF_FRESH; /* Success */ goto end; } error = parse_notification(notif, &new); if (error) goto end; + + remove(notif->tmppath); // XXX + if (mkdir(notif->tmppath) == -1) { + error = errno; + pr_val_err("Can't create notification's temporal directory: %s", + strerror(error)); + goto clean_notif; + } + + /////////////////////////////////////////////////////////////////////// + pr_val_debug("New session/serial: %s/%s", new.session.session_id, new.session.serial.str); if (!(notif->flags & CNF_NOTIFICATION)) { pr_val_debug("This is a new Notification."); - error = handle_snapshot(&new, rpp); + error = handle_snapshot(&new, notif); if (error) goto clean_notif; @@ -1178,7 +1217,6 @@ clean_notif: update_notification_cleanup(&new); end: - free(path); fnstack_pop(); return error; } diff --git a/src/rsync/rsync.c b/src/rsync/rsync.c index 7359664b..1b94076a 100644 --- a/src/rsync/rsync.c +++ b/src/rsync/rsync.c @@ -32,48 +32,34 @@ duplicate_fds(int fds[2][2]) } static void -release_args(char **args, unsigned int size) +prepare_rsync(char *args, char const *src, char const *dst, char const *cmpdst) { - unsigned int i; - - /* args[0] wasn't allocated */ - for (i = 1; i < size + 1; i++) - free(args[i]); - free(args); -} - -static void -prepare_rsync(char const *src, char const *dst, char ***args, size_t *args_len) -{ - struct string_array const *config_args; - char **copy_args; - unsigned int i; - - config_args = config_get_rsync_args(); - /* - * We need to work on a copy, because the config args are immutable, - * and we need to add the program name (for some reason) and NULL - * elements, and replace $REMOTE and $LOCAL. - */ - copy_args = pcalloc(config_args->length + 2, sizeof(char *)); - - copy_args[0] = config_get_rsync_program(); - copy_args[config_args->length + 1] = NULL; - - memcpy(copy_args + 1, config_args->array, - config_args->length * sizeof(char *)); - - for (i = 0; i < config_args->length; i++) { - if (strcmp(config_args->array[i], "$REMOTE") == 0) - copy_args[i + 1] = pstrdup(src); - else if (strcmp(config_args->array[i], "$LOCAL") == 0) - copy_args[i + 1] = pstrdup(dst); - else - copy_args[i + 1] = pstrdup(config_args->array[i]); + size_t i = 0; + + /* XXX review */ + args[i++] = config_get_rsync_program(); + args[i++] = "-rtz"; + args[i++] = "--omit-dir-times"; + args[i++] = "--contimeout"; + args[i++] = "20"; + args[i++] = "--max-size"; + args[i++] = "20MB"; + args[i++] = "--timeout"; + args[i++] = "15"; + args[i++] = "--include=*/"; + args[i++] = "--include=*.cer"; + args[i++] = "--include=*.crl"; + args[i++] = "--include=*.gbr"; + args[i++] = "--include=*.mft"; + args[i++] = "--include=*.roa"; + args[i++] = "--exclude=*"; + if (cmpdst) { + args[i++] = "--compare-dest"; + args[i++] = cmpdst; } - - *args = copy_args; - *args_len = config_args->length; + args[i++] = src; + args[i++] = dst; + args[i++] = NULL; } __dead static void @@ -202,15 +188,11 @@ read_pipes(int fds[2][2]) return read_pipe(fds, 1); } -/* - * Downloads @src @dst. @src is supposed to be an rsync URL, and @dst is - * supposed to be a filesystem path. - */ +/* rsync [--compare-dest @cmpdst] @src @dst */ int -rsync_download(char const *src, char const *dst, bool is_directory) +rsync_download(char const *src, char const *dst, char const *cmpdst) { - char **args; - size_t args_len; + char *args[32]; /* Descriptors to pipe stderr (first element) and stdout (second) */ int fork_fds[2][2]; pid_t child_pid; @@ -220,20 +202,18 @@ rsync_download(char const *src, char const *dst, bool is_directory) int error; /* Prepare everything for the child exec */ - args = NULL; - args_len = 0; - prepare_rsync(src, dst, &args, &args_len); + prepare_rsync(&args, src, dst, cmpdst); 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++) + for (i = 0; args[i] != NULL; i++) pr_val_debug(" %s", args[i]); } - error = mkdir_p(dst, is_directory, 0777); + error = mkdir_p(dst, true, 0777); if (error) - goto release_args; + return error; retries = 0; do { @@ -241,7 +221,7 @@ rsync_download(char const *src, char const *dst, bool is_directory) error = create_pipes(fork_fds); if (error) - goto release_args; + return error; /* Flush output (avoid locks between father and child) */ log_flush(); @@ -270,7 +250,7 @@ rsync_download(char const *src, char const *dst, bool is_directory) close(fork_fds[1][0]); close(fork_fds[0][1]); close(fork_fds[1][1]); - goto release_args; + return error; } /* This code is run by us. */ @@ -286,7 +266,7 @@ rsync_download(char const *src, char const *dst, bool is_directory) error, strerror(error)); if (child_status > 0) break; - goto release_args; + return error; } } while (0); @@ -296,14 +276,13 @@ rsync_download(char const *src, char const *dst, bool is_directory) pr_val_debug("The rsync sub-process terminated with error code %d.", error); if (!error) - goto release_args; + return 0; 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, src); - error = EIO; - goto release_args; + return EIO; } pr_val_warn("Retrying RSYNC '%s' in %u seconds, %u attempts remaining.", src, @@ -316,8 +295,6 @@ rsync_download(char const *src, char const *dst, bool is_directory) break; } while (true); - release_args(args, args_len); - if (WIFSIGNALED(child_status)) { switch (WTERMSIG(child_status)) { case SIGINT: @@ -339,8 +316,4 @@ rsync_download(char const *src, char const *dst, bool is_directory) pr_op_err_st("The RSYNC command died in a way I don't have a handler for. Dunno; guess I'll die as well."); return -EINVAL; -release_args: - /* The happy path also falls here */ - release_args(args, args_len); - return error; } diff --git a/src/rsync/rsync.h b/src/rsync/rsync.h index 3476c9c0..52781eed 100644 --- a/src/rsync/rsync.h +++ b/src/rsync/rsync.h @@ -1,8 +1,6 @@ #ifndef SRC_RSYNC_RSYNC_H_ #define SRC_RSYNC_RSYNC_H_ -#include - -int rsync_download(char const *, char const *, bool); +int rsync_download(char const *, char const *, char const *); #endif /* SRC_RSYNC_RSYNC_H_ */ diff --git a/src/types/url.c b/src/types/url.c index a8bab970..6d89f8b6 100644 --- a/src/types/url.c +++ b/src/types/url.c @@ -13,14 +13,14 @@ path_rewind(char const *root, char *cursor) } /* - * Collapses '//', '.' and '..'. Also removes the colon from the schema. + * Collapses '//' (except from the schema), '.' and '..'. * - * "rsync://a.b/./c//.././/d/." -> "rsync/a.b/d" + * "rsync://a.b/./c//.././/d/." -> "rsync://a.b/d" */ char * url_normalize(char const *url) { - char *normal, *dst, *root; + char *normal, *dst; struct tokenizer tkn; if (strncmp(url, "rsync://", RPKI_SCHEMA_LEN) && @@ -28,16 +28,14 @@ url_normalize(char const *url) return NULL; normal = pstrdup(url); - root = normal + 5; - *root = '/'; - dst = root + 1; + dst = normal + RPKI_SCHEMA_LEN; token_init(&tkn, url + RPKI_SCHEMA_LEN); while (token_next(&tkn)) { if (tkn.len == 1 && tkn.str[0] == '.') continue; if (tkn.len == 2 && tkn.str[0] == '.' && tkn.str[1] == '.') { - dst = path_rewind(root, dst); + dst = path_rewind(normal + RPKI_SCHEMA_LEN, dst); if (!dst) goto fail; continue; @@ -48,7 +46,7 @@ url_normalize(char const *url) } /* Reject URL if there's nothing after the schema. Maybe unnecessary. */ - if (dst == root + 1) + if (dst == normal + RPKI_SCHEMA_LEN) goto fail; dst[-1] = '\0'; diff --git a/test/cache/cachent_test.c b/test/cache/cachent_test.c index 16fa632a..9f4c9d49 100644 --- a/test/cache/cachent_test.c +++ b/test/cache/cachent_test.c @@ -7,7 +7,7 @@ #include "mock.c" #include "types/url.c" -static char deleted[16][5]; +static char deleted[16][6]; static unsigned int dn; static void @@ -20,14 +20,14 @@ START_TEST(test_delete) { struct cache_node *root, *a, *b; - a = unode("a", NULL); + a = runode("a", NULL); dn = 0; cachent_delete(a); ck_assert_uint_eq(1, dn); ck_assert_str_eq("a", deleted[0]); - a = unode("a", NULL); - root = unode("root", a, NULL); + a = runode("a", NULL); + root = runode("", a, NULL); dn = 0; cachent_delete(a); ck_assert_ptr_eq(NULL, root->children); @@ -37,25 +37,25 @@ START_TEST(test_delete) dn = 0; cachent_delete(root); ck_assert_uint_eq(1, dn); - ck_assert_str_eq("root", deleted[0]); - - b = unode("b", - unode("c", NULL), - unode("d", NULL), - unode("e", NULL), - unode("f", NULL), NULL); - a = unode("a", + ck_assert_str_eq("rsync", deleted[0]); + + b = runode("a/b", + runode("a/b/c", NULL), + runode("a/b/d", NULL), + runode("a/b/e", NULL), + runode("a/b/f", NULL), NULL); + a = runode("a", b, - unode("g", - unode("h", - unode("i", NULL), NULL), - unode("j", - unode("k", NULL), NULL), - unode("l", - unode("m", NULL), NULL), - unode("n", - unode("o", NULL), NULL), NULL), NULL); - root = unode("root", a, NULL); + runode("a/g", + runode("a/g/h", + runode("a/g/h/i", NULL), NULL), + runode("a/g/j", + runode("a/g/j/k", NULL), NULL), + runode("a/g/l", + runode("a/g/l/m", NULL), NULL), + runode("a/g/n", + runode("a/g/n/o", NULL), NULL), NULL), NULL); + root = runode("", a, NULL); dn = 0; cachent_delete(b); @@ -83,7 +83,7 @@ START_TEST(test_delete) dn = 0; cachent_delete(root); ck_assert_uint_eq(1, dn); - ck_assert_str_eq("root", deleted[0]); + ck_assert_str_eq("rsync", deleted[0]); } END_TEST @@ -91,9 +91,9 @@ static char const *expected[32]; static unsigned int e; static bool -ck_traverse_cb(struct cache_node *node, char const *path) +ck_traverse_cb(struct cache_node *node) { - ck_assert_str_eq(expected[e++], path); + ck_assert_str_eq(expected[e++], node->path); return true; } @@ -124,102 +124,102 @@ START_TEST(test_traverse) root = NULL; ck_traverse(root, NULL); - root = unode("a", NULL); - ck_traverse(root, "tmp/a", NULL); + root = runode("a", NULL); + ck_traverse(root, "tmp/rsync/a", NULL); - root = unode("a", - unode("b", NULL), NULL); - ck_traverse(root, "tmp/a", "tmp/a/b", NULL); + root = runode("a", + runode("a/b", NULL), NULL); + ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", NULL); - root = unode("a", - unode("b", - unode("c", NULL), NULL), NULL); + root = runode("a", + runode("a/b", + runode("a/b/c", NULL), NULL), NULL); ck_traverse(root, - "tmp/a", - "tmp/a/b", - "tmp/a/b/c", NULL); - - root = unode("a", - unode("b", - unode("c", NULL), - unode("d", NULL), NULL), NULL); + "tmp/rsync/a", + "tmp/rsync/a/b", + "tmp/rsync/a/b/c", NULL); + + root = runode("a", + runode("a/b", + runode("a/b/c", NULL), + runode("a/b/d", NULL), NULL), NULL); ck_traverse(root, - "tmp/a", - "tmp/a/b", - "tmp/a/b/c", - "tmp/a/b/d", NULL); - - root = unode("a", - unode("b", - unode("c", NULL), - unode("d", NULL), NULL), - unode("e", NULL), NULL); + "tmp/rsync/a", + "tmp/rsync/a/b", + "tmp/rsync/a/b/c", + "tmp/rsync/a/b/d", NULL); + + root = runode("a", + runode("a/b", + runode("a/b/c", NULL), + runode("a/b/d", NULL), NULL), + runode("a/e", NULL), NULL); ck_traverse(root, - "tmp/a", - "tmp/a/b", - "tmp/a/b/c", - "tmp/a/b/d", - "tmp/a/e", NULL); - - root = unode("a", - unode("b", NULL), - unode("c", - unode("d", NULL), - unode("e", NULL), NULL), NULL); + "tmp/rsync/a", + "tmp/rsync/a/b", + "tmp/rsync/a/b/c", + "tmp/rsync/a/b/d", + "tmp/rsync/a/e", NULL); + + root = runode("a", + runode("a/b", NULL), + runode("a/c", + runode("a/c/d", NULL), + runode("a/c/e", NULL), NULL), NULL); ck_traverse(root, - "tmp/a", - "tmp/a/b", - "tmp/a/c", - "tmp/a/c/d", - "tmp/a/c/e", NULL); - - root = unode("a", - unode("b", - unode("c", NULL), - unode("d", NULL), NULL), - unode("e", - unode("f", NULL), - unode("g", NULL), NULL), NULL); + "tmp/rsync/a", + "tmp/rsync/a/b", + "tmp/rsync/a/c", + "tmp/rsync/a/c/d", + "tmp/rsync/a/c/e", NULL); + + root = runode("a", + runode("a/b", + runode("a/b/c", NULL), + runode("a/b/d", NULL), NULL), + runode("a/e", + runode("a/e/f", NULL), + runode("a/e/g", NULL), NULL), NULL); ck_traverse(root, - "tmp/a", - "tmp/a/b", - "tmp/a/b/c", - "tmp/a/b/d", - "tmp/a/e", - "tmp/a/e/f", - "tmp/a/e/g", NULL); - - root = unode("a", - unode("b", - unode("c", NULL), - unode("d", NULL), - unode("e", NULL), - unode("f", NULL), NULL), - unode("g", - unode("h", - unode("i", NULL), NULL), - unode("j", - unode("k", NULL), NULL), - unode("l", - unode("m", NULL), NULL), - unode("n", - unode("o", NULL), NULL), NULL), NULL); + "tmp/rsync/a", + "tmp/rsync/a/b", + "tmp/rsync/a/b/c", + "tmp/rsync/a/b/d", + "tmp/rsync/a/e", + "tmp/rsync/a/e/f", + "tmp/rsync/a/e/g", NULL); + + root = runode("a", + runode("a/b", + runode("a/b/c", NULL), + runode("a/b/d", NULL), + runode("a/b/e", NULL), + runode("a/b/f", NULL), NULL), + runode("a/g", + runode("a/g/h", + runode("a/g/h/i", NULL), NULL), + runode("a/g/j", + runode("a/g/j/k", NULL), NULL), + runode("a/g/l", + runode("a/g/l/m", NULL), NULL), + runode("a/g/n", + runode("a/g/n/o", NULL), NULL), NULL), NULL); ck_traverse(root, - "tmp/a", - "tmp/a/b", - "tmp/a/b/c", - "tmp/a/b/d", - "tmp/a/b/e", - "tmp/a/b/f", - "tmp/a/g", - "tmp/a/g/h", - "tmp/a/g/h/i", - "tmp/a/g/j", - "tmp/a/g/j/k", - "tmp/a/g/l", - "tmp/a/g/l/m", - "tmp/a/g/n", - "tmp/a/g/n/o", NULL); + "tmp/rsync/a", + "tmp/rsync/a/b", + "tmp/rsync/a/b/c", + "tmp/rsync/a/b/d", + "tmp/rsync/a/b/e", + "tmp/rsync/a/b/f", + "tmp/rsync/a/g", + "tmp/rsync/a/g/h", + "tmp/rsync/a/g/h/i", + "tmp/rsync/a/g/j", + "tmp/rsync/a/g/j/k", + "tmp/rsync/a/g/l", + "tmp/rsync/a/g/l/m", + "tmp/rsync/a/g/n", + "tmp/rsync/a/g/n/o", NULL); } END_TEST @@ -227,26 +227,30 @@ START_TEST(test_provide) { struct cache_node *rsync, *abc, *d, *e, *f, *g, *h, *ee; - rsync = cachent_create_root("rsync"); + rsync = cachent_create_root(false); ck_assert_ptr_ne(NULL, rsync); ck_assert_ptr_eq(NULL, rsync->parent); - ck_assert_str_eq("rsync", rsync->url); + ck_assert_str_eq("rsync://", rsync->url); + ck_assert_str_eq("tmp/rsync", rsync->path); ck_assert_str_eq("rsync", rsync->name); /* Create branch chain from root */ e = cachent_provide(rsync, "rsync://a.b.c/d/e"); ck_assert_ptr_ne(NULL, e); - ck_assert_str_eq("rsync/a.b.c/d/e", e->url); + ck_assert_str_eq("rsync://a.b.c/d/e", e->url); + ck_assert_str_eq("tmp/rsync/a.b.c/d/e", e->path); ck_assert_str_eq("e", e->name); d = e->parent; ck_assert_ptr_ne(NULL, d); - ck_assert_str_eq("rsync/a.b.c/d", d->url); + ck_assert_str_eq("rsync://a.b.c/d", d->url); + ck_assert_str_eq("tmp/rsync/a.b.c/d", d->path); ck_assert_str_eq("d", d->name); abc = d->parent; ck_assert_ptr_ne(NULL, abc); - ck_assert_str_eq("rsync/a.b.c", abc->url); + ck_assert_str_eq("rsync://a.b.c", abc->url); + ck_assert_str_eq("tmp/rsync/a.b.c", abc->path); ck_assert_str_eq("a.b.c", abc->name); ck_assert_ptr_eq(rsync, abc->parent); @@ -267,32 +271,36 @@ START_TEST(test_provide) /* Some not normalized noise */ ck_assert_ptr_eq(e, cachent_provide(e, "rsync://a.b.c/d/e////")); ck_assert_ptr_eq(e, cachent_provide(e, "rsync://a.b.c///d/./e//")); - ck_assert_ptr_eq(e, cachent_provide(e, "rsync://a/../z/../a.b.c/d/e/")); + ck_assert_ptr_eq(e, cachent_provide(e, "rsync://a.b.c/d/f/../e/")); /* Create sibling from root */ f = cachent_provide(rsync, "rsync://a.b.c/f"); ck_assert_ptr_ne(NULL, f); ck_assert_ptr_eq(abc, f->parent); - ck_assert_str_eq("rsync/a.b.c/f", f->url); + ck_assert_str_eq("rsync://a.b.c/f", f->url); + ck_assert_str_eq("tmp/rsync/a.b.c/f", f->path); ck_assert_str_eq("f", f->name); /* Create more than one descendant from root */ h = cachent_provide(rsync, "rsync://a.b.c/f/g/h"); ck_assert_ptr_ne(NULL, h); - ck_assert_str_eq("rsync/a.b.c/f/g/h", h->url); + ck_assert_str_eq("rsync://a.b.c/f/g/h", h->url); + ck_assert_str_eq("tmp/rsync/a.b.c/f/g/h", h->path); ck_assert_str_eq("h", h->name); g = h->parent; ck_assert_ptr_ne(NULL, g); ck_assert_ptr_eq(f, g->parent); - ck_assert_str_eq("rsync/a.b.c/f/g", g->url); + ck_assert_str_eq("rsync://a.b.c/f/g", g->url); + ck_assert_str_eq("tmp/rsync/a.b.c/f/g", g->path); ck_assert_str_eq("g", g->name); /* Try to create a conflict by prefix */ ee = cachent_provide(rsync, "rsync://a.b.c/d/ee"); ck_assert_ptr_ne(e, ee); ck_assert_ptr_eq(d, ee->parent); - ck_assert_str_eq("rsync/a.b.c/d/ee", ee->url); + ck_assert_str_eq("rsync://a.b.c/d/ee", ee->url); + ck_assert_str_eq("tmp/rsync/a.b.c/d/ee", ee->path); ck_assert_str_eq("ee", ee->name); ck_assert_ptr_eq(e, cachent_provide(abc, "rsync://a.b.c/d/e")); ck_assert_ptr_eq(ee, cachent_provide(abc, "rsync://a.b.c/d/ee")); diff --git a/test/cache/local_cache_test.c b/test/cache/local_cache_test.c index be5371d0..3a9ff488 100644 --- a/test/cache/local_cache_test.c +++ b/test/cache/local_cache_test.c @@ -1,7 +1,4 @@ -/* - * This test will create some temporal directories on "/tmp". - * Needs permissions. - */ +/* This will create some test files in "tmp/". Needs permissions. */ #include //#include @@ -32,7 +29,7 @@ __delete_node_cb(struct cache_node const *node) } int -rsync_download(char const *src, char const *dst, bool is_directory) +rsync_download(char const *src, char const *dst, char const *cmpdir) { char cmd[64]; @@ -167,16 +164,17 @@ run_cleanup(void) } static bool -ck_path(struct cache_node *node, char const *_) +ck_path(struct cache_node *node) { int error; - if (!node->tmpdir) + if (!node->tmppath) return true; - error = file_exists(node->tmpdir); + error = file_exists(node->tmppath); if (error) - ck_abort_msg("Missing file in cache: %s (%s)", node->tmpdir, strerror(error)); + ck_abort_msg("Missing file in cache: %s (%s)", node->tmppath, + strerror(error)); return true; } @@ -189,12 +187,13 @@ ck_assert_cachent_eq(struct cache_node *expected, struct cache_node *actual) PR_DEBUG_MSG("Comparing %s vs %s", expected->url, actual->url); ck_assert_str_eq(expected->url, actual->url); + ck_assert_str_eq(expected->path, actual->path); ck_assert_str_eq(expected->name, actual->name); ck_assert_int_eq(expected->flags, actual->flags); - if (expected->tmpdir) - ck_assert_str_eq(expected->tmpdir, actual->tmpdir); + if (expected->tmppath) + ck_assert_str_eq(expected->tmppath, actual->tmppath); else - ck_assert_ptr_eq(NULL, actual->tmpdir); + ck_assert_ptr_eq(NULL, actual->tmppath); HASH_ITER(hh, expected->children, echild, tmp) { HASH_FIND(hh, actual->children, echild->name, @@ -244,22 +243,22 @@ ck_cache(struct cache_node *rsync, struct cache_node *https) static void ck_cache_rsync(struct cache_node *rsync) { - ck_cache(rsync, unode("https", NULL)); + ck_cache(rsync, hunode("", NULL)); } static void ck_cache_https(struct cache_node *https) { - ck_cache(unode("rsync", NULL), https); + ck_cache(runode("", NULL), https); } static time_t epoch; static bool -unfreshen(struct cache_node *node, char const *path) +unfreshen(struct cache_node *node) { PR_DEBUG_MSG("Unfreshening %s.", node->url); - node->flags &= ~CNF_FRESH; + node->flags &= ~(CNF_FRESH | CNF_CHANGED | CNF_VALID); node->mtim = epoch; return true; } @@ -316,7 +315,7 @@ cleanup_test(void) static const int DOWNLOADED = CNF_RSYNC | CNF_CACHED | CNF_FRESH; static const int VALIDATED = RSYNC_INHERIT | CNF_VALID; static const int FULL = DOWNLOADED | VALIDATED; -static const int STALE = CNF_RSYNC | CNF_CACHED | CNF_VALID; +static const int STALE = CNF_RSYNC | CNF_CACHED; /* Intermediary between a downloaded and a validated node */ static const int BRANCH = RSYNC_INHERIT; static const int FAILED = CNF_FRESH; @@ -325,29 +324,32 @@ START_TEST(test_cache_download_rsync) { setup_test(); + printf("==== Startup ====\n"); run_dl_rsync("rsync://a.b.c/d", 0, 1); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL)); /* Redownload same file, nothing should happen */ + printf("==== Redownload sample file ====\n"); run_dl_rsync("rsync://a.b.c/d", 0, 0); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL)); /* * rsyncs are recursive, which means if we've been recently asked to * download d, we needn't bother redownloading d/e. */ + printf("==== Don't redownload child ====\n"); run_dl_rsync("rsync://a.b.c/d/e", 0, 0); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", - ufnode("rsync/a.b.c/d/e", VALIDATED, NULL), NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", + rufnode("a.b.c/d/e", VALIDATED, NULL), NULL), NULL), NULL)); /* * rsyncs get truncated, because it results in much faster @@ -355,30 +357,32 @@ START_TEST(test_cache_download_rsync) * This is not defined in any RFCs; it's an effective standard, * and there would be consequences for violating it. */ + printf("==== rsync truncated ====\n"); run_dl_rsync("rsync://x.y.z/m/n/o", 0, 1); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", - ufnode("rsync/a.b.c/d/e", VALIDATED, NULL), NULL), NULL), - unode("rsync/x.y.z", - uftnode("rsync/x.y.z/m", DOWNLOADED, "tmp/tmp/1", - ufnode("rsync/x.y.z/m/n", BRANCH, - ufnode("rsync/x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", + rufnode("a.b.c/d/e", VALIDATED, NULL), NULL), NULL), + runode("x.y.z", + ruftnode("x.y.z/m", DOWNLOADED, "tmp/tmp/1", + rufnode("x.y.z/m/n", BRANCH, + rufnode("x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL)); /* Sibling */ + printf("==== Sibling ====\n"); run_dl_rsync("rsync://a.b.c/e/f", 0, 1); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", - ufnode("rsync/a.b.c/d/e", VALIDATED, NULL), NULL), - uftnode("rsync/a.b.c/e", DOWNLOADED, "tmp/tmp/2", - ufnode("rsync/a.b.c/e/f", VALIDATED, NULL), NULL), NULL), - unode("rsync/x.y.z", - uftnode("rsync/x.y.z/m", DOWNLOADED, "tmp/tmp/1", - ufnode("rsync/x.y.z/m/n", BRANCH, - ufnode("rsync/x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", + rufnode("a.b.c/d/e", VALIDATED, NULL), NULL), + ruftnode("a.b.c/e", DOWNLOADED, "tmp/tmp/2", + rufnode("a.b.c/e/f", VALIDATED, NULL), NULL), NULL), + runode("x.y.z", + ruftnode("x.y.z/m", DOWNLOADED, "tmp/tmp/1", + rufnode("x.y.z/m/n", BRANCH, + rufnode("x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL)); cleanup_test(); } @@ -393,27 +397,27 @@ START_TEST(test_cache_download_rsync_error) dl_error = -EINVAL; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 1); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), - ufnode("rsync/a.b.c/e", FAILED, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", NULL), + rufnode("a.b.c/e", FAILED, NULL), NULL), NULL)); /* Regardless of error, not reattempted because same iteration */ dl_error = EINVAL; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 0); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), - ufnode("rsync/a.b.c/e", FAILED, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", NULL), + rufnode("a.b.c/e", FAILED, NULL), NULL), NULL)); dl_error = 0; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 0); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), - ufnode("rsync/a.b.c/e", FAILED, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", NULL), + rufnode("a.b.c/e", FAILED, NULL), NULL), NULL)); cleanup_test(); } @@ -433,10 +437,10 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/d", FULL, NULL), - ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/d", FULL, NULL), + rufnode("a.b.c/e", FULL, NULL), NULL), NULL)); /* One iteration with no changes, for paranoia */ printf("==== No changes, for paranoia ====\n"); @@ -445,10 +449,10 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/d", FULL, NULL), - ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/d", FULL, NULL), + rufnode("a.b.c/e", FULL, NULL), NULL), NULL)); /* Add one sibling */ printf("==== Add one sibling ====\n"); @@ -458,22 +462,22 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/f", 0, 1); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/d", FULL, NULL), - ufnode("rsync/a.b.c/e", FULL, NULL), - ufnode("rsync/a.b.c/f", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/d", FULL, NULL), + rufnode("a.b.c/e", FULL, NULL), + rufnode("a.b.c/f", FULL, NULL), NULL), NULL)); /* Nodes don't get updated, but they're still too young. */ printf("==== Still too young ====\n"); new_iteration(false); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/d", STALE, NULL), - ufnode("rsync/a.b.c/e", STALE, NULL), - ufnode("rsync/a.b.c/f", STALE, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/d", STALE, NULL), + rufnode("a.b.c/e", STALE, NULL), + rufnode("a.b.c/f", STALE, NULL), NULL), NULL)); /* Remove some branches */ printf("==== Remove some branches ====\n"); @@ -481,9 +485,9 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/d", 0, 1); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/d", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/d", FULL, NULL), NULL), NULL)); /* Remove old branch and add sibling at the same time */ printf("==== Remove old branch + add sibling ====\n"); @@ -491,9 +495,9 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/e", FULL, NULL), NULL), NULL)); /* Try child */ printf("==== Try child ====\n"); @@ -501,9 +505,9 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e/f/g", 0, 1); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/e", FULL, NULL), NULL), NULL)); /* Parent again */ printf("==== Parent again ====\n"); @@ -511,15 +515,15 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/e", FULL, NULL), NULL), NULL)); /* Empty the tree */ printf("==== Empty the tree ====\n"); new_iteration(true); run_cleanup(); - ck_cache_rsync(unode("rsync", NULL)); + ck_cache_rsync(runode("", NULL)); /* Node exists, but file doesn't */ @@ -528,22 +532,22 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_dl_rsync("rsync://a.b.c/f", 0, 1); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/e", FULL, "tmp/tmp/B", NULL), - uftnode("rsync/a.b.c/f", FULL, "tmp/tmp/C", NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/e", FULL, "tmp/tmp/B", NULL), + ruftnode("a.b.c/f", FULL, "tmp/tmp/C", NULL), NULL), NULL)); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/e", FULL, NULL), - ufnode("rsync/a.b.c/f", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/e", FULL, NULL), + rufnode("a.b.c/f", FULL, NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/rsync/a.b.c/f")); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/e", FULL, NULL), NULL), NULL)); cleanup_test(); } @@ -554,45 +558,51 @@ START_TEST(test_cache_cleanup_rsync_error) setup_test(); /* Set up */ + printf("==== Set up ====\n"); dl_error = 0; run_dl_rsync("rsync://a.b.c/d", 0, 1); dl_error = -EINVAL; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 1); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), - ufnode("rsync/a.b.c/e", FAILED, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + ruftnode("a.b.c/d", FULL, "tmp/tmp/0", NULL), + rufnode("a.b.c/e", FAILED, NULL), NULL), NULL)); /* Node gets deleted because cached file doesn't exist */ + printf("==== Node deleted because file not found ====\n"); run_cleanup(); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/d", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/d", FULL, NULL), NULL), NULL)); /* * Node and file do not get deleted, because the failure is still not * that old. * Deletion does not depend on success or failure. */ + printf("==== Node and file preserved because young ====\n"); new_iteration(false); dl_error = -EINVAL; run_dl_rsync("rsync://a.b.c/d", -EINVAL, 1); ck_cache_rsync( - unode("rsync", - unode("rsync/a.b.c", - ufnode("rsync/a.b.c/d", FULL, NULL), NULL), NULL)); + runode("", + runode("a.b.c", + rufnode("a.b.c/d", DOWNLOADED, NULL), NULL), NULL)); /* Error is old; gets deleted */ + printf("==== Error deleted because old ====\n"); new_iteration(true); run_cleanup(); - ck_cache_rsync(unode("rsync", NULL)); + ck_cache_rsync(runode("", NULL)); cleanup_test(); } END_TEST +/* XXX ================================================================ */ + static const int HDOWNLOADED = CNF_CACHED | CNF_FRESH | CNF_CHANGED; static const int HVALIDATED = CNF_CACHED | CNF_VALID; static const int HFULL = HDOWNLOADED | HVALIDATED; @@ -605,30 +615,30 @@ START_TEST(test_cache_download_https) /* Download *file* e. */ run_dl_https("https://a.b.c/d/e", 0, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - unode("https/a.b.c/d", - uftnode("https/a.b.c/d/e", HFULL, "tmp/tmp/0", NULL), NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hunode("a.b.c/d", + huftnode("a.b.c/d/e", HFULL, "tmp/tmp/0", NULL), NULL), NULL), NULL)); /* Download something else 1 */ run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - unode("https/a.b.c/d", - uftnode("https/a.b.c/d/e", HFULL, "tmp/tmp/0", NULL), NULL), - uftnode("https/a.b.c/e", HFULL, "tmp/tmp/1", NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hunode("a.b.c/d", + huftnode("a.b.c/d/e", HFULL, "tmp/tmp/0", NULL), NULL), + huftnode("a.b.c/e", HFULL, "tmp/tmp/1", NULL), NULL), NULL)); /* Download something else 2 */ run_dl_https("https://x.y.z/e", 0, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - unode("https/a.b.c/d", - uftnode("https/a.b.c/d/e", HFULL, "tmp/tmp/0", NULL), NULL), - uftnode("https/a.b.c/e", HFULL, "tmp/tmp/1", NULL), NULL), - unode("https/x.y.z", - uftnode("https/x.y.z/e", HFULL, "tmp/tmp/2", NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hunode("a.b.c/d", + huftnode("a.b.c/d/e", HFULL, "tmp/tmp/0", NULL), NULL), + huftnode("a.b.c/e", HFULL, "tmp/tmp/1", NULL), NULL), + hunode("x.y.z", + huftnode("x.y.z/e", HFULL, "tmp/tmp/2", NULL), NULL), NULL)); cleanup_test(); } @@ -643,10 +653,10 @@ START_TEST(test_cache_download_https_error) dl_error = -EINVAL; run_dl_https("https://a.b.c/e", -EINVAL, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - uftnode("https/a.b.c/d", HFULL, "tmp/tmp/0", NULL), - uftnode("https/a.b.c/e", HFAILED, NULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + huftnode("a.b.c/d", HFULL, "tmp/tmp/0", NULL), + huftnode("a.b.c/e", HFAILED, NULL, NULL), NULL), NULL)); /* Regardless of error, not reattempted because same iteration */ dl_error = -EINVAL; @@ -654,10 +664,10 @@ START_TEST(test_cache_download_https_error) dl_error = 0; run_dl_https("https://a.b.c/e", -EINVAL, 0); ck_cache_https( - unode("https", - unode("https/a.b.c", - uftnode("https/a.b.c/d", HFULL, "tmp/tmp/0", NULL), - uftnode("https/a.b.c/e", HFAILED, NULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + huftnode("a.b.c/d", HFULL, "tmp/tmp/0", NULL), + huftnode("a.b.c/e", HFAILED, NULL, NULL), NULL), NULL)); cleanup_test(); } @@ -675,39 +685,39 @@ START_TEST(test_cache_cleanup_https) run_dl_https("https://a.b.c/e", 0, 1); run_cleanup(); ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/d", HFULL, NULL), - ufnode("https/a.b.c/e", HFULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/d", HFULL, NULL), + hufnode("a.b.c/e", HFULL, NULL), NULL), NULL)); /* Remove one branch */ new_iteration(true); run_dl_https("https://a.b.c/d", 0, 1); run_cleanup(); ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/d", HFULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/d", HFULL, NULL), NULL), NULL)); /* Change the one branch */ new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); run_cleanup(); ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/e", HFULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/e", HFULL, NULL), NULL), NULL)); /* Add a child to the same branch, do not update the old one */ new_iteration(true); run_dl_https("https://a.b.c/e/f/g", 0, 1); run_cleanup(); ck_cache_https( - unode("https", - unode("https/a.b.c", - unode("https/a.b.c/e", - unode("https/a.b.c/e/f", - ufnode("https/a.b.c/e/f/g", HFULL, NULL), NULL), NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hunode("a.b.c/e", + hunode("a.b.c/e/f", + hufnode("a.b.c/e/f/g", HFULL, NULL), NULL), NULL), NULL), NULL)); /* * Download parent, do not update child. @@ -717,154 +727,173 @@ START_TEST(test_cache_cleanup_https) run_dl_https("https://a.b.c/e/f", 0, 1); run_cleanup(); ck_cache_https( - unode("https", - unode("https/a.b.c", - unode("https/a.b.c/e", - ufnode("https/a.b.c/e/f", HFULL, NULL), NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hunode("a.b.c/e", + hufnode("a.b.c/e/f", HFULL, NULL), NULL), NULL), NULL)); /* Do it again. */ new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); run_cleanup(); ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/e", HFULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/e", HFULL, NULL), NULL), NULL)); /* Empty the tree */ new_iteration(true); run_cleanup(); - ck_cache_https(unode("https", NULL)); + ck_cache_https(hunode("", NULL)); /* Node exists, but file doesn't */ new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); run_dl_https("https://a.b.c/f/g/h", 0, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - uftnode("https/a.b.c/e", HFULL, "tmp/tmp/7", NULL), - unode("https/a.b.c/f", - unode("https/a.b.c/f/g", - uftnode("https/a.b.c/f/g/h", HFULL, "tmp/tmp/8", NULL), NULL), NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + huftnode("a.b.c/e", HFULL, "tmp/tmp/7", NULL), + hunode("a.b.c/f", + hunode("a.b.c/f/g", + huftnode("a.b.c/f/g/h", HFULL, "tmp/tmp/8", NULL), NULL), NULL), NULL), NULL)); run_cleanup(); /* Move from tmp/tmp to tmp/https */ ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/e", HFULL, NULL), - unode("https/a.b.c/f", - unode("https/a.b.c/f/g", - ufnode("https/a.b.c/f/g/h", HFULL, NULL), NULL), NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/e", HFULL, NULL), + hunode("a.b.c/f", + hunode("a.b.c/f/g", + hufnode("a.b.c/f/g/h", HFULL, NULL), NULL), NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/https/a.b.c/f/g/h")); run_cleanup(); /* Actual test */ ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/e", HFULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/e", HFULL, NULL), NULL), NULL)); /* Temporal version disappears before we get a commit */ new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - uftnode("https/a.b.c/e", HFULL, "tmp/tmp/9", NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + huftnode("a.b.c/e", HFULL, "tmp/tmp/9", NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/tmp/9")); run_cleanup(); - ck_cache_https(unode("https", NULL)); + ck_cache_https(hunode("", NULL)); /* Temporal version disappears after we get a commit */ new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - uftnode("https/a.b.c/e", HFULL, "tmp/tmp/A", NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + huftnode("a.b.c/e", HFULL, "tmp/tmp/A", NULL), NULL), NULL)); run_cleanup(); /* Commit */ ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/e", HFULL, NULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/e", HFULL, NULL, NULL), NULL), NULL)); new_iteration(false); run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - unode("https", - unode("https/a.b.c", - uftnode("https/a.b.c/e", HFULL, "tmp/tmp/B", NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + huftnode("a.b.c/e", HFULL, "tmp/tmp/B", NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/tmp/B")); run_cleanup(); ck_cache_https( - unode("https", - unode("https/a.b.c", - ufnode("https/a.b.c/e", HFULL, NULL), NULL), NULL)); + hunode("", + hunode("a.b.c", + hufnode("a.b.c/e", HFULL, NULL), NULL), NULL)); cleanup_test(); } END_TEST -//START_TEST(test_cache_cleanup_https_error) -//{ -// setup_test(); -// -// /* Set up */ -// dl_error = false; -// run_dl_https("https://a.b.c/d", 0, 1); -// dl_error = true; -// run_dl_https("https://a.b.c/e", -EINVAL, 1); -// ck_cache( -// NODE("https://a.b.c/d", 0, 1, 1), -// NODE("https://a.b.c/e", -EINVAL, 0, 0), -// NULL); -// -// /* Deleted because file ENOENT. */ -// run_cleanup(); -// ck_cache( -// NODE("https://a.b.c/d", 0, 1, 1), -// NULL); -// -// /* Fail d */ -// new_iteration(false); -// dl_error = true; -// run_dl_https("https://a.b.c/d", -EINVAL, 1); -// ck_cache(NODE("https://a.b.c/d", -EINVAL, 1, 1), NULL); -// -// /* Not deleted, because not old */ -// new_iteration(false); -// run_cleanup(); -// ck_cache(NODE("https://a.b.c/d", -EINVAL, 1, 1), NULL); -// -// /* Become old */ -// new_iteration(true); -// run_cleanup(); -// ck_cache(NULL); -// -// cleanup_test(); -//} -//END_TEST -// -//START_TEST(test_dots) -//{ -// setup_test(); -// -// run_cache_download("https://a.b.c/d", 0, 0, 1); -// ck_cache(NODE("https://a.b.c/d", 0, 1, 1), NULL); -// -// run_cache_download("https://a.b.c/d/.", 0, 0, 0); -// ck_cache(NODE("https://a.b.c/d", 0, 1, 1), NULL); -// -// run_cache_download("https://a.b.c/d/e/..", 0, 0, 0); -// ck_cache(NODE("https://a.b.c/d", 0, 1, 1), NULL); -// -// run_cache_download("https://a.b.c/./d/../e", 0, 0, 1); -// ck_cache( -// NODE("https://a.b.c/d", 0, 1, 1), -// NODE("https://a.b.c/./d/../e", 0, 1, 1), -// NULL); -// -// cleanup_test(); -//} -//END_TEST +START_TEST(test_cache_cleanup_https_error) +{ + setup_test(); + + /* Set up */ + dl_error = 0; + run_dl_https("https://a.b.c/d", 0, 1); + dl_error = -EINVAL; + run_dl_https("https://a.b.c/e", -EINVAL, 1); + PR_DEBUG; + ck_cache_https( + hunode("", + hunode("a.b.c", + huftnode("a.b.c/d", HFULL, "tmp/tmp/0", NULL), + hufnode("a.b.c/e", HFAILED, NULL), NULL), NULL)); + + /* Deleted because file ENOENT. */ + run_cleanup(); + ck_cache_https( + hunode("", + hunode("a.b.c", + hufnode("a.b.c/d", HFULL, NULL), NULL), NULL)); + + /* Fail d */ + new_iteration(false); + dl_error = -EINVAL; + run_dl_https("https://a.b.c/d", -EINVAL, 1); + ck_cache_https( + hunode("", + hunode("a.b.c", + hufnode("a.b.c/d", CNF_CACHED | CNF_FRESH, NULL), NULL), NULL)); + + /* Not deleted, because not old */ + new_iteration(false); + run_cleanup(); + ck_cache_https( + hunode("", + hunode("a.b.c", + hufnode("a.b.c/d", CNF_CACHED, NULL), NULL), NULL)); + + /* Become old */ + new_iteration(true); + run_cleanup(); + ck_cache_https(hunode("", NULL)); + + cleanup_test(); +} +END_TEST + +START_TEST(test_dots) +{ + setup_test(); + + run_dl_https("https://a.b.c/d", 0, 1); + ck_cache_https( + hunode("", + hunode("a.b.c", + huftnode("a.b.c/d", HFULL, "tmp/tmp/0", NULL), NULL), NULL)); + + run_dl_https("https://a.b.c/d/.", 0, 0); + ck_cache_https( + hunode("", + hunode("a.b.c", + huftnode("a.b.c/d", HFULL, "tmp/tmp/0", NULL), NULL), NULL)); + + run_dl_https("https://a.b.c/d/e/..", 0, 0); + ck_cache_https( + hunode("", + hunode("a.b.c", + huftnode("a.b.c/d", HFULL, "tmp/tmp/0", NULL), NULL), NULL)); + + run_dl_https("https://a.b.c/./d/../e", 0, 1); + ck_cache_https( + hunode("", + hunode("a.b.c", + huftnode("a.b.c/d", HFULL, "tmp/tmp/0", NULL), + huftnode("a.b.c/e", HFULL, "tmp/tmp/1", NULL), NULL), NULL)); + + cleanup_test(); +} +END_TEST // //START_TEST(test_tal_json) //{ @@ -937,7 +966,7 @@ END_TEST // } // va_end(args); //} -// + //#define PREPARE_MAP_LIST(maps, ...) prepare_map_list(maps, ##__VA_ARGS__, NULL) // //START_TEST(test_recover) @@ -1062,19 +1091,19 @@ static Suite *thread_pool_suite(void) TCase *rsync, *https, *dot, *meta, *recover; rsync = tcase_create("rsync"); -// tcase_add_test(rsync, test_cache_download_rsync); -// tcase_add_test(rsync, test_cache_download_rsync_error); -// tcase_add_test(rsync, test_cache_cleanup_rsync); -// tcase_add_test(rsync, test_cache_cleanup_rsync_error); + tcase_add_test(rsync, test_cache_download_rsync); + tcase_add_test(rsync, test_cache_download_rsync_error); + tcase_add_test(rsync, test_cache_cleanup_rsync); + tcase_add_test(rsync, test_cache_cleanup_rsync_error); https = tcase_create("https"); -// tcase_add_test(https, test_cache_download_https); -// tcase_add_test(https, test_cache_download_https_error); + tcase_add_test(https, test_cache_download_https); + tcase_add_test(https, test_cache_download_https_error); tcase_add_test(https, test_cache_cleanup_https); -// tcase_add_test(https, test_cache_cleanup_https_error); + tcase_add_test(https, test_cache_cleanup_https_error); dot = tcase_create("dot"); -// tcase_add_test(dot, test_dots); + tcase_add_test(dot, test_dots); meta = tcase_create(TAL_METAFILE); // tcase_add_test(meta, test_tal_json); diff --git a/test/cache/util.c b/test/cache/util.c index 682383a8..6acbb829 100644 --- a/test/cache/util.c +++ b/test/cache/util.c @@ -3,19 +3,27 @@ #include #include "data_structure/uthash.h" -struct cache_node * -vnode(char const *url, int flags, char const *tmpdir, va_list children) +static struct cache_node * +node(char const *schema, char const *path, int flags, char const *tmpdir, + va_list children) { struct cache_node *result; struct cache_node *child; + char buffer[64]; char const *slash; result = pzalloc(sizeof(struct cache_node)); - result->url = pstrdup(url); - slash = strrchr(url, '/'); - result->name = slash ? (slash + 1) : result->url; + + ck_assert(snprintf(buffer, 64, "%s://%s", schema, path) < 64); + result->url = pstrdup(buffer); + slash = (path[0] == 0) ? "" : "/"; + ck_assert(snprintf(buffer, 64, "tmp/%s%s%s", schema, slash, path) < 64); + result->path = pstrdup(buffer); + + result->name = strrchr(result->path, '/') + 1; + ck_assert_ptr_ne(NULL, result->name); result->flags = flags; - result->tmpdir = tmpdir ? pstrdup(tmpdir) : NULL; + result->tmppath = tmpdir ? pstrdup(tmpdir) : NULL; while ((child = va_arg(children, struct cache_node *)) != NULL) { HASH_ADD_KEYPTR(hh, result->children, child->name, @@ -27,39 +35,78 @@ vnode(char const *url, int flags, char const *tmpdir, va_list children) } struct cache_node * -uftnode(char const *url, int flags, char const *tmpdir, ...) +ruftnode(char const *path, int flags, char const *tmpdir, ...) +{ + struct cache_node *result; + va_list children; + + va_start(children, tmpdir); + result = node("rsync", path, flags, tmpdir, children); + va_end(children); + + return result; +} + +struct cache_node * +rufnode(char const *path, int flags, ...) +{ + struct cache_node *result; + va_list children; + + va_start(children, flags); + result = node("rsync", path, flags, NULL, children); + va_end(children); + + return result; +} + +struct cache_node * +runode(char const *path, ...) +{ + struct cache_node *result; + va_list children; + + va_start(children, path); + result = node("rsync", path, 0, NULL, children); + va_end(children); + + return result; +} + +struct cache_node * +huftnode(char const *path, int flags, char const *tmpdir, ...) { struct cache_node *result; va_list children; va_start(children, tmpdir); - result = vnode(url, flags, tmpdir, children); + result = node("https", path, flags, tmpdir, children); va_end(children); return result; } struct cache_node * -ufnode(char const *url, int flags, ...) +hufnode(char const *path, int flags, ...) { struct cache_node *result; va_list children; va_start(children, flags); - result = vnode(url, flags, NULL, children); + result = node("https", path, flags, NULL, children); va_end(children); return result; } struct cache_node * -unode(char const *url, ...) +hunode(char const *path, ...) { struct cache_node *result; va_list children; - va_start(children, url); - result = vnode(url, 0, NULL, children); + va_start(children, path); + result = node("https", path, 0, NULL, children); va_end(children); return result; diff --git a/test/cache/util.h b/test/cache/util.h index 4ff43efa..4e350c8d 100644 --- a/test/cache/util.h +++ b/test/cache/util.h @@ -4,9 +4,12 @@ #include #include "cache/cachent.h" -struct cache_node *vnode(char const *, int, char const *, va_list); -struct cache_node *uftnode(char const *, int , char const *, ...); -struct cache_node *ufnode(char const *, int , ...); -struct cache_node *unode(char const *, ...); +struct cache_node *ruftnode(char const *, int , char const *, ...); +struct cache_node *rufnode(char const *, int , ...); +struct cache_node *runode(char const *, ...); + +struct cache_node *huftnode(char const *, int , char const *, ...); +struct cache_node *hufnode(char const *, int , ...); +struct cache_node *hunode(char const *, ...); #endif /* TEST_CACHE_UTIL_H_ */ diff --git a/test/types/url_test.c b/test/types/url_test.c index 763843b1..ec5d57a7 100644 --- a/test/types/url_test.c +++ b/test/types/url_test.c @@ -15,19 +15,22 @@ START_TEST(test_normalize) { char *normal; - TEST_NORMALIZE("rsync://a.b.c", "rsync/a.b.c"); - TEST_NORMALIZE("rsync://a.b.c/", "rsync/a.b.c"); - TEST_NORMALIZE("rsync://a.b.c//////", "rsync/a.b.c"); - TEST_NORMALIZE("rsync://a.b.c/d/e", "rsync/a.b.c/d/e"); - TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync/a.b.c/d/e"); - TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync/a.b.c/d/e"); - TEST_NORMALIZE("rsync://a.b.c/d/./e/.", "rsync/a.b.c/d/e"); - TEST_NORMALIZE("rsync://a.b.c/d/../d/../d/e/", "rsync/a.b.c/d/e"); - TEST_NORMALIZE("rsync://a.b.c/../x/y/z", "rsync/x/y/z"); - TEST_NORMALIZE("rsync://x//y/z/../../../m/./n/o", "rsync/m/n/o"); + TEST_NORMALIZE("rsync://a.b.c", "rsync://a.b.c"); + TEST_NORMALIZE("rsync://a.b.c/", "rsync://a.b.c"); + TEST_NORMALIZE("rsync://a.b.c//////", "rsync://a.b.c"); + TEST_NORMALIZE("rsync://a.b.c/d/e", "rsync://a.b.c/d/e"); + TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync://a.b.c/d/e"); + TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync://a.b.c/d/e"); + TEST_NORMALIZE("rsync://a.b.c/d/./e/.", "rsync://a.b.c/d/e"); + TEST_NORMALIZE("rsync://a.b.c/x/../x/y/z", "rsync://a.b.c/x/y/z"); + TEST_NORMALIZE("rsync://a.b.c/d/../d/../d/e/", "rsync://a.b.c/d/e"); + TEST_NORMALIZE("rsync://x//y/z/../../m/./n/o", "rsync://x/m/n/o"); ck_assert_ptr_eq(NULL, url_normalize("rsync://")); + ck_assert_ptr_eq(NULL, url_normalize("rsync://.")); ck_assert_ptr_eq(NULL, url_normalize("rsync://..")); ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/..")); + ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/../x")); + ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/../x/y/z")); ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/d/e/../../..")); ck_assert_ptr_eq(NULL, url_normalize("abcde://a.b.c/d")); }