aboutsummaryrefslogtreecommitdiffstats
path: root/create.c
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2022-05-20 10:42:38 -0400
committerCameron Katri <me@cameronkatri.com>2022-05-20 10:42:38 -0400
commitaa035f73ce081b3f07247bd15860d72355a096b2 (patch)
tree170a83f5aa816f936df5ae906f20da3fb6b9404e /create.c
downloadtrustcache-aa035f73ce081b3f07247bd15860d72355a096b2.tar.gz
trustcache-aa035f73ce081b3f07247bd15860d72355a096b2.tar.zst
trustcache-aa035f73ce081b3f07247bd15860d72355a096b2.zip
Initial import
Diffstat (limited to 'create.c')
-rw-r--r--create.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/create.c b/create.c
new file mode 100644
index 0000000..a19d7f3
--- /dev/null
+++ b/create.c
@@ -0,0 +1,130 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Cameron Katri. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CAMERON KATRI AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CAMERON KATRI OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "trustcache.h"
+#include "uuid/uuid.h"
+
+int
+tccreate(int argc, char **argv)
+{
+ struct trust_cache cache = {
+ .version = 1,
+ .uuid = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ .num_entries = 0,
+ .entries = NULL,
+ }, append = {};
+
+ uuid_generate(cache.uuid);
+
+ int ch;
+ while ((ch = getopt(argc, argv, "u:v:")) != -1) {
+ switch (ch) {
+ case 'u':
+ if (uuid_parse(optarg, cache.uuid) != 0)
+ fprintf(stderr, "Failed to parse %s as a UUID\n", optarg);
+ break;
+ case 'v':
+ if (strlen(optarg) != 1 || (optarg[0] != '0' && optarg[0] != '1')) {
+ fprintf(stderr, "Unsupported trustcache version %s\n", optarg);
+ return 1;
+ }
+ if (optarg[0] == '0')
+ cache.version = 0;
+ else if (optarg[0] == '1')
+ cache.version = 1;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ return -1;
+ }
+
+ for (int i = 1; i < argc; i++) {
+ append = cache_from_tree(argv[i], cache.version);
+ if (append.version == 0) {
+ if ((cache.hashes = realloc(cache.hashes, sizeof(trust_cache_hash0) *
+ (cache.num_entries + append.num_entries))) == NULL)
+ exit(1);
+ for (int j = 0; j < append.num_entries; j++) {
+ memcpy(cache.hashes[cache.num_entries + j], append.hashes[j], CS_CDHASH_LEN);
+ }
+ } else if (append.version == 1) {
+ if ((cache.entries = realloc(cache.entries, sizeof(struct trust_cache_entry1) *
+ (cache.num_entries + append.num_entries))) == NULL)
+ exit(1);
+ for (int j = 0; j < append.num_entries; j++) {
+ cache.entries[cache.num_entries + j].hash_type = append.entries[j].hash_type;
+ cache.entries[cache.num_entries + j].flags = append.entries[j].flags;
+ memcpy(cache.entries[cache.num_entries + j].cdhash, append.entries[j].cdhash, CS_CDHASH_LEN);
+ }
+ }
+ free(append.hashes);
+ cache.num_entries += append.num_entries;
+ }
+
+ if (cache.version == 1)
+ mergesort(cache.entries, cache.num_entries, sizeof(*cache.entries), ent_cmp);
+ else if (cache.version == 0)
+ mergesort(cache.hashes, cache.num_entries, sizeof(*cache.hashes), hash_cmp);
+
+ FILE *f = NULL;
+ if ((f = fopen(argv[0], "wb")) == NULL) {
+ fprintf(stderr, "%s: %s\n", argv[0], strerror(errno));
+ return 1;
+ }
+
+ cache.version = htole32(cache.version);
+ cache.num_entries = htole32(cache.num_entries);
+ fwrite(&cache, sizeof(struct trust_cache) - sizeof(struct trust_cache_entry1*), 1, f);
+ cache.version = le32toh(cache.version);
+ cache.num_entries = le32toh(cache.num_entries);
+
+ for (int i = 0; i < cache.num_entries; i++) {
+ if (cache.version == 1)
+ fwrite(&cache.entries[i], sizeof(struct trust_cache_entry1), 1, f);
+ else if (cache.version == 0)
+ fwrite(&cache.hashes[i], sizeof(trust_cache_hash0), 1, f);
+ }
+
+ fclose(f);
+
+ free(cache.entries);
+
+ return 0;
+}