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