2 * libopensync - A synchronization framework
3 * Copyright (C) 2006 NetNix Finland Ltd <netnix@netnix.fi>
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.
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>
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
);
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
);
46 int ret
= regcomp(preg
, pattern
, 0);
51 errbuf_size
= regerror(ret
, preg
, NULL
, 0);
52 errbuf
= osync_try_malloc0(errbuf_size
, error
);
55 regerror(ret
, preg
, errbuf
, errbuf_size
);
56 osync_error_set(error
, OSYNC_ERROR_GENERIC
, "%s", errbuf
);
61 ret
= regexec(preg
, string
, 0, NULL
, 0);
66 if(ret
== REG_NOMATCH
)
68 errbuf_size
= regerror(ret
, preg
, NULL
, 0);
69 errbuf
= osync_try_malloc0(errbuf_size
, error
);
72 regerror(ret
, preg
, errbuf
, errbuf_size
);
73 osync_error_set(error
, OSYNC_ERROR_GENERIC
, "%s", errbuf
);
85 #else /* HAVE_GLIB_GREGEX_H */
86 return g_regex_match_simple(pattern
, string
, 0, 0);
90 OSyncList
*osync_version_load_from_descriptions(OSyncError
**error
, const char *descriptiondir
, const char *schemadir
)
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
;
105 osync_trace(TRACE_ENTRY
, "%s(%p)", __func__
, error
);
107 dir
= g_dir_open(descpath
, 0, &gerror
);
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
);
115 while ((de
= g_dir_read_name(dir
))) {
116 char *schemafilepath
= NULL
;
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
);
126 doc
= xmlReadFile(filename
, NULL
, XML_PARSE_NOBLANKS
);
128 osync_free(filename
);
132 osync_free(filename
);
134 root
= xmlDocGetRootElement(doc
);
135 if(!root
|| !xmlStrEqual(root
->name
, BAD_CAST
"versions")) {
136 osync_xml_free_doc(doc
);
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
);
145 osync_xml_free_doc(doc
);
149 cur
= root
->children
;
150 for(; cur
!= NULL
; cur
= cur
->next
) {
152 version
= osync_version_new(error
);
154 OSyncList
*cur
= NULL
;
155 osync_xml_free_doc(doc
);
156 cur
= osync_list_first(versions
);
158 osync_version_unref(cur
->data
);
164 child
= cur
->children
;
165 osync_version_set_plugin(version
, (const char *)osync_xml_node_get_content(child
));
167 osync_version_set_priority(version
, (const char *)osync_xml_node_get_content(child
));
169 osync_version_set_vendor(version
, (const char *)osync_xml_node_get_content(child
));
171 osync_version_set_modelversion(version
, (const char *)osync_xml_node_get_content(child
));
173 osync_version_set_firmwareversion(version
, (const char *)osync_xml_node_get_content(child
));
175 osync_version_set_softwareversion(version
, (const char *)osync_xml_node_get_content(child
));
177 osync_version_set_hardwareversion(version
, (const char *)osync_xml_node_get_content(child
));
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
);
189 osync_trace(TRACE_EXIT
, "%s: %p", __func__
, versions
);
193 osync_trace(TRACE_EXIT_ERROR
, "%s: %s", __func__
, osync_error_print(error
));
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
);
204 osync_trace(TRACE_EXIT_ERROR
, "%s: %s" , __func__
, osync_error_print(error
));
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
);
222 OSyncVersion
*osync_version_ref(OSyncVersion
*version
)
224 osync_assert(version
);
226 g_atomic_int_inc(&(version
->ref_count
));
231 void osync_version_unref(OSyncVersion
*version
)
233 osync_assert(version
);
235 if (g_atomic_int_dec_and_test(&(version
->ref_count
))) {
238 osync_free(version
->plugin
);
239 if(version
->priority
)
240 osync_free(version
->priority
);
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
);
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
)
301 osync_free(version
->plugin
);
303 version
->plugin
= osync_strdup("");
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
);
313 version
->priority
= osync_strdup("");
315 version
->priority
= osync_strdup(priority
);
318 void osync_version_set_vendor(OSyncVersion
*version
, const char *vendor
)
321 osync_free(version
->vendor
);
323 version
->vendor
= osync_strdup("");
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
);
333 version
->modelversion
= osync_strdup("");
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
);
343 version
->firmwareversion
= osync_strdup("");
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
);
353 version
->softwareversion
= osync_strdup("");
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
);
364 version
->hardwareversion
= osync_strdup("");
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
);
374 version
->identifier
= osync_strdup("");
376 version
->identifier
= osync_strdup(identifier
);
379 int osync_version_matches(OSyncVersion
*pattern
, OSyncVersion
*version
, OSyncError
**error
)
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
);
391 ret
= _osync_version_match(osync_version_get_vendor(pattern
), osync_version_get_vendor(version
), error
);
395 ret
= _osync_version_match(osync_version_get_modelversion(pattern
), osync_version_get_modelversion(version
), error
);
399 ret
= _osync_version_match(osync_version_get_firmwareversion(pattern
), osync_version_get_firmwareversion(version
), error
);
403 ret
= _osync_version_match(osync_version_get_softwareversion(pattern
), osync_version_get_softwareversion(version
), error
);
407 ret
= _osync_version_match(osync_version_get_hardwareversion(pattern
), osync_version_get_hardwareversion(version
), error
);
411 ret
= atoi(osync_version_get_priority(pattern
));
415 osync_trace(TRACE_EXIT
, "%s: %i" , __func__
, ret
);
418 osync_trace(TRACE_EXIT_ERROR
, "%s: %s" , __func__
, osync_error_print(error
));
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
)
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 */
442 cur
= osync_list_first(versions
);
444 int curpriority
= osync_version_matches(cur
->data
, version
, error
);
445 if (curpriority
== -1) {
447 osync_list_free(versions
);
450 osync_version_unref(winner
);
455 if( curpriority
> 0 && curpriority
> priority
) {
457 osync_version_unref(winner
);
460 osync_version_ref(winner
);
461 priority
= curpriority
;
463 osync_version_unref(cur
->data
);
466 osync_list_free(versions
);
468 /* we found or own capabilities */
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
);
480 osync_trace(TRACE_EXIT
, "%s: %p", __func__
, capabilities
);
485 osync_trace(TRACE_EXIT_ERROR
, "%s: %s", __func__
, osync_error_print(error
));