]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Remove the path builder
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 8 Oct 2024 21:11:24 +0000 (15:11 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 8 Oct 2024 22:57:31 +0000 (16:57 -0600)
This has become overkill since design 5 and chdir() trivialized cache
pathing.

12 files changed:
src/cachetmp.c
src/cachetmp.h
src/init.c
src/object/manifest.c
src/print_file.c
src/rrdp.c
src/types/path.c
src/types/path.h
src/types/url.c
src/types/url.h
test/Makefile.am
test/types/path_test.c [deleted file]

index 856248f4ace1f440a3971bf77d7b07e5461f02a5..b9cccc8d007bacf1b95e5a653e62a578be2552ac 100644 (file)
@@ -1,40 +1,31 @@
 #include "cachetmp.h"
 
 #include <stdatomic.h>
+#include <stdio.h>
 
+#include "log.h"
 #include "types/path.h"
 
 static atomic_uint file_counter;
 
 /*
- * Returns a unique temporary file name in the local cache. Note, it's a name,
- * and it's pretty much reserved. The file itself will not be created.
+ * Returns (in @buf, which needs to length CACHE_TMPFILE_BUFLEN) a unique
+ * temporary file name in the local cache.
+ * Note, it's a name, and it's pretty much reserved. The file itself will not be
+ * created.
  *
  * The file will not be automatically deleted when it is closed or the program
  * terminates.
- *
- * The name of the function is inherited from tmpfile(3).
- *
- * The resulting string needs to be released.
  */
-int
-cache_tmpfile(char **filename)
+void
+cache_tmpfile(char *buf)
 {
-       struct path_builder pb;
-       int error;
-
-       pb_init(&pb);
-
-       error = pb_append(&pb, CACHE_TMPDIR);
-       if (error)
-               goto fail;
-       error = pb_append_u32(&pb, atomic_fetch_add(&file_counter, 1u));
-       if (error)
-               goto fail;
+       unsigned int next;
+       int written;
 
-       *filename = pb.string;
-       return 0;
+       next = atomic_fetch_add(&file_counter, 1u);
 
-fail:  pb_cleanup(&pb);
-       return error;
+       written = snprintf(buf, CACHE_TMPFILE_BUFLEN, CACHE_TMPDIR "/%X", next);
+       if (written >= CACHE_TMPFILE_BUFLEN)
+               pr_crit("I ran out of temporal directories: %u", next);
 }
index dec35d11b8882a7d2733067079e55fac43e4c613..af1c9d0a7c3612d33d721a5122410d354db1b00a 100644 (file)
@@ -2,7 +2,8 @@
 #define SRC_CACHETMP_H_
 
 #define CACHE_TMPDIR "tmp"
+#define CACHE_TMPFILE_BUFLEN 24 /* tmp/%X\0 */
 
-int cache_tmpfile(char **);    /* Return new unique path in <cache>/tmp/ */
+void cache_tmpfile(char *);    /* Return new unique path in <cache>/tmp/ */
 
 #endif /* SRC_CACHETMP_H_ */
index 4faf458735ed62e03d7f8b4565577b6ee02dfb2e..9839152b024d3b290edf3f358f9f8eca1b17a8f4 100644 (file)
@@ -7,35 +7,20 @@
 static int
 fetch_url(char const *url, char const *filename)
 {
-       struct path_builder pb;
+       char *path;
        int error;
 
-       pb_init(&pb);
-       error = pb_append(&pb, config_get_tal());
-       if (error)
-               goto pbfail;
-       error = pb_append(&pb, filename);
-       if (error)
-               goto pbfail;
-
-       error = http_download_direct(url, pb.string);
-       if (error)
-               goto dlfail;
-
-       fprintf(stdout, "Successfully fetched '%s'!\n\n", pb.string);
-       pb_cleanup(&pb);
-       return 0;
+       path = path_join(config_get_tal(), filename);
 
-pbfail:
-       fprintf(stderr, "Cannot determine destination path: %s\n",
-               strerror(abs(error)));
-       pb_cleanup(&pb);
-       return error;
+       error = http_download_direct(url, path);
+       if (error) {
+               fprintf(stderr, "Couldn't fetch '%s': %s\n",
+                   path, strerror(abs(error)));
+               goto end;
+       }
 
-dlfail:
-       fprintf(stderr, "Couldn't fetch '%s': %s\n", pb.string,
-               strerror(abs(error)));
-       pb_cleanup(&pb);
+       fprintf(stdout, "Successfully fetched '%s'!\n\n", path);
+end:   free(path);
        return error;
 }
 
index 221483d2d1d29e6b9ac6ff93b3460d86bfbf25ab..6700c123d223f21bdc11874a8bc7b9b88177e3b6 100644 (file)
@@ -12,6 +12,7 @@
 #include "object/signed_object.h"
 #include "thread_var.h"
 #include "types/path.h"
+#include "types/url.h"
 
 static int
 decode_manifest(struct signed_object *sobj, struct Manifest **result)
@@ -270,7 +271,7 @@ build_rpp(char const *mft_url, struct Manifest *mft, struct cache_cage *cage,
        shuffle_mft_files(mft);
 
        rpp = &parent->rpp;
-       rpp_url = path_parent(mft_url);
+       rpp_url = url_parent(mft_url); // XXX
        rpp->nfiles = mft->fileList.list.count;
        rpp->files = pzalloc(rpp->nfiles * sizeof(*rpp->files));
 
@@ -287,7 +288,7 @@ build_rpp(char const *mft_url, struct Manifest *mft, struct cache_cage *cage,
                if (error)
                        goto revert;
 
-               dst->url = path_childn(rpp_url,
+               dst->url = path_njoin(rpp_url,
                    (char const *)src->file.buf,
                    src->file.size);
 
index 1739b7397d3f7378287280d3510dd176d6ca0e45..c978ea64b91f9c75e5bd5cbb6e3f617183d26a19 100644 (file)
@@ -38,11 +38,10 @@ rsync2bio_tmpdir(char const *src)
 {
 #define TMPDIR "/tmp/fort-XXXXXX"
 
-       struct path_builder pb;
        char buf[sizeof(TMPDIR)];
        char *tmpdir;
+       char *tmpfile;
        BIO *result = NULL;
-       int error;
 
        strcpy(buf, TMPDIR);
        tmpdir = mkdtemp(buf);
@@ -51,17 +50,10 @@ rsync2bio_tmpdir(char const *src)
                return NULL;
        }
 
-       pb_init(&pb);
-       error = pb_append(&pb, tmpdir);
-       if (error)
-               goto end;
-       error = pb_append(&pb, path_filename(src));
-       if (error)
-               goto end;
-
-       result = __rsync2bio(src, pb.string);
+       tmpfile = path_join(tmpdir, path_filename(src));
+       result = __rsync2bio(src, tmpfile);
+       free(tmpfile);
 
-end:   pb_cleanup(&pb);
        return result;
 }
 
index 6912919fab52bdcacee2eacd6af82d01ce441d5a..1fcd6fe59f64ddc624bb2099925fa66cb0374cac 100644 (file)
@@ -897,41 +897,31 @@ validate_session_desync(struct rrdp_state *old_notif,
 
 /* TODO (performance) Stream instead of caching notifs, snapshots & deltas. */
 static int
-dl_tmp(char const *url, char **path)
+dl_tmp(char const *url, char *path)
 {
-       int error;
-
-       error = cache_tmpfile(path);
-       if (error)
-               return error;
-
-       error = http_download(url, *path, 0, NULL);
-       if (error)
-               free(*path);
-
-       return error;
+       cache_tmpfile(path);
+       return http_download(url, path, 0, NULL);
 }
 
 static int
 handle_snapshot(struct update_notification *new, struct rrdp_state *state)
 {
-       char *tmppath;
+       char tmppath[CACHE_TMPFILE_BUFLEN];
        int error;
 
        pr_val_debug("Processing snapshot.");
        fnstack_push(new->snapshot.uri);
 
-       error = dl_tmp(new->snapshot.uri, &tmppath);
+       error = dl_tmp(new->snapshot.uri, tmppath);
        if (error)
-               goto end1;
+               goto end;
        error = validate_hash(&new->snapshot, tmppath);
        if (error)
-               goto end2;
+               goto end;
        error = parse_snapshot(&new->session, tmppath, state);
 //     delete_file(tmppath); XXX
 
-end2:  free(tmppath);
-end1:  fnstack_pop();
+end:   fnstack_pop();
        return error;
 }
 
@@ -988,19 +978,18 @@ static int
 handle_delta(struct update_notification *notif,
     struct notification_delta *delta, struct rrdp_state *state)
 {
-       char *tmppath;
+       char tmppath[CACHE_TMPFILE_BUFLEN];
        int error;
 
        pr_val_debug("Processing delta '%s'.", delta->meta.uri);
        fnstack_push(delta->meta.uri);
 
-       error = dl_tmp(delta->meta.uri, &tmppath);
+       error = dl_tmp(delta->meta.uri, tmppath);
        if (error)
                goto end;
        error = parse_delta(notif, delta, tmppath, state);
 //     delete_file(tmppath); XXX
 
-       free(tmppath);
 end:   fnstack_pop();
        return error;
 }
@@ -1148,25 +1137,23 @@ static int
 dl_notif(struct cache_mapping const *map,  time_t mtim, bool *changed,
     struct update_notification *new)
 {
-       char *tmppath;
+       char tmppath[CACHE_TMPFILE_BUFLEN];
        int error;
 
-       error = cache_tmpfile(&tmppath);
-       if (error)
-               return error;
+       cache_tmpfile(tmppath);
 
        *changed = false;
        error = http_download(map->url, tmppath, mtim, changed);
        if (error)
-               goto end;
+               return error;
        if (!(*changed)) {
                pr_val_debug("The Notification has not changed.");
-               goto end;
+               return 0;
        }
 
        error = parse_notification(map->url, tmppath, new);
        if (error)
-               goto end;
+               return error;
 
        if (remove(tmppath) < 0) {
                pr_val_warn("Can't remove notification's temporal file: %s",
@@ -1175,8 +1162,7 @@ dl_notif(struct cache_mapping const *map,  time_t mtim, bool *changed,
                /* Nonfatal; fall through */
        }
 
-end:   free(tmppath);
-       return error;
+       return 0;
 }
 
 /*
index 2a17a1703ba45f23452a003de175d90c1a3b1a28..d793ab327655c0f3872e5e409452b956650e189b 100644 (file)
@@ -39,184 +39,6 @@ token_next(struct tokenizer *tkn)
        return true;
 }
 
-/* @reserve needs to be < INITIAL_CAPACITY. */
-void
-__pb_init(struct path_builder *pb, size_t reserve)
-{
-       pb->string = pmalloc(INITIAL_CAPACITY);
-       pb->string[reserve] = 0;
-       pb->len = reserve;
-       pb->capacity = INITIAL_CAPACITY;
-}
-
-static int
-pb_grow(struct path_builder *pb, size_t total_len, char const *addend)
-{
-       if (total_len > MAX_CAPACITY) {
-               pr_val_err("Unable to concatenate '%.32s' (might be truncated) to path '%s': Path too long (%zu > %u)",
-                   addend, pb->string, total_len, MAX_CAPACITY);
-               return ENOSPC;
-       }
-
-       do {
-               pb->capacity *= 2;
-       } while (total_len > pb->capacity);
-
-       pb->string = prealloc(pb->string, pb->capacity);
-       return 0;
-}
-
-int
-pb_appendn(struct path_builder *pb, char const *addend, size_t addlen)
-{
-       size_t total_len;
-       bool add_slash;
-       int error;
-
-       if (addlen == 0)
-               return 0;
-
-       add_slash = (pb->len != 0);
-       if (add_slash)
-               addlen++;
-
-       total_len = pb->len + addlen + 1;
-       if (total_len > pb->capacity) {
-               error = pb_grow(pb, total_len, addend);
-               if (error)
-                       return error;
-       }
-
-       if (add_slash) {
-               pb->string[pb->len] = '/';
-               memcpy(pb->string + pb->len + 1, addend, addlen);
-       } else {
-               memcpy(pb->string + pb->len, addend, addlen);
-       }
-
-       pb->len += addlen;
-       pb->string[pb->len] = 0;
-
-       return 0;
-}
-
-int
-pb_append(struct path_builder *pb, char const *addend)
-{
-       return (addend != NULL) ? pb_appendn(pb, addend, strlen(addend)) : 0;
-}
-
-int
-pb_append_u32(struct path_builder *pb, uint32_t num)
-{
-#define MAX_STRLEN 9 /* 8 hexadecimal digits plus null chara */
-       char buffer[MAX_STRLEN];
-       int num_len;
-
-       num_len = snprintf(buffer, MAX_STRLEN, "%X", num);
-       if (num_len < 0) {
-               pr_val_err("Cannot stringify number '%u': Unknown cause. Error code might be %d.",
-                   num, num_len);
-               return EIO; /* num_len is not necessarily an error code */
-       }
-       if (num_len >= MAX_STRLEN)
-               pr_crit("pb: Number %u requires %d digits", num, num_len);
-
-       return pb_appendn(pb, buffer, num_len);
-}
-
-/* Removes the last component added. */
-int
-pb_pop(struct path_builder *pb, bool fatal)
-{
-       size_t i;
-
-       if (pb->len == 0 || (pb->len == 1 && pb->string[0] == '/')) {
-               if (fatal)
-                       pr_crit("Programming error: Attempting to pop empty path builder");
-               return -pr_val_err("Path cannot '..' over the root.");
-       }
-
-       for (i = pb->len - 1; i >= 1; i--) {
-               if (pb->string[i] == '/') {
-                       pb->string[i] = 0;
-                       pb->len = i;
-                       return 0;
-               }
-       }
-
-       if (pb->string[0] == '/') {
-               pb->string[1] = 0;
-               pb->len = 1;
-       } else {
-               pb->string[0] = 0;
-               pb->len = 0;
-       }
-       return 0;
-}
-
-static void
-reverse_string(char *str, size_t len)
-{
-       char *b, *e; /* beginning, end */
-       char tmp;
-
-       for (b = str, e = str + len - 1; b < e; b++, e--) {
-               tmp = *b;
-               *b = *e;
-               *e = tmp;
-       }
-}
-
-/* Turns ab/cd/ef/gh into gh/ef/cd/ab. */
-void
-pb_reverse(struct path_builder *pb)
-{
-       size_t min;
-       size_t max;
-
-       reverse_string(pb->string, pb->len);
-
-       min = 0;
-       for (max = 1; max < pb->len; max++) {
-               if (pb->string[max] == '/') {
-                       reverse_string(&pb->string[min], max - min);
-                       max++;
-                       min = max;
-               }
-       }
-       reverse_string(&pb->string[min], pb->len - min);
-}
-
-void
-pb_cleanup(struct path_builder *pb)
-{
-       free(pb->string);
-}
-
-/* Note, fatal is hardcoded as 1. */
-char *
-path_parent(char const *child)
-{
-       struct path_builder pb;
-       pb.string = pstrdup(child);
-       pb.len = pb.capacity = strlen(pb.string);
-       pb_pop(&pb, true);
-       return pb.string;
-}
-
-char *
-path_childn(char const *p1, char const *p2, size_t p2len)
-{
-       struct path_builder pb;
-
-       pb_init(&pb);
-       pb_append(&pb, p1); // XXX
-       pb_appendn(&pb, p2, p2len); // XXX
-
-       return pb.string;
-}
-
 char const *
 path_filename(char const *path)
 {
@@ -227,27 +49,34 @@ path_filename(char const *path)
 /*
  * Cannot return NULL.
  *
- * XXX I'm starting to use this more. Probably clean the slashes.
+ * XXX I'm starting to use this more. Probably sanitize better.
  */
 char *
 path_join(char const *path1, char const *path2)
 {
-       size_t n;
-       char *result;
-       int written;
-
        // XXX needed?
        if (path1[0] == 0)
                return pstrdup(path2);
        if (path2 == NULL || path2[0] == 0)
                return pstrdup(path1);
 
-       n = strlen(path1) + strlen(path2) + 2;
+       return path_njoin(path1, path2, strlen(path2));
+}
+
+char *
+path_njoin(char const *p1, char const *p2, size_t p2len)
+{
+       size_t n;
+       char *result;
+       int written;
+
+       n = strlen(p1) + p2len + 2;
        result = pmalloc(n);
 
-       written = snprintf(result, n, "%s/%s", path1, path2);
+       written = snprintf(result, n, "%s/%.*s", p1, (int) p2len, p2);
        if (written != n - 1)
-               pr_crit("join_paths: %zu %d %s %s", n, written, path1, path2);
+               pr_crit("path_njoin: %zu %d %s %.*s",
+                   n, written, p1, (int) p2len, p2);
 
        return result;
 }
index 84bcdd091a4dec156c36c1474bb9c73e6e34c274..ec31211eb99a33e7d73d2b034dc70798947b5d3f 100644 (file)
@@ -1,18 +1,8 @@
 #ifndef SRC_TYPES_PATH_H_
 #define SRC_TYPES_PATH_H_
 
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
 #include <stdbool.h>
 #include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <unistd.h>
 
 // XXX rename
 struct tokenizer {
@@ -23,33 +13,8 @@ struct tokenizer {
 void token_init(struct tokenizer *, char const *);
 bool token_next(struct tokenizer *tkn);
 
-struct path_builder {
-       char *string;
-       size_t len; /* Includes the null chara */
-       size_t capacity;
-};
-
-void __pb_init(struct path_builder *, size_t);
-#define pb_init(pb) __pb_init(pb, 0)
-
-/*
- * The appends are atomic.
- * They are also naive; they don't collapse `.`, `..` nor slashes.
- */
-
-int pb_appendn(struct path_builder *, char const *, size_t);
-int pb_append(struct path_builder *, char const *);
-int pb_append_u32(struct path_builder *, uint32_t);
-
-int pb_pop(struct path_builder *, bool);
-
-void pb_reverse(struct path_builder *);
-
-void pb_cleanup(struct path_builder *);
-
-char *path_parent(char const *);
-char *path_childn(char const *, char const *, size_t);
 char const *path_filename(char const *);
 char *path_join(char const *, char const *);
+char *path_njoin(char const *, char const *, size_t);
 
 #endif /* SRC_TYPES_PATH_H_ */
index 46c4dffc30cd55c1bc7b33bd710832a2e334d935..bfc5a7207c457859012f44fbe4a7978e8f5054d5 100644 (file)
@@ -133,6 +133,13 @@ fail:      free(normal);
        return NULL;
 }
 
+char *
+url_parent(char const *child)
+{
+       char *slash = strrchr(child, '/');
+       return (slash != NULL) ? pstrndup(child, slash - child) : NULL;
+}
+
 bool
 url_same_origin(char const *url1, char const *url2)
 {
index a2b0ea5d37cccf9478a13fec77db427a6491c7e7..86c93feb70860510443753f1b3183f4f1e5965e0 100644 (file)
@@ -9,6 +9,7 @@ bool url_is_rsync(char const *);
 bool url_is_https(char const *);
 
 char *url_normalize(char const *);
+char *url_parent(char const *);
 bool url_same_origin(char const *, char const *);
 
 #endif /* SRC_TYPES_URL_H_ */
index afb3833808194ce272e11f033c6f8a32ffc0cc1a..11a8e446b9577a3da3ac29af469345090e54d75d 100644 (file)
@@ -29,7 +29,6 @@ check_PROGRAMS += db_table.test
 check_PROGRAMS += deltas_array.test
 check_PROGRAMS += hash.test
 check_PROGRAMS += mft.test
-check_PROGRAMS += path.test
 check_PROGRAMS += pdu_handler.test
 check_PROGRAMS += pdu_stream.test
 check_PROGRAMS += rrdp.test
@@ -71,9 +70,6 @@ hash_test_LDADD = ${MY_LDADD}
 mft_test_SOURCES = object/manifest_test.c
 mft_test_LDADD = ${MY_LDADD}
 
-path_test_SOURCES = types/path_test.c
-path_test_LDADD = ${MY_LDADD}
-
 pdu_handler_test_SOURCES = rtr/pdu_handler_test.c
 pdu_handler_test_LDADD = ${MY_LDADD} ${JANSSON_LIBS}
 
diff --git a/test/types/path_test.c b/test/types/path_test.c
deleted file mode 100644 (file)
index f56e462..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-#include <check.h>
-#include <stdlib.h>
-
-#define INITIAL_CAPACITY 8
-
-#include "alloc.c"
-#include "mock.c"
-#include "types/path.c"
-
-#define CHECK_PB(_string, _capacity)                                   \
-       ck_assert_str_eq(_string, pb.string);                           \
-       ck_assert_uint_eq(strlen(_string), pb.len);                     \
-       ck_assert_uint_eq(_capacity, pb.capacity);
-
-START_TEST(test_append)
-{
-       struct path_builder pb;
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, ""));
-       CHECK_PB("", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       CHECK_PB("a", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "/a"));
-       CHECK_PB("/a", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       CHECK_PB("a", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "b"));
-       CHECK_PB("a/b", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a/b"));
-       CHECK_PB("a/b", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a/"));
-       CHECK_PB("a/", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "b/"));
-       CHECK_PB("a//b/", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a/"));
-       CHECK_PB("a/", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "b"));
-       CHECK_PB("a//b", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       CHECK_PB("a", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "/b"));
-       CHECK_PB("a//b", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a/"));
-       CHECK_PB("a/", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "/b"));
-       CHECK_PB("a///b", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "//a"));
-       CHECK_PB("//a", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "///"));
-       CHECK_PB("//a////", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "b////"));
-       CHECK_PB("//a/////b////", 16);
-       ck_assert_int_eq(0, pb_append(&pb, "/////c//////"));
-       CHECK_PB("//a/////b//////////c//////", 32);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "//a///b//c//"));
-       CHECK_PB("//a///b//c//", 16);
-       pb_cleanup(&pb);
-}
-END_TEST
-
-/* Actually mainly designed to manhandle capacity expansion */
-START_TEST(test_uint)
-{
-       struct path_builder pb;
-
-       pb_init(&pb);
-       pb_append_u32(&pb, 0x123);
-       CHECK_PB("123", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       pb_append_u32(&pb, 0x1234567);
-       CHECK_PB("1234567", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       pb_append_u32(&pb, 0x12345678);
-       CHECK_PB("12345678", 16);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       pb_append_u32(&pb, 0x12345);
-       CHECK_PB("12345", 8);
-       pb_append_u32(&pb, 0x7);
-       CHECK_PB("12345/7", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       pb_append_u32(&pb, 0x12345);
-       CHECK_PB("12345", 8);
-       pb_append_u32(&pb, 0x78);
-       CHECK_PB("12345/78", 16);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       pb_append_u32(&pb, 0x12345);
-       CHECK_PB("12345", 8);
-       pb_append_u32(&pb, 0x789);
-       CHECK_PB("12345/789", 16);
-       pb_cleanup(&pb);
-}
-END_TEST
-
-START_TEST(test_pop)
-{
-       struct path_builder pb;
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       CHECK_PB("a", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "b"));
-       CHECK_PB("a/b", 8);
-       ck_assert_int_eq(0, pb_pop(&pb, false));
-       CHECK_PB("a", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "abc"));
-       CHECK_PB("abc", 8);
-       ck_assert_int_eq(0, pb_append(&pb, "def"));
-       CHECK_PB("abc/def", 8);
-       ck_assert_int_eq(0, pb_pop(&pb, false));
-       CHECK_PB("abc", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       CHECK_PB("a", 8);
-       ck_assert_int_eq(0, pb_pop(&pb, false));
-       CHECK_PB("", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "/a"));
-       CHECK_PB("/a", 8);
-       ck_assert_int_eq(0, pb_pop(&pb, false));
-       CHECK_PB("/", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(EINVAL, pb_pop(&pb, false));
-       CHECK_PB("", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       ck_assert_int_eq(0, pb_pop(&pb, false));
-       CHECK_PB("", 8);
-       ck_assert_int_eq(EINVAL, pb_pop(&pb, false));
-       CHECK_PB("", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "/"));
-       CHECK_PB("/", 8);
-       ck_assert_int_eq(EINVAL, pb_pop(&pb, false));
-       CHECK_PB("/", 8);
-       pb_cleanup(&pb);
-}
-END_TEST
-
-START_TEST(test_reverse)
-{
-       struct path_builder pb;
-
-       /* 0 components */
-       pb_init(&pb);
-       pb_reverse(&pb);
-       CHECK_PB("", 8);
-       pb_cleanup(&pb);
-
-       /* 1 component */
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       pb_reverse(&pb);
-       CHECK_PB("a", 8);
-       pb_cleanup(&pb);
-
-       /* 2 components */
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       ck_assert_int_eq(0, pb_append(&pb, "b"));
-       pb_reverse(&pb);
-       CHECK_PB("b/a", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "abc"));
-       ck_assert_int_eq(0, pb_append(&pb, "def"));
-       pb_reverse(&pb);
-       CHECK_PB("def/abc", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "abcd"));
-       ck_assert_int_eq(0, pb_append(&pb, "efgh"));
-       pb_reverse(&pb);
-       CHECK_PB("efgh/abcd", 16);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "abc"));
-       ck_assert_int_eq(0, pb_append(&pb, "efgh"));
-       pb_reverse(&pb);
-       CHECK_PB("efgh/abc", 16);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "abcd"));
-       ck_assert_int_eq(0, pb_append(&pb, "fgh"));
-       pb_reverse(&pb);
-       CHECK_PB("fgh/abcd", 16);
-       pb_cleanup(&pb);
-
-       /* 3 components */
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "abc"));
-       ck_assert_int_eq(0, pb_append(&pb, "def"));
-       ck_assert_int_eq(0, pb_append(&pb, "ghi"));
-       pb_reverse(&pb);
-       CHECK_PB("ghi/def/abc", 16);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "ab"));
-       ck_assert_int_eq(0, pb_append(&pb, "cde"));
-       ck_assert_int_eq(0, pb_append(&pb, "fghi"));
-       pb_reverse(&pb);
-       CHECK_PB("fghi/cde/ab", 16);
-       pb_cleanup(&pb);
-
-       /* 4 components */
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       ck_assert_int_eq(0, pb_append(&pb, "b"));
-       ck_assert_int_eq(0, pb_append(&pb, "c"));
-       ck_assert_int_eq(0, pb_append(&pb, "d"));
-       pb_reverse(&pb);
-       CHECK_PB("d/c/b/a", 8);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "ab"));
-       ck_assert_int_eq(0, pb_append(&pb, "cd"));
-       ck_assert_int_eq(0, pb_append(&pb, "ef"));
-       ck_assert_int_eq(0, pb_append(&pb, "gh"));
-       pb_reverse(&pb);
-       CHECK_PB("gh/ef/cd/ab", 16);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "a"));
-       ck_assert_int_eq(0, pb_append(&pb, "bcd"));
-       ck_assert_int_eq(0, pb_append(&pb, "efgh"));
-       ck_assert_int_eq(0, pb_append(&pb, "ijklm"));
-       pb_reverse(&pb);
-       CHECK_PB("ijklm/efgh/bcd/a", 32);
-       pb_cleanup(&pb);
-
-       pb_init(&pb);
-       ck_assert_int_eq(0, pb_append(&pb, "abcdefghijklmnopq"));
-       ck_assert_int_eq(0, pb_append(&pb, "r"));
-       ck_assert_int_eq(0, pb_append(&pb, "stu"));
-       ck_assert_int_eq(0, pb_append(&pb, "vx"));
-       pb_reverse(&pb);
-       CHECK_PB("vx/stu/r/abcdefghijklmnopq", 32);
-       pb_cleanup(&pb);
-}
-END_TEST
-
-static Suite *
-create_suite(void)
-{
-       Suite *suite;
-       TCase *core;
-
-       core = tcase_create("functions");
-       tcase_add_test(core, test_append);
-       tcase_add_test(core, test_uint);
-       tcase_add_test(core, test_pop);
-       tcase_add_test(core, test_reverse);
-
-       suite = suite_create("path_builder");
-       suite_add_tcase(suite, core);
-       return suite;
-}
-
-int
-main(int argc, char **argv)
-{
-       Suite *suite;
-       SRunner *runner;
-       int tests_failed;
-
-       suite = create_suite();
-
-       runner = srunner_create(suite);
-       srunner_run_all(runner, CK_NORMAL);
-       tests_failed = srunner_ntests_failed(runner);
-       srunner_free(runner);
-
-       return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}