windows port - regular expressions are not supported by mingw - replaced with glib...
[opensync.git] / opensync / version / opensync_version.c
blobd3a2572f2ac82eaa741ee5fd7a93c2d76310b0d3
1 /*
2 * libopensync - A synchronization framework
3 * Copyright (C) 2006 NetNix Finland Ltd <netnix@netnix.fi>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Author: Daniel Friedrich <daniel.friedrich@opensync.org>
23 #include "opensync.h"
24 #include "opensync_internals.h"
26 #include "opensync-capabilities.h"
27 #include "capabilities/opensync-capabilities_internals.h"
29 #include "opensync-version.h"
30 #include "opensync-version_internals.h"
31 #include "opensync_version_private.h"
33 static int _osync_version_match(char *pattern, char* string, OSyncError **error)
35 osync_assert(pattern);
36 osync_assert(string);
37 if(!strlen(pattern))
38 return 1;
39 /* Only newer versions of glib support regular expressions */
40 /* On Windows the glib regular expressions are required */
41 #ifndef HAVE_GLIB_GREGEX_H
42 regex_t *preg = osync_try_malloc0(sizeof(regex_t), error);
43 if(!preg)
44 goto error;
46 int ret = regcomp(preg, pattern, 0);
48 char *errbuf;
49 size_t errbuf_size;
50 if(ret) {
51 errbuf_size = regerror(ret, preg, NULL, 0);
52 errbuf = osync_try_malloc0(errbuf_size, error);
53 if(!errbuf)
54 goto error_and_free;
55 regerror(ret, preg, errbuf, errbuf_size);
56 osync_error_set(error, OSYNC_ERROR_GENERIC, "%s", errbuf);
57 osync_free(errbuf);
58 goto error_and_free;
61 ret = regexec(preg, string, 0, NULL, 0);
62 regfree(preg);
63 osync_free(preg);
65 if(ret != 0) {
66 if(ret == REG_NOMATCH)
67 return 0;
68 errbuf_size = regerror(ret, preg, NULL, 0);
69 errbuf = osync_try_malloc0(errbuf_size, error);
70 if(!errbuf)
71 goto error;
72 regerror(ret, preg, errbuf, errbuf_size);
73 osync_error_set(error, OSYNC_ERROR_GENERIC, "%s", errbuf);
74 osync_free(errbuf);
75 goto error;
77 return 1;
79 error_and_free:
80 regfree(preg);
81 osync_free(preg);
82 error:
83 return -1;
85 #else /* HAVE_GLIB_GREGEX_H */
86 return g_regex_match_simple(pattern, string, 0, 0);
87 #endif
90 OSyncList *osync_version_load_from_descriptions(OSyncError **error, const char *descriptiondir, const char *schemadir)
92 GDir *dir = NULL;
93 GError *gerror = NULL;
94 const char *descpath = descriptiondir ? descriptiondir : OPENSYNC_DESCRIPTIONSDIR;
95 const char *schemapath = schemadir ? schemadir : OPENSYNC_SCHEMASDIR;
96 char *filename = NULL;
97 const gchar *de = NULL;
98 OSyncList *versions = NULL;
99 OSyncVersion *version = NULL;
100 xmlDocPtr doc;
101 xmlNodePtr root;
102 xmlNodePtr cur;
103 xmlNodePtr child;
105 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, error);
107 dir = g_dir_open(descpath, 0, &gerror);
108 if (!dir) {
109 /* If description directory doesn't exist (e.g. unittests), just ignore this. */
110 osync_trace(TRACE_EXIT, "Unable to open directory %s: %s", descpath, gerror->message);
111 g_error_free(gerror);
112 return NULL;
115 while ((de = g_dir_read_name(dir))) {
116 char *schemafilepath = NULL;
117 osync_bool res;
119 filename = osync_strdup_printf ("%s%c%s", descpath, G_DIR_SEPARATOR, de);
121 if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR) || !g_pattern_match_simple("*.xml", filename)) {
122 osync_free(filename);
123 continue;
126 doc = xmlReadFile(filename, NULL, XML_PARSE_NOBLANKS);
127 if(!doc) {
128 osync_free(filename);
129 continue;
132 osync_free(filename);
134 root = xmlDocGetRootElement(doc);
135 if(!root || !xmlStrEqual(root->name, BAD_CAST "versions")) {
136 osync_xml_free_doc(doc);
137 continue;
140 schemafilepath = osync_strdup_printf("%s%c%s", schemapath, G_DIR_SEPARATOR, "descriptions.xsd");
141 res = osync_xml_validate_document(doc, schemafilepath);
142 osync_free(schemafilepath);
144 if(res == FALSE) {
145 osync_xml_free_doc(doc);
146 continue;
149 cur = root->children;
150 for(; cur != NULL; cur = cur->next) {
152 version = osync_version_new(error);
153 if(!version) {
154 OSyncList *cur = NULL;
155 osync_xml_free_doc(doc);
156 cur = osync_list_first(versions);
157 while(cur) {
158 osync_version_unref(cur->data);
159 cur = cur->next;
161 goto error;
164 child = cur->children;
165 osync_version_set_plugin(version, (const char *)osync_xml_node_get_content(child));
166 child = child->next;
167 osync_version_set_priority(version, (const char *)osync_xml_node_get_content(child));
168 child = child->next;
169 osync_version_set_vendor(version, (const char *)osync_xml_node_get_content(child));
170 child = child->next;
171 osync_version_set_modelversion(version, (const char *)osync_xml_node_get_content(child));
172 child = child->next;
173 osync_version_set_firmwareversion(version, (const char *)osync_xml_node_get_content(child));
174 child = child->next;
175 osync_version_set_softwareversion(version, (const char *)osync_xml_node_get_content(child));
176 child = child->next;
177 osync_version_set_hardwareversion(version, (const char *)osync_xml_node_get_content(child));
178 child = child->next;
179 osync_version_set_identifier(version, (const char *)osync_xml_node_get_content(child));
181 versions = osync_list_append(versions, version);
184 osync_xml_free_doc(doc);
187 g_dir_close(dir);
189 osync_trace(TRACE_EXIT, "%s: %p", __func__, versions);
190 return versions;
192 error:
193 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
194 return NULL;
197 OSyncVersion *osync_version_new(OSyncError **error)
199 OSyncVersion *version = NULL;
200 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, error);
202 version = osync_try_malloc0(sizeof(OSyncVersion), error);
203 if(!version) {
204 osync_trace(TRACE_EXIT_ERROR, "%s: %s" , __func__, osync_error_print(error));
205 return NULL;
208 version->ref_count = 1;
209 version->plugin = osync_strdup("");
210 version->priority = osync_strdup("");
211 version->vendor = osync_strdup("");
212 version->modelversion = osync_strdup("");
213 version->firmwareversion = osync_strdup("");
214 version->softwareversion = osync_strdup("");
215 version->hardwareversion = osync_strdup("");
216 version->identifier = osync_strdup("");
218 osync_trace(TRACE_EXIT, "%s: %p", __func__, version);
219 return version;
222 OSyncVersion *osync_version_ref(OSyncVersion *version)
224 osync_assert(version);
226 g_atomic_int_inc(&(version->ref_count));
228 return version;
231 void osync_version_unref(OSyncVersion *version)
233 osync_assert(version);
235 if (g_atomic_int_dec_and_test(&(version->ref_count))) {
237 if(version->plugin)
238 osync_free(version->plugin);
239 if(version->priority)
240 osync_free(version->priority);
241 if(version->vendor)
242 osync_free(version->vendor);
243 if(version->modelversion)
244 osync_free(version->modelversion);
245 if(version->firmwareversion)
246 osync_free(version->firmwareversion);
247 if(version->softwareversion)
248 osync_free(version->softwareversion);
249 if(version->hardwareversion)
250 osync_free(version->hardwareversion);
251 if(version->identifier)
252 osync_free(version->identifier);
254 osync_free(version);
258 char *osync_version_get_plugin(OSyncVersion *version)
260 return version->plugin;
263 char *osync_version_get_priority(OSyncVersion *version)
265 return version->priority;
268 char *osync_version_get_vendor(OSyncVersion *version)
270 return version->vendor;
273 char *osync_version_get_modelversion(OSyncVersion *version)
275 return version->modelversion;
278 char *osync_version_get_firmwareversion(OSyncVersion *version)
280 return version->firmwareversion;
283 char *osync_version_get_softwareversion(OSyncVersion *version)
285 return version->softwareversion;
288 char *osync_version_get_hardwareversion(OSyncVersion *version)
290 return version->hardwareversion;
293 char *osync_version_get_identifier(OSyncVersion *version)
295 return version->identifier;
298 void osync_version_set_plugin(OSyncVersion *version, const char *plugin)
300 if(version->plugin)
301 osync_free(version->plugin);
302 if(!plugin)
303 version->plugin = osync_strdup("");
304 else
305 version->plugin = osync_strdup(plugin);
308 void osync_version_set_priority(OSyncVersion *version, const char *priority)
310 if(version->priority)
311 osync_free(version->priority);
312 if(!priority)
313 version->priority = osync_strdup("");
314 else
315 version->priority = osync_strdup(priority);
318 void osync_version_set_vendor(OSyncVersion *version, const char *vendor)
320 if(version->vendor)
321 osync_free(version->vendor);
322 if(!vendor)
323 version->vendor = osync_strdup("");
324 else
325 version->vendor = osync_strdup(vendor);
328 void osync_version_set_modelversion(OSyncVersion *version, const char *modelversion)
330 if(version->modelversion)
331 osync_free(version->modelversion);
332 if(!modelversion)
333 version->modelversion = osync_strdup("");
334 else
335 version->modelversion = osync_strdup(modelversion);
338 void osync_version_set_firmwareversion(OSyncVersion *version, const char *firmwareversion)
340 if(version->firmwareversion)
341 osync_free(version->firmwareversion);
342 if(!firmwareversion)
343 version->firmwareversion = osync_strdup("");
344 else
345 version->firmwareversion = osync_strdup(firmwareversion);
348 void osync_version_set_softwareversion(OSyncVersion *version, const char *softwareversion)
350 if(version->softwareversion)
351 osync_free(version->softwareversion);
352 if(!softwareversion)
353 version->softwareversion = osync_strdup("");
354 else
355 version->softwareversion = osync_strdup(softwareversion);
359 void osync_version_set_hardwareversion(OSyncVersion *version, const char *hardwareversion)
361 if(version->hardwareversion)
362 osync_free(version->hardwareversion);
363 if(!hardwareversion)
364 version->hardwareversion = osync_strdup("");
365 else
366 version->hardwareversion = osync_strdup(hardwareversion);
369 void osync_version_set_identifier(OSyncVersion *version, const char *identifier)
371 if(version->identifier)
372 osync_free(version->identifier);
373 if(!identifier)
374 version->identifier = osync_strdup("");
375 else
376 version->identifier = osync_strdup(identifier);
379 int osync_version_matches(OSyncVersion *pattern, OSyncVersion *version, OSyncError **error)
381 int ret;
382 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, pattern, version, error);
384 osync_assert(pattern);
385 osync_assert(version);
387 ret = _osync_version_match(osync_version_get_plugin(pattern), osync_version_get_plugin(version), error);
388 if(ret <= 0)
389 goto error;
391 ret = _osync_version_match(osync_version_get_vendor(pattern), osync_version_get_vendor(version), error);
392 if(ret <= 0)
393 goto error;
395 ret = _osync_version_match(osync_version_get_modelversion(pattern), osync_version_get_modelversion(version), error);
396 if(ret <= 0)
397 goto error;
399 ret = _osync_version_match(osync_version_get_firmwareversion(pattern), osync_version_get_firmwareversion(version), error);
400 if(ret <= 0)
401 goto error;
403 ret = _osync_version_match(osync_version_get_softwareversion(pattern), osync_version_get_softwareversion(version), error);
404 if(ret <= 0)
405 goto error;
407 ret = _osync_version_match(osync_version_get_hardwareversion(pattern), osync_version_get_hardwareversion(version), error);
408 if(ret <= 0)
409 goto error;
411 ret = atoi(osync_version_get_priority(pattern));
413 error:
414 if(ret >= 0) {
415 osync_trace(TRACE_EXIT, "%s: %i" , __func__, ret);
416 return ret;
418 osync_trace(TRACE_EXIT_ERROR, "%s: %s" , __func__, osync_error_print(error));
419 return -1;
422 OSyncList *osync_version_load_from_default_descriptions(OSyncError **error)
424 return osync_version_load_from_descriptions(error, NULL, NULL);
427 OSyncCapabilities *osync_version_find_capabilities(OSyncVersion *version, OSyncError **error)
429 int priority = -1;
430 OSyncVersion *winner = NULL;
431 OSyncCapabilities *capabilities = NULL;
432 OSyncList *versions = NULL;
433 OSyncList *cur = NULL;
435 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, version, error);
436 osync_assert(version);
438 versions = osync_version_load_from_default_descriptions(error);
439 if (*error) /* versions can be null */
440 goto error;
442 cur = osync_list_first(versions);
443 while(cur) {
444 int curpriority = osync_version_matches(cur->data, version, error);
445 if (curpriority == -1) {
446 if (versions)
447 osync_list_free(versions);
449 if (winner)
450 osync_version_unref(winner);
452 goto error;
455 if( curpriority > 0 && curpriority > priority) {
456 if(winner)
457 osync_version_unref(winner);
459 winner = cur->data;
460 osync_version_ref(winner);
461 priority = curpriority;
463 osync_version_unref(cur->data);
464 cur = cur->next;
466 osync_list_free(versions);
468 /* we found or own capabilities */
469 if(priority > 0)
471 osync_trace(TRACE_INTERNAL, "Found capabilities file by version: %s ", (const char*)osync_version_get_identifier(winner));
473 capabilities = osync_capabilities_load((const char*)osync_version_get_identifier(winner), error);
474 osync_version_unref(winner);
476 if (!capabilities)
477 goto error;
480 osync_trace(TRACE_EXIT, "%s: %p", __func__, capabilities);
481 return capabilities;
483 error:
485 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
486 return NULL;