a71682f43dacd52560054235b844c26e0d4f8133
[strongswan.git] / src / libpts / swid / swid_inventory.c
1 /*
2 * Copyright (C) 2013 Andreas Steffen
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"
19
20 #include <collections/linked_list.h>
21 #include <utils/debug.h>
22
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <libgen.h>
28 #include <errno.h>
29
30 typedef struct private_swid_inventory_t private_swid_inventory_t;
31
32 /**
33 * Private data of a swid_inventory_t object.
34 *
35 */
36 struct private_swid_inventory_t {
37
38 /**
39 * Public swid_inventory_t interface.
40 */
41 swid_inventory_t public;
42
43 /**
44 * Full SWID tags or just SWID tag IDs
45 */
46 bool full_tags;
47
48 /**
49 * List of SWID tags or tag IDs
50 */
51 linked_list_t *list;
52 };
53
54 static bool collect_tags(private_swid_inventory_t *this, char *pathname,
55 swid_inventory_t *targets)
56 {
57 char *rel_name, *abs_name;
58 struct stat st;
59 bool success = FALSE;
60 enumerator_t *enumerator;
61
62 enumerator = enumerator_create_directory(pathname);
63 if (!enumerator)
64 {
65 DBG1(DBG_IMC, "directory '%s' can not be opened, %s",
66 pathname, strerror(errno));
67 return FALSE;
68 }
69 DBG2(DBG_IMC, "entering %s", pathname);
70
71 while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
72 {
73 char * start, *stop;
74 chunk_t tag_creator;
75 chunk_t unique_sw_id = chunk_empty, unique_seq_id = chunk_empty;
76 if (!strstr(rel_name, "regid."))
77 {
78 continue;
79 }
80 if (S_ISDIR(st.st_mode))
81 {
82 /* In case of a targeted request */
83 if (targets->get_count(targets))
84 {
85 enumerator_t *target_enumerator;
86 swid_tag_id_t *tag_id;
87 bool match = FALSE;
88
89 target_enumerator = targets->create_enumerator(targets);
90 while (target_enumerator->enumerate(target_enumerator, &tag_id))
91 {
92 if (chunk_equals(tag_id->get_tag_creator(tag_id),
93 chunk_from_str(rel_name)))
94 {
95 match = TRUE;
96 break;
97 }
98 }
99 target_enumerator->destroy(target_enumerator);
100
101 if (!match)
102 {
103 continue;
104 }
105 }
106
107 if (!collect_tags(this, abs_name, targets))
108 {
109 goto end;
110 }
111 continue;
112 }
113
114 /* parse the regid filename into its components */
115 start = rel_name;
116 stop = strchr(start, '_');
117 if (!stop)
118 {
119 DBG1(DBG_IMC, " %s", rel_name);
120 DBG1(DBG_IMC, " '_' separator not found");
121 goto end;
122 }
123 tag_creator = chunk_create(start, stop-start);
124
125 start = stop + 1;
126 stop = strchr(start, '_');
127 if (stop)
128 {
129 unique_sw_id = chunk_create(start, stop-start);
130 start = stop + 1;
131 }
132
133 stop = strstr(start, ".swidtag");
134 if (!stop)
135 {
136 DBG1(DBG_IMC, " %s", rel_name);
137 DBG1(DBG_IMC, " swidtag postfix not found");
138 goto end;
139 }
140 if (unique_sw_id.ptr)
141 {
142 unique_seq_id = chunk_create(start, stop-start);
143 }
144 else
145 {
146 unique_sw_id = chunk_create(start, stop-start);
147 }
148
149 /* In case of a targeted request */
150 if (targets->get_count(targets))
151 {
152 enumerator_t *target_enumerator;
153 swid_tag_id_t *tag_id;
154 bool match = FALSE;
155
156 target_enumerator = targets->create_enumerator(targets);
157 while (target_enumerator->enumerate(target_enumerator, &tag_id))
158 {
159 if (chunk_equals(tag_id->get_unique_sw_id(tag_id, NULL),
160 unique_sw_id) &&
161 chunk_equals(tag_id->get_tag_creator(tag_id),
162 tag_creator))
163 {
164 match = TRUE;
165 break;
166 }
167 }
168 target_enumerator->destroy(target_enumerator);
169
170 if (!match)
171 {
172 continue;
173 }
174 }
175 DBG2(DBG_IMC, " %s", rel_name);
176
177 if (this->full_tags)
178 {
179 swid_tag_t *tag;
180 chunk_t *xml_tag;
181
182 xml_tag = chunk_map(abs_name, FALSE);
183 if (!xml_tag)
184 {
185 DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name,
186 strerror(errno));
187 goto end;
188 }
189
190 tag = swid_tag_create(*xml_tag, unique_seq_id);
191 this->list->insert_last(this->list, tag);
192 chunk_unmap(xml_tag);
193 }
194 else
195 {
196 swid_tag_id_t *tag_id;
197
198 tag_id = swid_tag_id_create(tag_creator, unique_sw_id, unique_seq_id);
199 this->list->insert_last(this->list, tag_id);
200 }
201
202 }
203 success = TRUE;
204
205 end:
206 enumerator->destroy(enumerator);
207 DBG2(DBG_IMC, "leaving %s", pathname);
208
209 return success;
210 }
211
212 METHOD(swid_inventory_t, collect, bool,
213 private_swid_inventory_t *this, char *directory, swid_inventory_t *targets)
214 {
215 return collect_tags(this, directory, targets);
216 }
217
218 METHOD(swid_inventory_t, add, void,
219 private_swid_inventory_t *this, void *item)
220 {
221 this->list->insert_last(this->list, item);
222 }
223
224 METHOD(swid_inventory_t, get_count, int,
225 private_swid_inventory_t *this)
226 {
227 return this->list->get_count(this->list);
228 }
229
230 METHOD(swid_inventory_t, create_enumerator, enumerator_t*,
231 private_swid_inventory_t *this)
232 {
233 return this->list->create_enumerator(this->list);
234 }
235
236 METHOD(swid_inventory_t, destroy, void,
237 private_swid_inventory_t *this)
238 {
239 if (this->full_tags)
240 {
241 this->list->destroy_offset(this->list, offsetof(swid_tag_t, destroy));
242 }
243 else
244 {
245 this->list->destroy_offset(this->list, offsetof(swid_tag_id_t, destroy));
246 }
247 free(this);
248 }
249
250 /**
251 * See header
252 */
253 swid_inventory_t *swid_inventory_create(bool full_tags)
254 {
255 private_swid_inventory_t *this;
256
257 INIT(this,
258 .public = {
259 .collect = _collect,
260 .add = _add,
261 .get_count = _get_count,
262 .create_enumerator = _create_enumerator,
263 .destroy = _destroy,
264 },
265 .full_tags = full_tags,
266 .list = linked_list_create(),
267 );
268
269 return &this->public;
270 }