]>
Commit | Line | Data |
---|---|---|
4e2a1762 | 1 | /* |
6795de04 | 2 | * Copyright (C) 2013-2017 Andreas Steffen |
4e2a1762 AS |
3 | * HSR Hochschule fuer Technik Rapperswil |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 | * for more details. | |
14 | */ | |
15 | ||
16 | #include "swid_inventory.h" | |
17 | #include "swid_tag.h" | |
18 | #include "swid_tag_id.h" | |
88501a64 | 19 | #include "swid_gen/swid_gen.h" |
4e2a1762 AS |
20 | |
21 | #include <collections/linked_list.h> | |
88501a64 | 22 | #include <utils/lexparser.h> |
4e2a1762 AS |
23 | #include <utils/debug.h> |
24 | ||
25 | #include <stdio.h> | |
26 | #include <fcntl.h> | |
27 | #include <unistd.h> | |
28 | #include <sys/stat.h> | |
4e2a1762 AS |
29 | #include <libgen.h> |
30 | #include <errno.h> | |
31 | ||
32 | typedef struct private_swid_inventory_t private_swid_inventory_t; | |
33 | ||
4e2a1762 AS |
34 | /** |
35 | * Private data of a swid_inventory_t object. | |
36 | * | |
37 | */ | |
38 | struct private_swid_inventory_t { | |
39 | ||
40 | /** | |
41 | * Public swid_inventory_t interface. | |
42 | */ | |
43 | swid_inventory_t public; | |
44 | ||
45 | /** | |
46 | * Full SWID tags or just SWID tag IDs | |
47 | */ | |
48 | bool full_tags; | |
49 | ||
50 | /** | |
51 | * List of SWID tags or tag IDs | |
52 | */ | |
53 | linked_list_t *list; | |
54 | }; | |
55 | ||
88501a64 AS |
56 | static status_t generate_tags(private_swid_inventory_t *this, |
57 | swid_inventory_t *targets, bool pretty, bool full) | |
8c40609f | 58 | { |
88501a64 | 59 | swid_gen_t *swid_gen; |
8c40609f | 60 | swid_tag_t *tag; |
b7679e90 | 61 | swid_tag_id_t *tag_id; |
88501a64 | 62 | enumerator_t *enumerator; |
b7679e90 | 63 | status_t status = SUCCESS; |
88501a64 AS |
64 | chunk_t out; |
65 | ||
66 | swid_gen = swid_gen_create(); | |
b7679e90 AS |
67 | |
68 | if (targets->get_count(targets) == 0) | |
69 | { | |
88501a64 AS |
70 | DBG2(DBG_IMC, "SWID tag%s generation by package manager", |
71 | this->full_tags ? "" : " ID"); | |
b7679e90 | 72 | |
88501a64 AS |
73 | enumerator = swid_gen->create_tag_enumerator(swid_gen, !this->full_tags, |
74 | full, pretty); | |
75 | if (enumerator) | |
b7679e90 | 76 | { |
88501a64 AS |
77 | while (enumerator->enumerate(enumerator, &out)) |
78 | { | |
79 | if (this->full_tags) | |
80 | { | |
81 | chunk_t swid_tag = out; | |
b7679e90 | 82 | |
88501a64 AS |
83 | tag = swid_tag_create(swid_tag, chunk_empty); |
84 | this->list->insert_last(this->list, tag); | |
85 | } | |
86 | else | |
87 | { | |
88 | chunk_t tag_creator, sw_id = out; | |
89 | ||
90 | if (extract_token_str(&tag_creator, "__", &sw_id)) | |
91 | { | |
92 | tag_id = swid_tag_id_create(tag_creator, sw_id, | |
93 | chunk_empty); | |
94 | this->list->insert_last(this->list, tag_id); | |
95 | } | |
96 | else | |
97 | { | |
98 | DBG1(DBG_IMC, "separation of regid from unique " | |
99 | "software ID failed"); | |
100 | status = FAILED; | |
101 | chunk_free(&out); | |
102 | break; | |
103 | } | |
104 | } | |
105 | chunk_free(&out); | |
106 | } | |
107 | enumerator->destroy(enumerator); | |
b7679e90 AS |
108 | } |
109 | else | |
110 | { | |
88501a64 | 111 | status = NOT_SUPPORTED; |
b7679e90 | 112 | } |
b7679e90 AS |
113 | } |
114 | else if (this->full_tags) | |
115 | { | |
88501a64 | 116 | DBG2(DBG_IMC, "targeted SWID tag generation"); |
f82d7aff | 117 | |
b7679e90 AS |
118 | enumerator = targets->create_enumerator(targets); |
119 | while (enumerator->enumerate(enumerator, &tag_id)) | |
120 | { | |
88501a64 AS |
121 | char software_id[BUF_LEN], *swid_tag; |
122 | chunk_t tag_creator, sw_id; | |
b7679e90 | 123 | |
88501a64 | 124 | /* Construct software ID from tag creator and unique software ID */ |
b7679e90 | 125 | tag_creator = tag_id->get_tag_creator(tag_id); |
88501a64 AS |
126 | sw_id = tag_id->get_unique_sw_id(tag_id, NULL); |
127 | snprintf(software_id, BUF_LEN, "%.*s__%.*s", | |
128 | tag_creator.len, tag_creator.ptr, sw_id.len, sw_id.ptr); | |
8c40609f | 129 | |
88501a64 AS |
130 | swid_tag = swid_gen->generate_tag(swid_gen, software_id, NULL, NULL, |
131 | full, pretty); | |
132 | if (swid_tag) | |
8c40609f | 133 | { |
88501a64 AS |
134 | tag = swid_tag_create(chunk_from_str(swid_tag), chunk_empty); |
135 | this->list->insert_last(this->list, tag); | |
136 | free(swid_tag); | |
8c40609f | 137 | } |
8c40609f | 138 | } |
b7679e90 | 139 | enumerator->destroy(enumerator); |
8c40609f | 140 | } |
88501a64 | 141 | swid_gen->destroy(swid_gen); |
8c40609f | 142 | |
8c40609f AS |
143 | return status; |
144 | } | |
145 | ||
3adffcd9 | 146 | static bool collect_tags(private_swid_inventory_t *this, char *pathname, |
6795de04 | 147 | swid_inventory_t *targets, bool is_swidtag_dir) |
4e2a1762 AS |
148 | { |
149 | char *rel_name, *abs_name; | |
150 | struct stat st; | |
151 | bool success = FALSE; | |
152 | enumerator_t *enumerator; | |
153 | ||
154 | enumerator = enumerator_create_directory(pathname); | |
155 | if (!enumerator) | |
156 | { | |
d1696c0e | 157 | DBG1(DBG_IMC, "directory '%s' can not be opened, %s", |
4e2a1762 AS |
158 | pathname, strerror(errno)); |
159 | return FALSE; | |
160 | } | |
6795de04 AS |
161 | if (is_swidtag_dir) |
162 | { | |
163 | DBG2(DBG_IMC, "entering %s", pathname); | |
164 | } | |
751670a9 | 165 | |
4e2a1762 AS |
166 | while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st)) |
167 | { | |
6795de04 | 168 | char *separator, *suffix; |
4e2a1762 | 169 | chunk_t tag_creator; |
8c40609f | 170 | chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty; |
b7679e90 | 171 | |
4e2a1762 AS |
172 | if (S_ISDIR(st.st_mode)) |
173 | { | |
6795de04 AS |
174 | if (!collect_tags(this, abs_name, targets, is_swidtag_dir || |
175 | streq(rel_name, "swidtag"))) | |
4e2a1762 AS |
176 | { |
177 | goto end; | |
178 | } | |
179 | continue; | |
180 | } | |
6795de04 AS |
181 | if (!is_swidtag_dir) |
182 | { | |
183 | continue; | |
184 | } | |
4e2a1762 | 185 | |
6795de04 AS |
186 | /* found a swidtag file? */ |
187 | suffix = strstr(rel_name, ".swidtag"); | |
188 | if (!suffix) | |
4e2a1762 | 189 | { |
6795de04 | 190 | continue; |
4e2a1762 | 191 | } |
4e2a1762 | 192 | |
6795de04 | 193 | /* parse the swidtag filename into its components */ |
88501a64 | 194 | separator = strstr(rel_name, "__"); |
6795de04 | 195 | if (!separator) |
4e2a1762 | 196 | { |
3adffcd9 | 197 | DBG1(DBG_IMC, " %s", rel_name); |
88501a64 | 198 | DBG1(DBG_IMC, " '__' separator not found"); |
4e2a1762 AS |
199 | goto end; |
200 | } | |
6795de04 AS |
201 | tag_creator = chunk_create(rel_name, separator-rel_name); |
202 | ||
88501a64 | 203 | unique_sw_id = chunk_create(separator+2, suffix-separator-2); |
8c40609f | 204 | tag_file_path = chunk_from_str(abs_name); |
4e2a1762 | 205 | |
3adffcd9 AS |
206 | /* In case of a targeted request */ |
207 | if (targets->get_count(targets)) | |
208 | { | |
b7679e90 | 209 | chunk_t target_unique_sw_id, target_tag_creator; |
3adffcd9 AS |
210 | enumerator_t *target_enumerator; |
211 | swid_tag_id_t *tag_id; | |
212 | bool match = FALSE; | |
213 | ||
214 | target_enumerator = targets->create_enumerator(targets); | |
215 | while (target_enumerator->enumerate(target_enumerator, &tag_id)) | |
216 | { | |
b7679e90 AS |
217 | target_unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL); |
218 | target_tag_creator = tag_id->get_tag_creator(tag_id); | |
219 | ||
220 | if (chunk_equals(target_unique_sw_id, unique_sw_id) && | |
6795de04 | 221 | chunk_equals(target_tag_creator, tag_creator)) |
3adffcd9 AS |
222 | { |
223 | match = TRUE; | |
224 | break; | |
225 | } | |
226 | } | |
227 | target_enumerator->destroy(target_enumerator); | |
228 | ||
229 | if (!match) | |
230 | { | |
231 | continue; | |
232 | } | |
233 | } | |
234 | DBG2(DBG_IMC, " %s", rel_name); | |
235 | ||
4e2a1762 AS |
236 | if (this->full_tags) |
237 | { | |
238 | swid_tag_t *tag; | |
85349815 | 239 | chunk_t *xml_tag; |
4e2a1762 | 240 | |
85349815 MW |
241 | xml_tag = chunk_map(abs_name, FALSE); |
242 | if (!xml_tag) | |
4e2a1762 | 243 | { |
d1696c0e | 244 | DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name, |
6795de04 | 245 | strerror(errno)); |
4e2a1762 AS |
246 | goto end; |
247 | } | |
248 | ||
8c40609f | 249 | tag = swid_tag_create(*xml_tag, tag_file_path); |
4e2a1762 | 250 | this->list->insert_last(this->list, tag); |
85349815 | 251 | chunk_unmap(xml_tag); |
4e2a1762 AS |
252 | } |
253 | else | |
254 | { | |
255 | swid_tag_id_t *tag_id; | |
256 | ||
8c40609f | 257 | tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path); |
4e2a1762 AS |
258 | this->list->insert_last(this->list, tag_id); |
259 | } | |
260 | } | |
261 | success = TRUE; | |
262 | ||
263 | end: | |
264 | enumerator->destroy(enumerator); | |
6795de04 AS |
265 | if (is_swidtag_dir) |
266 | { | |
267 | DBG2(DBG_IMC, "leaving %s", pathname); | |
268 | } | |
4e2a1762 AS |
269 | |
270 | return success; | |
271 | } | |
272 | ||
273 | METHOD(swid_inventory_t, collect, bool, | |
88501a64 AS |
274 | private_swid_inventory_t *this, char *directory, swid_inventory_t *targets, |
275 | bool pretty, bool full) | |
4e2a1762 | 276 | { |
8c40609f AS |
277 | /** |
278 | * Tags are generated by a package manager | |
279 | */ | |
88501a64 | 280 | generate_tags(this, targets, pretty, full); |
8c40609f AS |
281 | |
282 | /** | |
283 | * Collect swidtag files by iteratively entering all directories in | |
284 | * the tree under the "directory" path. | |
285 | */ | |
6795de04 | 286 | return collect_tags(this, directory, targets, FALSE); |
4e2a1762 AS |
287 | } |
288 | ||
289 | METHOD(swid_inventory_t, add, void, | |
290 | private_swid_inventory_t *this, void *item) | |
291 | { | |
292 | this->list->insert_last(this->list, item); | |
293 | } | |
294 | ||
295 | METHOD(swid_inventory_t, get_count, int, | |
296 | private_swid_inventory_t *this) | |
297 | { | |
298 | return this->list->get_count(this->list); | |
299 | } | |
300 | ||
301 | METHOD(swid_inventory_t, create_enumerator, enumerator_t*, | |
302 | private_swid_inventory_t *this) | |
303 | { | |
304 | return this->list->create_enumerator(this->list); | |
305 | } | |
306 | ||
307 | METHOD(swid_inventory_t, destroy, void, | |
308 | private_swid_inventory_t *this) | |
309 | { | |
310 | if (this->full_tags) | |
311 | { | |
312 | this->list->destroy_offset(this->list, offsetof(swid_tag_t, destroy)); | |
313 | } | |
314 | else | |
315 | { | |
316 | this->list->destroy_offset(this->list, offsetof(swid_tag_id_t, destroy)); | |
317 | } | |
318 | free(this); | |
319 | } | |
320 | ||
321 | /** | |
322 | * See header | |
323 | */ | |
324 | swid_inventory_t *swid_inventory_create(bool full_tags) | |
325 | { | |
326 | private_swid_inventory_t *this; | |
327 | ||
328 | INIT(this, | |
329 | .public = { | |
330 | .collect = _collect, | |
331 | .add = _add, | |
332 | .get_count = _get_count, | |
333 | .create_enumerator = _create_enumerator, | |
334 | .destroy = _destroy, | |
335 | }, | |
336 | .full_tags = full_tags, | |
337 | .list = linked_list_create(), | |
338 | ); | |
339 | ||
340 | return &this->public; | |
341 | } |