9a33018af98e2eaa21c1c9ca882ddcbf5caf721b
[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 <sys/mman.h>
28 #include <libgen.h>
29 #include <errno.h>
30
31 typedef struct private_swid_inventory_t private_swid_inventory_t;
32
33 #define SWID_TAG_DIRECTORY "/usr/share"
34
35 /**
36 * Private data of a swid_inventory_t object.
37 *
38 */
39 struct private_swid_inventory_t {
40
41 /**
42 * Public swid_inventory_t interface.
43 */
44 swid_inventory_t public;
45
46 /**
47 * Full SWID tags or just SWID tag IDs
48 */
49 bool full_tags;
50
51 /**
52 * List of SWID tags or tag IDs
53 */
54 linked_list_t *list;
55 };
56
57 static bool collect_tags(private_swid_inventory_t *this, char *pathname)
58 {
59 char *rel_name, *abs_name;
60 struct stat st;
61 bool success = FALSE;
62 enumerator_t *enumerator;
63
64 enumerator = enumerator_create_directory(pathname);
65 if (!enumerator)
66 {
67 DBG1(DBG_IMC, "directory '%s' can not be opened, %s",
68 pathname, strerror(errno));
69 return FALSE;
70 }
71 DBG2(DBG_IMC, "entering %s", pathname);
72
73 while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
74 {
75 char * start, *stop;
76 chunk_t tag_creator;
77 chunk_t unique_sw_id = chunk_empty, unique_seq_id = chunk_empty;
78
79 if (!strstr(rel_name, "regid."))
80 {
81 continue;
82 }
83 if (S_ISDIR(st.st_mode))
84 {
85 if (!collect_tags(this, abs_name))
86 {
87 goto end;
88 }
89 continue;
90 }
91 DBG2(DBG_IMC, " %s", rel_name);
92
93 /* parse the regid filename into its components */
94 start = rel_name;
95 stop = strchr(start, '_');
96 if (!stop)
97 {
98 DBG1(DBG_IMC, " '_' separator not found");
99 goto end;
100 }
101 tag_creator = chunk_create(start, stop-start);
102
103 start = stop + 1;
104 stop = strchr(start, '_');
105 if (stop)
106 {
107 unique_sw_id = chunk_create(start, stop-start);
108 start = stop + 1;
109 }
110
111 stop = strstr(start, ".swidtag");
112 if (!stop)
113 {
114 DBG1(DBG_IMC, " swidtag postfix not found");
115 goto end;
116 }
117 if (unique_sw_id.ptr)
118 {
119 unique_seq_id = chunk_create(start, stop-start);
120 }
121 else
122 {
123 unique_sw_id = chunk_create(start, stop-start);
124 }
125
126 if (this->full_tags)
127 {
128 swid_tag_t *tag;
129 chunk_t xml_tag;
130 struct stat sb;
131 void *addr;
132 int fd;
133
134 fd = open(abs_name, O_RDONLY);
135 if (fd == -1)
136 {
137 DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name,
138 strerror(errno));
139 goto end;
140 }
141
142 if (fstat(fd, &sb) == -1)
143 {
144 DBG1(DBG_IMC, " getting file size of '%s' failed: %s", abs_name,
145 strerror(errno));
146 close(fd);
147 goto end;
148 }
149
150 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
151 if (addr == MAP_FAILED)
152 {
153 DBG1(DBG_IMC, " mapping '%s' failed: %s", abs_name,
154 strerror(errno));
155 close(fd);
156 goto end;
157 }
158 xml_tag = chunk_create(addr, sb.st_size);
159
160 tag = swid_tag_create(xml_tag, unique_seq_id);
161 this->list->insert_last(this->list, tag);
162 }
163 else
164 {
165 swid_tag_id_t *tag_id;
166
167 tag_id = swid_tag_id_create(tag_creator, unique_sw_id, unique_seq_id);
168 this->list->insert_last(this->list, tag_id);
169 }
170
171 }
172 success = TRUE;
173
174 end:
175 enumerator->destroy(enumerator);
176 DBG2(DBG_IMC, "leaving %s", pathname);
177
178 return success;
179 }
180
181 METHOD(swid_inventory_t, collect, bool,
182 private_swid_inventory_t *this)
183 {
184 return collect_tags(this, SWID_TAG_DIRECTORY);
185 }
186
187 METHOD(swid_inventory_t, add, void,
188 private_swid_inventory_t *this, void *item)
189 {
190 this->list->insert_last(this->list, item);
191 }
192
193 METHOD(swid_inventory_t, get_count, int,
194 private_swid_inventory_t *this)
195 {
196 return this->list->get_count(this->list);
197 }
198
199 METHOD(swid_inventory_t, create_enumerator, enumerator_t*,
200 private_swid_inventory_t *this)
201 {
202 return this->list->create_enumerator(this->list);
203 }
204
205 METHOD(swid_inventory_t, destroy, void,
206 private_swid_inventory_t *this)
207 {
208 if (this->full_tags)
209 {
210 this->list->destroy_offset(this->list, offsetof(swid_tag_t, destroy));
211 }
212 else
213 {
214 this->list->destroy_offset(this->list, offsetof(swid_tag_id_t, destroy));
215 }
216 free(this);
217 }
218
219 /**
220 * See header
221 */
222 swid_inventory_t *swid_inventory_create(bool full_tags)
223 {
224 private_swid_inventory_t *this;
225
226 INIT(this,
227 .public = {
228 .collect = _collect,
229 .add = _add,
230 .get_count = _get_count,
231 .create_enumerator = _create_enumerator,
232 .destroy = _destroy,
233 },
234 .full_tags = full_tags,
235 .list = linked_list_create(),
236 );
237
238 return &this->public;
239 }
240
241