15 #include <sys/types.h> 18 #include <libxml/parser.h> 19 #include <libxml/tree.h> 20 #include <libxml/xmlIO.h> 39 decompress_file(
const char *filename)
44 BZFILE *bz_file = NULL;
45 FILE *
input = fopen(filename,
"r");
48 crm_perror(LOG_ERR,
"Could not open %s for reading", filename);
52 bz_file = BZ2_bzReadOpen(&rc,
input, 0, 0, NULL, 0);
55 crm_err(
"Could not prepare to read compressed %s: %s " 68 if ((rc == BZ_OK) || (rc == BZ_STREAM_END)) {
69 crm_trace(
"Read %ld bytes from file: %d", (
long) read_len, rc);
72 }
while (rc == BZ_OK);
77 crm_err(
"Could not read compressed %s: %s " QB_XS
" rc=%d",
82 buffer[length] =
'\0';
86 BZ2_bzReadClose(&rc, bz_file);
106 xmlDoc *output = NULL;
107 xmlParserCtxt *ctxt = NULL;
108 const xmlError *last_error = NULL;
111 ctxt = xmlNewParserCtxt();
114 xmlCtxtResetLastError(ctxt);
118 output = xmlCtxtReadFd(ctxt, STDIN_FILENO, NULL, NULL,
122 char *
input = decompress_file(filename);
131 output = xmlCtxtReadFile(ctxt, filename, NULL, XML_PARSE_NOBLANKS);
134 if (output != NULL) {
136 xml = xmlDocGetRootElement(output);
148 last_error = xmlCtxtGetLastError(ctxt);
149 if ((last_error != NULL) && (xml != NULL)) {
155 xmlFreeParserCtxt(ctxt);
171 xmlDoc *output = NULL;
172 xmlParserCtxt *ctxt = NULL;
173 const xmlError *last_error = NULL;
179 ctxt = xmlNewParserCtxt();
184 xmlCtxtResetLastError(ctxt);
189 if (output != NULL) {
191 xml = xmlDocGetRootElement(output);
194 last_error = xmlCtxtGetLastError(ctxt);
195 if ((last_error != NULL) && (xml != NULL)) {
201 xmlFreeParserCtxt(ctxt);
215 dump_xml_element(
const xmlNode *
data, uint32_t options, GString *buffer,
220 int spaces = pretty? (2 * depth) : 0;
222 for (
int lpc = 0; lpc < spaces; lpc++) {
223 g_string_append_c(buffer,
' ');
228 for (
const xmlAttr *attr = pcmk__xe_first_attr(
data); attr != NULL;
236 if (
data->children == NULL) {
237 g_string_append(buffer,
"/>");
240 g_string_append_c(buffer,
'>');
244 g_string_append_c(buffer,
'\n');
247 if (
data->children) {
248 for (
const xmlNode *child =
data->children; child != NULL;
249 child = child->next) {
253 for (
int lpc = 0; lpc < spaces; lpc++) {
254 g_string_append_c(buffer,
' ');
260 g_string_append_c(buffer,
'\n');
275 dump_xml_text(
const xmlNode *
data, uint32_t options, GString *buffer,
279 int spaces = pretty? (2 * depth) : 0;
280 const char *content = (
const char *)
data->content;
281 gchar *content_esc = NULL;
285 content = content_esc;
288 for (
int lpc = 0; lpc < spaces; lpc++) {
289 g_string_append_c(buffer,
' ');
292 g_string_append(buffer, content);
295 g_string_append_c(buffer,
'\n');
310 dump_xml_cdata(
const xmlNode *
data, uint32_t options, GString *buffer,
314 int spaces = pretty? (2 * depth) : 0;
316 for (
int lpc = 0; lpc < spaces; lpc++) {
317 g_string_append_c(buffer,
' ');
324 g_string_append_c(buffer,
'\n');
338 dump_xml_comment(
const xmlNode *
data, uint32_t options, GString *buffer,
342 int spaces = pretty? (2 * depth) : 0;
344 for (
int lpc = 0; lpc < spaces; lpc++) {
345 g_string_append_c(buffer,
' ');
351 g_string_append_c(buffer,
'\n');
364 xml_element_type_text(xmlElementType
type)
366 static const char *
const element_type_names[] = {
367 [XML_ELEMENT_NODE] =
"element",
368 [XML_ATTRIBUTE_NODE] =
"attribute",
369 [XML_TEXT_NODE] =
"text",
370 [XML_CDATA_SECTION_NODE] =
"CDATA section",
371 [XML_ENTITY_REF_NODE] =
"entity reference",
372 [XML_ENTITY_NODE] =
"entity",
373 [XML_PI_NODE] =
"PI",
374 [XML_COMMENT_NODE] =
"comment",
375 [XML_DOCUMENT_NODE] =
"document",
376 [XML_DOCUMENT_TYPE_NODE] =
"document type",
377 [XML_DOCUMENT_FRAG_NODE] =
"document fragment",
378 [XML_NOTATION_NODE] =
"notation",
379 [XML_HTML_DOCUMENT_NODE] =
"HTML document",
380 [XML_DTD_NODE] =
"DTD",
381 [XML_ELEMENT_DECL] =
"element declaration",
382 [XML_ATTRIBUTE_DECL] =
"attribute declaration",
383 [XML_ENTITY_DECL] =
"entity declaration",
384 [XML_NAMESPACE_DECL] =
"namespace declaration",
385 [XML_XINCLUDE_START] =
"XInclude start",
386 [XML_XINCLUDE_END] =
"XInclude end",
390 return "unrecognized type";
392 return element_type_names[
type];
423 case XML_ELEMENT_NODE:
425 dump_xml_element(
data, options, buffer, depth);
429 dump_xml_text(
data, options, buffer, depth);
432 case XML_COMMENT_NODE:
433 dump_xml_comment(
data, options, buffer, depth);
435 case XML_CDATA_SECTION_NODE:
436 dump_xml_cdata(
data, options, buffer, depth);
439 crm_warn(
"Cannot convert XML %s node to text " QB_XS
" type=%d",
440 xml_element_type_text(
data->type),
data->type);
457 write_compressed_stream(
char *text,
const char *filename, FILE *stream,
458 unsigned int *bytes_out)
460 unsigned int bytes_in = 0;
464 BZFILE *bz_file = BZ2_bzWriteOpen(&rc, stream, 5, 0, 0);
468 crm_warn(
"Not compressing %s: could not prepare file stream: %s " 474 BZ2_bzWrite(&rc, bz_file, text, strlen(text));
477 crm_warn(
"Not compressing %s: could not compress data: %s " 478 QB_XS
" rc=%d errno=%d",
483 BZ2_bzWriteClose(&rc, bz_file, 0, &bytes_in, bytes_out);
487 crm_warn(
"Not compressing %s: could not write compressed data: %s " 488 QB_XS
" rc=%d errno=%d",
493 crm_trace(
"Compressed XML for %s from %u bytes to %u",
494 filename, bytes_in, *bytes_out);
497 if (bz_file != NULL) {
498 BZ2_bzWriteClose(&rc, bz_file, 0, NULL, NULL);
516 write_xml_stream(
const xmlNode *xml,
const char *filename, FILE *stream,
519 GString *buffer = g_string_sized_new(1024);
520 unsigned int bytes_out = 0;
532 && (write_compressed_stream(buffer->str, filename, stream,
537 rc = fprintf(stream,
"%s", buffer->str);
543 bytes_out = (
unsigned int) rc;
547 if (fflush(stream) != 0) {
553 if ((fsync(fileno(stream)) < 0) && (errno != EROFS) && (errno != EINVAL)) {
555 crm_perror(LOG_ERR,
"synchronizing %s", filename);
559 crm_trace(
"Saved %u bytes to %s as XML", bytes_out, filename);
561 g_string_free(buffer, TRUE);
580 CRM_CHECK((xml != NULL) && (fd > 0),
return EINVAL);
581 stream = fdopen(fd,
"w");
582 if (stream == NULL) {
586 return write_xml_stream(xml, pcmk__s(filename,
"unnamed file"), stream,
605 CRM_CHECK((xml != NULL) && (filename != NULL),
return EINVAL);
606 stream = fopen(filename,
"w");
607 if (stream == NULL) {
611 return write_xml_stream(xml, filename, stream, compress);
628 xmlOutputBuffer *fd_out = xmlOutputBufferCreateFd(fd, NULL);
632 success = xmlOutputBufferWrite(fd_out,
sizeof(
"\n") - 1,
"\n") != -1;
634 success = xmlOutputBufferClose(fd_out) != -1 && success;
649 if (filename == NULL) {
657 crm_info(
"Saving %s to %s", desc, filename);
#define CRM_CHECK(expr, failure_action)
char * pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type)
char * crm_generate_uuid(void)
void pcmk__xml_string(const xmlNode *data, uint32_t options, GString *buffer, int depth)
enum pcmk_ipc_server type
int pcmk__xml_write_fd(const xmlNode *xml, const char *filename, int fd)
bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type)
G_GNUC_INTERNAL void pcmk__log_xmllib_err(void *ctx, const char *fmt,...) G_GNUC_PRINTF(2
Exclude certain XML attributes (for calculating digests)
xmlNode * pcmk__xml_parse(const char *input)
Wrappers for and extensions to XML input/output functions.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Include indentation and newlines.
void pcmk__xml_free(xmlNode *xml)
#define crm_warn(fmt, args...)
void pcmk__strip_xml_text(xmlNode *xml)
G_GNUC_INTERNAL void pcmk__xml_new_private_data(xmlNode *xml)
#define crm_trace(fmt, args...)
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
#define crm_log_xml_debug(xml, text)
Wrappers for and extensions to libxml2.
int pcmk__xml_write_file(const xmlNode *xml, const char *filename, bool compress)
xmlNode * pcmk__xml_read(const char *filename)
int pcmk__xml2fd(int fd, xmlNode *cur)
const xmlChar * pcmkXmlStr
G_GNUC_INTERNAL bool pcmk__xa_filterable(const char *name)
#define pcmk__assert(expr)
const char * pcmk__get_tmpdir(void)
int pcmk__bzlib2rc(int bz2)
Map a bz2 return code to the most similar Pacemaker return code.
#define PCMK__BUFFER_SIZE
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
#define crm_err(fmt, args...)
G_GNUC_INTERNAL void pcmk__dump_xml_attr(const xmlAttr *attr, GString *buffer)
#define pcmk__mem_assert(ptr)
#define crm_log_xml_info(xml, text)
#define crm_log_xml_trace(xml, text)
void save_xml_to_file(const xmlNode *xml, const char *desc, const char *filename)
#define crm_info(fmt, args...)
bool pcmk__ends_with_ext(const char *s, const char *match)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1