]> git.cameronkatri.com Git - trustcache.git/blob - append.c
Add tc remove and append -f flags
[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 <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "trustcache.h"
37 #include "uuid/uuid.h"
38
39 int
40 tcappend(int argc, char **argv)
41 {
42 int keepuuid = 0;
43 uuid_t uuid;
44 const char *errstr = NULL;
45 uint8_t flags = 0;
46
47 int ch;
48 while ((ch = getopt(argc, argv, "u:f:")) != -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 case 'f':
61 flags = strtonum(optarg, 0, UINT8_MAX, &errstr);
62 if (errstr != NULL) {
63 fprintf(stderr, "flag number is %s: %s\n", errstr, optarg);
64 exit(1);
65 }
66 break;
67 }
68 }
69
70 argc -= optind;
71 argv += optind;
72
73 if (argc < 2)
74 return -1;
75
76 FILE *f = NULL;
77 struct trust_cache cache = opentrustcache(argv[0]);
78 struct trust_cache append = {
79 .version = cache.version,
80 .num_entries = 0
81 };
82
83 for (int i = 1; i < argc; i++) {
84 append = cache_from_tree(argv[i], cache.version);
85 if (append.version == 0) {
86 if ((cache.hashes = realloc(cache.hashes, sizeof(trust_cache_hash0) *
87 (cache.num_entries + append.num_entries))) == NULL)
88 exit(1);
89 for (uint32_t j = 0; j < append.num_entries; j++) {
90 memcpy(cache.hashes[cache.num_entries + j], append.hashes[j], CS_CDHASH_LEN);
91 }
92 } else if (append.version == 1) {
93 if ((cache.entries = realloc(cache.entries, sizeof(struct trust_cache_entry1) *
94 (cache.num_entries + append.num_entries))) == NULL)
95 exit(1);
96 for (uint32_t j = 0; j < append.num_entries; j++) {
97 cache.entries[cache.num_entries + j].hash_type = append.entries[j].hash_type;
98 cache.entries[cache.num_entries + j].flags = flags != 0 ? flags : append.entries[j].flags;
99 memcpy(cache.entries[cache.num_entries + j].cdhash, append.entries[j].cdhash, CS_CDHASH_LEN);
100 }
101 }
102 free(append.hashes);
103 cache.num_entries += append.num_entries;
104 }
105
106 if (cache.version == 1)
107 mergesort(cache.entries, cache.num_entries, sizeof(*cache.entries), ent_cmp);
108 else if (cache.version == 0)
109 mergesort(cache.hashes, cache.num_entries, sizeof(*cache.hashes), hash_cmp);
110
111 switch (keepuuid) {
112 case 0:
113 uuid_generate(cache.uuid);
114 break;
115 case 1:
116 break;
117 case 2:
118 uuid_copy(cache.uuid, uuid);
119 break;
120 }
121
122 if ((f = fopen(argv[0], "wb")) == NULL) {
123 fprintf(stderr, "%s: %s\n", argv[0], strerror(errno));
124 return 1;
125 }
126
127 cache.version = htole32(cache.version);
128 cache.num_entries = htole32(cache.num_entries);
129 fwrite(&cache, sizeof(struct trust_cache) - sizeof(struct trust_cache_entry1*), 1, f);
130 cache.version = le32toh(cache.version);
131 cache.num_entries = le32toh(cache.num_entries);
132
133 for (uint32_t i = 0; i < cache.num_entries; i++) {
134 if (cache.version == 0)
135 fwrite(&cache.hashes[i], sizeof(trust_cache_hash0), 1, f);
136 else if (cache.version == 1)
137 fwrite(&cache.entries[i], sizeof(struct trust_cache_entry1), 1, f);
138 }
139
140 return 0;
141 }