18#include <libxml/parser.h>
19#include <libxml/tree.h>
20#include <libxml/xmlIO.h>
21#include <libxml/xmlstring.h>
40decompress_file(
const char *filename)
45 BZFILE *bz_file = NULL;
46 FILE *
input = fopen(filename,
"r");
49 crm_perror(LOG_ERR,
"Could not open %s for reading", filename);
53 bz_file = BZ2_bzReadOpen(&rc,
input, 0, 0, NULL, 0);
56 crm_err(
"Could not prepare to read compressed %s: %s "
67 if ((rc == BZ_OK) || (rc == BZ_STREAM_END)) {
68 crm_trace(
"Read %ld bytes from file: %d", (
long) read_len, rc);
71 }
while (rc == BZ_OK);
76 crm_err(
"Could not read compressed %s: %s " QB_XS
" rc=%d",
81 buffer[length] =
'\0';
85 BZ2_bzReadClose(&rc, bz_file);
105 xmlDoc *output = NULL;
106 xmlParserCtxt *ctxt = NULL;
107 const xmlError *last_error = NULL;
110 ctxt = xmlNewParserCtxt();
113 xmlCtxtResetLastError(ctxt);
117 output = xmlCtxtReadFd(ctxt, STDIN_FILENO, NULL, NULL,
121 char *
input = decompress_file(filename);
124 output = xmlCtxtReadDoc(ctxt, (
const xmlChar *)
input, NULL, NULL,
130 output = xmlCtxtReadFile(ctxt, filename, NULL, XML_PARSE_NOBLANKS);
133 if (output != NULL) {
135 xml = xmlDocGetRootElement(output);
147 last_error = xmlCtxtGetLastError(ctxt);
148 if ((last_error != NULL) && (xml != NULL)) {
154 xmlFreeParserCtxt(ctxt);
170 xmlDoc *output = NULL;
171 xmlParserCtxt *ctxt = NULL;
172 const xmlError *last_error = NULL;
178 ctxt = xmlNewParserCtxt();
183 xmlCtxtResetLastError(ctxt);
186 output = xmlCtxtReadDoc(ctxt, (
const xmlChar *)
input, NULL, NULL,
188 if (output != NULL) {
190 xml = xmlDocGetRootElement(output);
193 last_error = xmlCtxtGetLastError(ctxt);
194 if ((last_error != NULL) && (xml != NULL)) {
200 xmlFreeParserCtxt(ctxt);
214dump_xml_element(
const xmlNode *
data, uint32_t options, GString *buffer,
219 int spaces = pretty? (2 * depth) : 0;
221 for (
int lpc = 0; lpc < spaces; lpc++) {
222 g_string_append_c(buffer,
' ');
227 for (
const xmlAttr *attr = pcmk__xe_first_attr(
data); attr != NULL;
235 if (
data->children == NULL) {
236 g_string_append(buffer,
"/>");
239 g_string_append_c(buffer,
'>');
243 g_string_append_c(buffer,
'\n');
246 if (
data->children) {
247 for (
const xmlNode *child =
data->children; child != NULL;
248 child = child->next) {
252 for (
int lpc = 0; lpc < spaces; lpc++) {
253 g_string_append_c(buffer,
' ');
259 g_string_append_c(buffer,
'\n');
274dump_xml_text(
const xmlNode *
data, uint32_t options, GString *buffer,
278 int spaces = pretty? (2 * depth) : 0;
279 const char *content = (
const char *)
data->content;
280 gchar *content_esc = NULL;
284 content = content_esc;
287 for (
int lpc = 0; lpc < spaces; lpc++) {
288 g_string_append_c(buffer,
' ');
291 g_string_append(buffer, content);
294 g_string_append_c(buffer,
'\n');
309dump_xml_cdata(
const xmlNode *
data, uint32_t options, GString *buffer,
313 int spaces = pretty? (2 * depth) : 0;
315 for (
int lpc = 0; lpc < spaces; lpc++) {
316 g_string_append_c(buffer,
' ');
323 g_string_append_c(buffer,
'\n');
337dump_xml_comment(
const xmlNode *
data, uint32_t options, GString *buffer,
341 int spaces = pretty? (2 * depth) : 0;
343 for (
int lpc = 0; lpc < spaces; lpc++) {
344 g_string_append_c(buffer,
' ');
350 g_string_append_c(buffer,
'\n');
382 case XML_ELEMENT_NODE:
384 dump_xml_element(
data, options, buffer, depth);
388 dump_xml_text(
data, options, buffer, depth);
391 case XML_COMMENT_NODE:
392 dump_xml_comment(
data, options, buffer, depth);
394 case XML_CDATA_SECTION_NODE:
395 dump_xml_cdata(
data, options, buffer, depth);
398 crm_warn(
"Cannot convert XML %s node to text " QB_XS
" type=%d",
416write_compressed_stream(
char *text,
const char *filename, FILE *stream,
417 unsigned int *bytes_out)
419 unsigned int bytes_in = 0;
423 BZFILE *bz_file = BZ2_bzWriteOpen(&rc, stream, 5, 0, 0);
427 crm_warn(
"Not compressing %s: could not prepare file stream: %s "
433 BZ2_bzWrite(&rc, bz_file, text, strlen(text));
436 crm_warn(
"Not compressing %s: could not compress data: %s "
437 QB_XS
" rc=%d errno=%d",
442 BZ2_bzWriteClose(&rc, bz_file, 0, &bytes_in, bytes_out);
446 crm_warn(
"Not compressing %s: could not write compressed data: %s "
447 QB_XS
" rc=%d errno=%d",
452 crm_trace(
"Compressed XML for %s from %u bytes to %u",
453 filename, bytes_in, *bytes_out);
456 if (bz_file != NULL) {
457 BZ2_bzWriteClose(&rc, bz_file, 0, NULL, NULL);
475write_xml_stream(
const xmlNode *xml,
const char *filename, FILE *stream,
478 GString *buffer = g_string_sized_new(1024);
479 unsigned int bytes_out = 0;
491 && (write_compressed_stream(buffer->str, filename, stream,
496 rc = fprintf(stream,
"%s", buffer->str);
502 bytes_out = (
unsigned int) rc;
506 if (fflush(stream) != 0) {
512 if ((fsync(fileno(stream)) < 0) && (errno != EROFS) && (errno != EINVAL)) {
514 crm_perror(LOG_ERR,
"synchronizing %s", filename);
518 crm_trace(
"Saved %u bytes to %s as XML", bytes_out, filename);
520 g_string_free(buffer, TRUE);
539 CRM_CHECK((xml != NULL) && (fd > 0),
return EINVAL);
540 stream = fdopen(fd,
"w");
541 if (stream == NULL) {
545 return write_xml_stream(xml, pcmk__s(filename,
"unnamed file"), stream,
564 CRM_CHECK((xml != NULL) && (filename != NULL),
return EINVAL);
565 stream = fopen(filename,
"w");
566 if (stream == NULL) {
570 return write_xml_stream(xml, filename, stream, compress);
587 xmlOutputBuffer *fd_out = xmlOutputBufferCreateFd(fd, NULL);
591 success = xmlOutputBufferWrite(fd_out,
sizeof(
"\n") - 1,
"\n") != -1;
593 success = xmlOutputBufferClose(fd_out) != -1 && success;
608 if (filename == NULL) {
616 crm_info(
"Saving %s to %s", desc, filename);
char * crm_generate_uuid(void)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
G_GNUC_INTERNAL const char * pcmk__xml_element_type_text(xmlElementType type)
#define PCMK__BUFFER_SIZE
G_GNUC_INTERNAL void pcmk__xml_new_private_data(xmlNode *xml)
G_GNUC_INTERNAL void pcmk__dump_xml_attr(const xmlAttr *attr, GString *buffer)
G_GNUC_INTERNAL bool pcmk__xa_filterable(const char *name)
G_GNUC_INTERNAL void pcmk__log_xmllib_err(void *ctx, const char *fmt,...) G_GNUC_PRINTF(2
const char * pcmk__get_tmpdir(void)
#define crm_log_xml_info(xml, text)
#define crm_info(fmt, args...)
#define crm_warn(fmt, args...)
#define crm_log_xml_debug(xml, text)
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
#define CRM_CHECK(expr, failure_action)
#define crm_err(fmt, args...)
#define crm_log_xml_trace(xml, text)
#define crm_trace(fmt, args...)
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
#define pcmk__assert(expr)
#define pcmk__mem_assert(ptr)
int pcmk__bzlib2rc(int bz2)
Map a bz2 return code to the most similar Pacemaker return code.
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
bool pcmk__ends_with_ext(const char *s, const char *match)
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Wrappers for and extensions to libxml2.
@ pcmk__xml_fmt_pretty
Include indentation and newlines.
@ pcmk__xml_fmt_filtered
Exclude certain XML attributes (for calculating digests)
@ pcmk__xml_fmt_text
Include XML text nodes.
bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type)
void pcmk__strip_xml_text(xmlNode *xml)
char * pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type)
void pcmk__xml_free(xmlNode *xml)
int pcmk__xml_write_fd(const xmlNode *xml, const char *filename, int fd)
void save_xml_to_file(const xmlNode *xml, const char *desc, const char *filename)
void pcmk__xml_string(const xmlNode *data, uint32_t options, GString *buffer, int depth)
xmlNode * pcmk__xml_read(const char *filename)
int pcmk__xml2fd(int fd, xmlNode *cur)
int pcmk__xml_write_file(const xmlNode *xml, const char *filename, bool compress)
xmlNode * pcmk__xml_parse(const char *input)
Wrappers for and extensions to XML input/output functions.