]> git.cameronkatri.com Git - trustcache.git/blob - append.c
Initial import
[trustcache.git] / append.c
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2022 Cameron Katri. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY CAMERON KATRI AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL CAMERON KATRI OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <errno.h>
29 #include <getopt.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "trustcache.h"
36 #include "uuid/uuid.h"
37
38 int
39 tcappend(int argc, char **argv)
40 {
41 if (argc < 3)
42 return -1;
43
44 int keepuuid = 0;
45 uuid_t uuid;
46
47 int ch;
48 while ((ch = getopt(argc, argv, "u:")) != -1) {
49 switch (ch) {
50 case 'u':
51 if (strlen(optarg) == 1 && *optarg == '0') {
52 keepuuid = 1;
53 } else {
54 if (uuid_parse(optarg, uuid) != 0) {
55 fprintf(stderr, "Failed to parse %s as a UUID\n", optarg);
56 } else
57 keepuuid = 2;
58 }
59 break;
60 }
61 }
62
63 argc -= optind;
64 argv += optind;
65
66 FILE *f = NULL;
67 struct trust_cache cache = opentrustcache(argv[0]);
68 struct trust_cache append = {
69 .version = cache.version,
70 .num_entries = 0
71 };
72
73 for (int i = 1; i < argc; i++) {
74 append = cache_from_tree(argv[i], cache.version);
75 if (append.version == 0) {
76 if ((cache.hashes = realloc(cache.hashes, sizeof(trust_cache_hash0) *
77 (cache.num_entries + append.num_entries))) == NULL)
78 exit(1);
79 for (int j = 0; j < append.num_entries; j++) {
80 memcpy(cache.hashes[cache.num_entries + j], append.hashes[j], CS_CDHASH_LEN);
81 }
82 } else if (append.version == 1) {
83 if ((cache.entries = realloc(cache.entries, sizeof(struct trust_cache_entry1) *
84 (cache.num_entries + append.num_entries))) == NULL)
85 exit(1);
86 for (int j = 0; j < append.num_entries; j++) {
87 cache.entries[cache.num_entries + j].hash_type = append.entries[j].hash_type;
88 cache.entries[cache.num_entries + j].flags = append.entries[j].flags;
89 memcpy(cache.entries[cache.num_entries + j].cdhash, append.entries[j].cdhash, CS_CDHASH_LEN);
90 }
91 }
92 free(append.hashes);
93 cache.num_entries += append.num_entries;
94 }
95
96 if (cache.version == 1)
97 mergesort(cache.entries, cache.num_entries, sizeof(*cache.entries), ent_cmp);
98 else if (cache.version == 0)
99 mergesort(cache.hashes, cache.num_entries, sizeof(*cache.hashes), hash_cmp);
100
101 switch (keepuuid) {
102 case 0:
103 uuid_generate(cache.uuid);
104 break;
105 case 1:
106 break;
107 case 2:
108 uuid_copy(cache.uuid, uuid);
109 break;
110 }
111
112 if ((f = fopen(argv[0], "wb")) == NULL) {
113 fprintf(stderr, "%s: %s\n", argv[0], strerror(errno));
114 return 1;
115 }
116
117 cache.version = htole32(cache.version);
118 cache.num_entries = htole32(cache.num_entries);
119 fwrite(&cache, sizeof(struct trust_cache) - sizeof(struct trust_cache_entry1*), 1, f);
120 cache.version = le32toh(cache.version);
121 cache.num_entries = le32toh(cache.num_entries);
122
123 for (int i = 0; i < cache.num_entries; i++) {
124 if (cache.version == 0)
125 fwrite(&cache.hashes[i], sizeof(trust_cache_hash0), 1, f);
126 else if (cache.version == 1)
127 fwrite(&cache.entries[i], sizeof(struct trust_cache_entry1), 1, f);
128 }
129
130 return 0;
131 }