19 #include <libxml/relaxng.h> 20 #include <libxslt/xslt.h> 21 #include <libxslt/transform.h> 22 #include <libxslt/security.h> 23 #include <libxslt/xsltutils.h> 30 #define SCHEMA_ZERO { .v = { 0, 0 } } 32 #define schema_strdup_printf(prefix, version, suffix) \ 33 crm_strdup_printf(prefix "%u.%u" suffix, (version).v[0], (version).v[1]) 37 xmlRelaxNGValidCtxtPtr valid;
38 xmlRelaxNGParserCtxtPtr parser;
39 } relaxng_ctx_cache_t;
41 static GList *known_schemas = NULL;
42 static bool initialized =
false;
43 static bool silent_logging = FALSE;
45 static void G_GNUC_PRINTF(2, 3)
46 xml_log(
int priority, const
char *fmt, ...)
51 if (silent_logging == FALSE) {
59 xml_latest_schema_index(
void)
68 return g_list_length(known_schemas) - 3;
78 get_highest_schema(
void)
86 CRM_ASSERT((entry != NULL) && (entry->prev != NULL));
99 GList *entry = get_highest_schema();
113 #if defined(PCMK__UNIT_TESTING) 118 GList *x_0_entry = NULL;
120 static GList *x_0_entry = NULL;
125 if (x_0_entry != NULL) {
128 x_0_entry = get_highest_schema();
129 highest_schema = x_0_entry->data;
131 for (GList *iter = x_0_entry->prev; iter != NULL; iter = iter->prev) {
139 x_0_entry = iter->next;
146 if (iter->prev == NULL) {
147 x_0_entry = known_schemas->data;
158 return sscanf(filename,
"pacemaker-%hhu.%hhu.rng", &(
version->v[0]), &(
version->v[1])) == 2;
160 return sscanf(filename,
"pacemaker-%hhu.%hhu", &(
version->v[0]), &(
version->v[1])) == 2;
165 schema_filter(
const struct dirent *a)
170 if (strstr(a->d_name,
"pacemaker-") != a->d_name) {
176 }
else if (!version_from_filename(a->d_name, &
version)) {
190 for (
int i = 0; i < 2; ++i) {
191 if (a_version.
v[i] < b_version.
v[i]) {
193 }
else if (a_version.
v[i] > b_version.
v[i]) {
201 schema_cmp_directory(
const struct dirent **a,
const struct dirent **b)
206 if (!version_from_filename(a[0]->d_name, &a_version)
207 || !version_from_filename(b[0]->d_name, &b_version)) {
212 return schema_cmp(a_version, b_version);
224 const char *
name,
const char *transform,
225 const char *transform_enter,
bool transform_onleave)
247 if (transform_enter) {
251 known_schemas = g_list_prepend(known_schemas, schema);
285 bool transform_onleave = FALSE;
289 *transform_upgrade = NULL,
290 *transform_enter = NULL;
293 if (transform_expected) {
300 if (!transform_expected) {
303 }
else if (stat(xslt, &s) == 0) {
309 if (stat(xslt, &s) != 0) {
311 crm_debug(
"Upgrade-enter transform %s.xsl not found", xslt);
313 free(transform_enter);
314 transform_enter = strdup(
"upgrade-enter");
317 if (stat(xslt, &s) != 0) {
318 crm_debug(
"Upgrade-enter transform %s.xsl not found, either", xslt);
326 memcpy(strrchr(xslt,
'-') + 1,
"leave",
sizeof(
"leave") - 1);
327 transform_onleave = (stat(xslt, &s) == 0);
330 free(transform_enter);
331 transform_enter = NULL;
335 crm_err(
"Upgrade transform %s not found", xslt);
337 free(transform_upgrade);
338 transform_upgrade = NULL;
343 transform_upgrade, transform_enter, transform_onleave);
345 free(transform_upgrade);
346 free(transform_enter);
352 wrap_libxslt(
bool finalize)
354 static xsltSecurityPrefsPtr secprefs;
360 secprefs = xsltNewSecurityPrefs();
361 ret = xsltSetSecurityPrefs(secprefs, XSLT_SECPREF_WRITE_FILE,
363 | xsltSetSecurityPrefs(secprefs, XSLT_SECPREF_CREATE_DIRECTORY,
365 | xsltSetSecurityPrefs(secprefs, XSLT_SECPREF_READ_NETWORK,
367 | xsltSetSecurityPrefs(secprefs, XSLT_SECPREF_WRITE_NETWORK,
373 xsltFreeSecurityPrefs(secprefs);
379 xsltCleanupGlobals();
387 struct dirent **namelist = NULL;
389 max = scandir(dir, &namelist, schema_filter, schema_cmp_directory);
391 crm_warn(
"Could not load schemas from %s: %s", dir, strerror(errno));
395 for (lpc = 0; lpc < max; lpc++) {
396 bool transform_expected =
false;
399 if (!version_from_filename(namelist[lpc]->d_name, &
version)) {
401 crm_warn(
"Skipping schema '%s': could not parse version",
402 namelist[lpc]->d_name);
405 if ((lpc + 1) < max) {
408 if (version_from_filename(namelist[lpc+1]->d_name, &next_version)
409 && (
version.v[0] < next_version.
v[0])) {
410 transform_expected =
true;
419 for (lpc = 0; lpc < max; lpc++) {
427 schema_sort_GCompareFunc(gconstpointer a, gconstpointer b)
459 known_schemas = g_list_sort(known_schemas, schema_sort_GCompareFunc);
476 int schema_index = 0;
501 for (GList *iter = known_schemas; iter != NULL; iter = iter->next) {
505 crm_debug(
"Loaded schema %d: %s", schema_index, schema->
name);
507 crm_debug(
"Loaded schema %d: %s (upgrades with %s.xsl)",
516 validate_with_relaxng(xmlDocPtr doc, xmlRelaxNGValidityErrorFunc error_handler,
517 void *error_handler_context,
const char *relaxng_file,
518 relaxng_ctx_cache_t **cached_ctx)
522 relaxng_ctx_cache_t *ctx = NULL;
525 CRM_CHECK(relaxng_file != NULL,
return false);
527 if (cached_ctx && *cached_ctx) {
531 crm_debug(
"Creating RNG parser context");
534 ctx->parser = xmlRelaxNGNewParserCtxt(relaxng_file);
535 CRM_CHECK(ctx->parser != NULL,
goto cleanup);
538 xmlRelaxNGSetParserErrors(ctx->parser,
539 (xmlRelaxNGValidityErrorFunc) error_handler,
540 (xmlRelaxNGValidityWarningFunc) error_handler,
541 error_handler_context);
543 xmlRelaxNGSetParserErrors(ctx->parser,
544 (xmlRelaxNGValidityErrorFunc) fprintf,
545 (xmlRelaxNGValidityWarningFunc) fprintf,
549 ctx->rng = xmlRelaxNGParse(ctx->parser);
551 crm_err(
"Could not find/parse %s", relaxng_file);
554 ctx->valid = xmlRelaxNGNewValidCtxt(ctx->rng);
555 CRM_CHECK(ctx->valid != NULL,
goto cleanup);
558 xmlRelaxNGSetValidErrors(ctx->valid,
559 (xmlRelaxNGValidityErrorFunc) error_handler,
560 (xmlRelaxNGValidityWarningFunc) error_handler,
561 error_handler_context);
563 xmlRelaxNGSetValidErrors(ctx->valid,
564 (xmlRelaxNGValidityErrorFunc) fprintf,
565 (xmlRelaxNGValidityWarningFunc) fprintf,
570 rc = xmlRelaxNGValidateDoc(ctx->valid, doc);
575 crm_err(
"Internal libxml error during validation");
584 if (ctx->parser != NULL) {
585 xmlRelaxNGFreeParserCtxt(ctx->parser);
587 if (ctx->valid != NULL) {
588 xmlRelaxNGFreeValidCtxt(ctx->valid);
590 if (ctx->rng != NULL) {
591 xmlRelaxNGFree(ctx->rng);
600 free_schema(gpointer
data)
603 relaxng_ctx_cache_t *ctx = NULL;
610 ctx = (relaxng_ctx_cache_t *) schema->
cache;
615 if (ctx->parser != NULL) {
616 xmlRelaxNGFreeParserCtxt(ctx->parser);
619 if (ctx->valid != NULL) {
620 xmlRelaxNGFreeValidCtxt(ctx->valid);
623 if (ctx->rng != NULL) {
624 xmlRelaxNGFree(ctx->rng);
628 schema->
cache = NULL;
645 if (known_schemas != NULL) {
646 g_list_free_full(known_schemas, free_schema);
647 known_schemas = NULL;
669 for (GList *iter = known_schemas; iter != NULL; iter = iter->next) {
696 if (entry1 == NULL) {
697 return (entry2 == NULL)? 0 : -1;
699 }
else if (entry2 == NULL) {
712 xmlRelaxNGValidityErrorFunc error_handler,
713 void *error_handler_context)
717 relaxng_ctx_cache_t **cache = NULL;
719 if (schema == NULL) {
730 crm_trace(
"Validating with %s (type=%d)",
731 pcmk__s(file,
"missing schema"), schema->
validator);
734 cache = (relaxng_ctx_cache_t **) &(schema->
cache);
735 valid = validate_with_relaxng(xml->doc, error_handler, error_handler_context, file, cache);
749 bool rc, sl_backup = silent_logging;
750 silent_logging = TRUE;
751 rc = validate_with(xml, schema, (xmlRelaxNGValidityErrorFunc) xml_log, GUINT_TO_POINTER(LOG_ERR));
752 silent_logging = sl_backup;
758 xmlRelaxNGValidityErrorFunc error_handler,
759 void *error_handler_context)
764 CRM_CHECK((xml_blob != NULL) && (xml_blob->doc != NULL),
return false);
766 if (validation == NULL) {
772 if (validation == NULL) {
775 for (entry = known_schemas; entry != NULL; entry = entry->next) {
776 schema = entry->data;
777 if (validate_with(xml_blob, schema, NULL, NULL)) {
789 " set to an unknown schema such as '%s' (manually" 790 " edit to use a known schema)",
795 schema = entry->data;
796 return validate_with(xml_blob, schema, error_handler,
797 error_handler_context);
812 (xmlRelaxNGValidityErrorFunc) xml_log,
813 GUINT_TO_POINTER(LOG_ERR));
839 static void G_GNUC_PRINTF(2, 3)
840 cib_upgrade_err(
void *ctx, const
char *fmt, ...)
846 const char *fmt_iter = fmt;
847 uint8_t msg_log_level = LOG_WARNING;
848 const unsigned * log_level = (
const unsigned *) ctx;
852 } scan_state = escan_seennothing;
857 while (!found && *fmt_iter !=
'\0') {
859 switch (*fmt_iter++) {
861 if (scan_state == escan_seennothing) {
862 scan_state = escan_seenpercent;
863 }
else if (scan_state == escan_seenpercent) {
864 scan_state = escan_seennothing;
868 if (scan_state == escan_seenpercent) {
869 scan_state = escan_seennothing;
870 arg_cur = va_arg(aq,
char *);
871 if (arg_cur != NULL) {
872 switch (arg_cur[0]) {
874 if (!strncmp(arg_cur,
"WARNING: ",
875 sizeof(
"WARNING: ") - 1)) {
876 msg_log_level = LOG_WARNING;
879 memmove(arg_cur, arg_cur +
sizeof(
"WARNING: ") - 1,
880 strlen(arg_cur +
sizeof(
"WARNING: ") - 1) + 1);
885 if (!strncmp(arg_cur,
"INFO: ",
886 sizeof(
"INFO: ") - 1)) {
887 msg_log_level = LOG_INFO;
890 memmove(arg_cur, arg_cur +
sizeof(
"INFO: ") - 1,
891 strlen(arg_cur +
sizeof(
"INFO: ") - 1) + 1);
896 if (!strncmp(arg_cur,
"DEBUG: ",
897 sizeof(
"DEBUG: ") - 1)) {
898 msg_log_level = LOG_DEBUG;
901 memmove(arg_cur, arg_cur +
sizeof(
"DEBUG: ") - 1,
902 strlen(arg_cur +
sizeof(
"DEBUG: ") - 1) + 1);
910 case '#':
case '-':
case ' ':
case '+':
case '\'':
case 'I':
case '.':
911 case '0':
case '1':
case '2':
case '3':
case '4':
912 case '5':
case '6':
case '7':
case '8':
case '9':
929 if (scan_state == escan_seenpercent) {
930 (void) va_arg(aq,
void *);
931 scan_state = escan_seennothing;
935 scan_state = escan_seennothing;
940 if (log_level != NULL) {
943 if (*log_level + 4 >= msg_log_level) {
944 vfprintf(stderr, fmt, ap);
966 apply_transformation(
const xmlNode *xml,
const char *transform,
971 xmlDocPtr res = NULL;
972 xsltStylesheet *xslt = NULL;
979 xsltSetGenericErrorFunc(NULL, cib_upgrade_err);
984 xslt = xsltParseStylesheetFile((
pcmkXmlStr) xform);
987 res = xsltApplyStylesheet(xslt, xml->doc, NULL);
990 xsltSetGenericErrorFunc(NULL, NULL);
992 out = xmlDocGetRootElement(res);
996 xsltFreeStylesheet(xslt);
1021 apply_upgrade(
const xmlNode *original_xml,
int schema_index, gboolean to_logs)
1023 pcmk__schema_t *schema = g_list_nth_data(known_schemas, schema_index);
1026 bool transform_onleave =
false;
1027 char *transform_leave;
1028 const xmlNode *xml = original_xml;
1029 xmlNode *upgrade = NULL;
1030 xmlNode *
final = NULL;
1031 xmlRelaxNGValidityErrorFunc error_handler = NULL;
1033 CRM_ASSERT((schema != NULL) && (upgraded_schema != NULL));
1036 error_handler = (xmlRelaxNGValidityErrorFunc) xml_log;
1041 crm_debug(
"Upgrading schema from %s to %s: " 1042 "applying pre-upgrade XSL transform %s",
1044 upgrade = apply_transformation(xml, schema->
transform_enter, to_logs);
1045 if (upgrade == NULL) {
1046 crm_warn(
"Pre-upgrade XSL transform %s failed, " 1047 "will skip post-upgrade transform",
1049 transform_onleave = FALSE;
1056 crm_debug(
"Upgrading schema from %s to %s: " 1057 "applying upgrade XSL transform %s",
1059 final = apply_transformation(xml, schema->
transform, to_logs);
1060 if (upgrade != xml) {
1065 if ((
final != NULL) && transform_onleave) {
1071 memcpy(strrchr(transform_leave,
'-') + 1,
"leave",
sizeof(
"leave") - 1);
1072 crm_debug(
"Upgrading schema from %s to %s: " 1073 "applying post-upgrade XSL transform %s",
1074 schema->
name, upgraded_schema->
name, transform_leave);
1075 final = apply_transformation(upgrade, transform_leave, to_logs);
1076 if (
final == NULL) {
1077 crm_warn(
"Ignoring failure of post-upgrade XSL transform %s",
1083 free(transform_leave);
1086 if (
final == NULL) {
1091 if (!validate_with(
final, upgraded_schema, error_handler,
1092 GUINT_TO_POINTER(LOG_ERR))) {
1093 crm_err(
"Schema upgrade from %s to %s failed: " 1094 "XSL transform %s produced an invalid configuration",
1101 crm_info(
"Schema upgrade from %s to %s succeeded",
1102 schema->
name, upgraded_schema->
name);
1115 get_configured_schema(
const xmlNode *xml)
1120 if (schema_name == NULL) {
1144 int max_stable_schemas = xml_latest_schema_index();
1145 int max_schema_index = 0;
1147 GList *entry = NULL;
1150 xmlRelaxNGValidityErrorFunc error_handler =
1151 to_logs ? (xmlRelaxNGValidityErrorFunc) xml_log : NULL;
1153 CRM_CHECK((xml != NULL) && (*xml != NULL) && ((*xml)->doc != NULL),
1156 if (max_schema_name != NULL) {
1159 if (max_entry != NULL) {
1165 if ((max_schema_index < 1) || (max_schema_index > max_stable_schemas)) {
1166 max_schema_index = max_stable_schemas;
1169 entry = get_configured_schema(*xml);
1170 if (entry == NULL) {
1172 entry = known_schemas;
1174 original_schema = entry->data;
1175 if (original_schema->
schema_index >= max_schema_index) {
1180 for (; entry != NULL; entry = entry->next) {
1182 xmlNode *upgrade = NULL;
1188 if (!validate_with(*xml, current_schema, error_handler,
1189 GUINT_TO_POINTER(LOG_ERR))) {
1190 crm_debug(
"Schema %s does not validate", current_schema->
name);
1191 if (best_schema != NULL) {
1201 best_schema = current_schema;
1202 if (current_schema->
schema_index == max_schema_index) {
1206 if (!transform || (current_schema->
transform == NULL)
1207 || validate_with_silent(*xml, entry->next->data)) {
1215 upgrade = apply_upgrade(*xml, current_schema->
schema_index, to_logs);
1216 if (upgrade == NULL) {
1223 best_schema = current_schema;
1229 if (best_schema != NULL) {
1230 if ((original_schema == NULL)
1232 crm_info(
"%s the configuration schema to %s",
1233 (transform?
"Transformed" :
"Upgraded"),
1260 char *original_schema_name = NULL;
1263 const char *effective_original_name =
"the first";
1265 int orig_version = -1;
1267 GList *entry = NULL;
1274 if (entry != NULL) {
1277 effective_original_name = original_schema->
name;
1281 if (orig_version < x_0_schema->schema_index) {
1283 xmlNode *converted = NULL;
1284 const char *new_schema_name = NULL;
1294 schema = (entry == NULL)? NULL : entry->data;
1296 if ((schema == NULL)
1300 if ((orig_version == -1) || (schema == NULL)
1305 "%s schema) to at least %s because it " 1306 "does not validate with any schema from " 1308 pcmk__s(original_schema_name,
"no"),
1309 x_0_schema->
name, effective_original_name);
1311 fprintf(stderr,
"Cannot upgrade configuration (claiming " 1312 "%s schema) to at least %s because it " 1313 "does not validate with any schema from " 1314 "%s to the latest\n",
1315 pcmk__s(original_schema_name,
"no"),
1316 x_0_schema->
name, effective_original_name);
1322 "%s schema) to at least %s because it " 1323 "would not upgrade past %s",
1324 pcmk__s(original_schema_name,
"no"),
1326 pcmk__s(new_schema_name,
"unspecified version"));
1328 fprintf(stderr,
"Cannot upgrade configuration (claiming " 1329 "%s schema) to at least %s because it " 1330 "would not upgrade past %s\n",
1331 pcmk__s(original_schema_name,
"no"),
1333 pcmk__s(new_schema_name,
"unspecified version"));
1346 if (schema->
schema_index < xml_latest_schema_index()) {
1349 "internally upgraded to acceptable (but " 1350 "not most recent) %s",
1351 pcmk__s(original_schema_name,
"no"),
1354 }
else if (to_logs) {
1355 crm_info(
"Configuration with %s schema was internally " 1356 "upgraded to latest version %s",
1357 pcmk__s(original_schema_name,
"no"),
1367 CRM_ASSERT((entry != NULL) && (entry->data != NULL));
1369 none_schema = entry->data;
1370 if (!to_logs && (orig_version >= none_schema->
schema_index)) {
1371 fprintf(stderr,
"Schema validation of configuration is " 1374 " and will be removed in a future release)\n");
1378 free(original_schema_name);
1400 if (!version_from_filename(
name, &ver)) {
1404 for (GList *iter = g_list_nth(known_schemas, xml_latest_schema_index());
1405 iter != NULL; iter = iter->prev) {
1409 if (schema_cmp(ver, schema->
version) != -1) {
1414 lst = g_list_prepend(lst, s);
1418 lst = g_list_prepend(lst, xform);
1424 lst = g_list_prepend(lst, enter);
1427 int last_dash = strrchr(enter,
'-') - enter;
1430 lst = g_list_prepend(lst, leave);
1439 append_href(xmlNode *xml,
void *user_data)
1441 GList **list = user_data;
1447 *list = g_list_prepend(*list, href);
1451 external_refs_in_schema(GList **list,
const char *contents)
1456 const char *search =
"//*[local-name()='externalRef'] | //*[local-name()='include']";
1464 read_file_contents(
const char *file,
char **contents)
1482 add_schema_file_to_xml(xmlNode *
parent,
const char *file, GList **already_included)
1484 char *contents = NULL;
1486 xmlNode *file_node = NULL;
1487 GList *includes = NULL;
1491 if (g_list_find_custom(*already_included, file, (GCompareFunc) strcmp) != NULL) {
1504 rc = read_file_contents(
path, &contents);
1516 *already_included = g_list_prepend(*already_included,
path);
1518 xmlAddChild(file_node, xmlNewCDataBlock(
parent->doc, (
pcmkXmlStr) contents,
1524 external_refs_in_schema(&includes, contents);
1529 for (GList *iter = includes; iter != NULL; iter = iter->next) {
1530 add_schema_file_to_xml(
parent, iter->data, already_included);
1534 g_list_free_full(includes, free);
1557 add_schema_file_to_xml(schema_node,
name, already_included);
1559 if (schema_node->children == NULL) {
1575 if (pcmk__str_empty(dir)) {
1591 if ((schema == NULL) ||
1594 "deprecated and will be removed in a future release " 1595 "without the possibility of upgrades (manually edit " 1596 "to use a supported schema)", pcmk__s(schema,
""));
1616 return (schema != NULL)? schema->
name :
"unknown";
1628 for (GList *iter = known_schemas; iter != NULL; iter = iter->next) {
1647 if ((best != NULL) && (xml != NULL) && (rc ==
pcmk_rc_ok)) {
1652 if (schema_entry != NULL) {
1664 to_logs? (xmlRelaxNGValidityErrorFunc) xml_log : NULL,
1665 GUINT_TO_POINTER(LOG_ERR));
1666 return rc? TRUE : FALSE;
1670 dump_file(
const char *filename)
1678 fp = fopen(filename,
"r");
1680 crm_perror(LOG_ERR,
"Could not open %s for reading", filename);
1684 fprintf(stderr,
"%4d ", ++line);
1690 }
else if (ch ==
'\n') {
1691 fprintf(stderr,
"\n%4d ", ++line);
1705 xmlNode *xml = NULL;
1706 gboolean rc = FALSE;
1707 char *filename = NULL;
1711 umask(S_IWGRP | S_IWOTH | S_IROTH);
1712 fd = mkstemp(filename);
1715 dump_file(filename);
1717 doc = xmlReadFile(filename, NULL, 0);
1718 xml = xmlDocGetRootElement(doc);
1725 return rc? TRUE : FALSE;
1733 if (best_version != NULL) {
1742 *best_version = (schema == NULL)? -1 : schema->
schema_index;
char * pcmk__xml_artefact_root(enum pcmk__xml_artefact_ns ns)
int pcmk_update_configured_schema(xmlNode **xml)
#define CRM_CHECK(expr, failure_action)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
void crm_schema_init(void)
#define schema_strdup_printf(prefix, version, suffix)
bool pcmk__validate_xml(xmlNode *xml_blob, const char *validation, xmlRelaxNGValidityErrorFunc error_handler, void *error_handler_context)
int pcmk_rc2legacy(int rc)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
int pcmk__cmp_schemas_by_name(const char *schema1_name, const char *schema2_name)
const char * pcmk__highest_schema_name(void)
#define pcmk__config_warn(fmt...)
#define pcmk__config_err(fmt...)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
int pcmk__update_configured_schema(xmlNode **xml, bool to_logs)
Update XML from its configured schema to the latest major series.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
bool pcmk__ends_with(const char *s, const char *match)
const char * pcmk__env_option(const char *option)
Deprecated Pacemaker XML API.
const char * pcmk__remote_schema_dir(void)
void pcmk__build_schema_xml_node(xmlNode *parent, const char *name, GList **already_included)
#define crm_warn(fmt, args...)
int get_schema_version(const char *name)
#define crm_debug(fmt, args...)
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define PCMK__XML_LOG_BASE(priority, dechunk, postemit, prefix, fmt, ap)
Base for directing lib{xml2,xslt} log into standard libqb backend.
gboolean validate_xml_verbose(const xmlNode *xml_blob)
GList * pcmk__get_schema(const char *name)
void crm_schema_cleanup(void)
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define crm_log_xml_debug(xml, text)
const char * get_schema_name(int version)
bool pcmk__configured_schema_validates(xmlNode *xml)
Wrappers for and extensions to libxml2.
enum pcmk__schema_validator validator
void free_xml(xmlNode *child)
int update_validation(xmlNode **xml, int *best, int max, gboolean transform, gboolean to_logs)
#define pcmk__str_copy(str)
#define PCMK_XA_VALIDATE_WITH
xmlNode * pcmk__xml_parse(const char *input)
#define PCMK__ENV_REMOTE_SCHEMA_DIRECTORY
const xmlChar * pcmkXmlStr
const char * pcmk__get_tmpdir(void)
gboolean validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
unsigned int crm_log_level
int pcmk__file_contents(const char *filename, char **contents)
void pcmk__load_schemas_from_dir(const char *dir)
GList * pcmk__schema_files_later_than(const char *name)
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
#define crm_err(fmt, args...)
void pcmk__warn_if_schema_deprecated(const char *schema)
pcmk__schema_version_t version
void crm_foreach_xpath_result(xmlNode *xml, const char *xpath, void(*helper)(xmlNode *, void *), void *user_data)
Run a supplied function for each result of an xpath search.
int pcmk__update_schema(xmlNode **xml, const char *max_schema_name, bool transform, bool to_logs)
Update CIB XML to latest schema that validates it.
gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs)
int pcmk__xml_write_fd(const xmlNode *xml, const char *filename, int fd, bool compress, unsigned int *nbytes)
GList * pcmk__find_x_0_schema(void)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
char * pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, const char *filespec)
#define pcmk__assert_alloc(nmemb, size)
void pcmk__sort_schemas(void)
#define PCMK__REMOTE_SCHEMA_DIR
#define crm_info(fmt, args...)
bool pcmk__ends_with_ext(const char *s, const char *match)
const char * xml_latest_schema(void)