15 #include <sys/types.h> 18 #include <libxml/parser.h> 19 #include <libxml/tree.h> 20 #include <libxml/xmlIO.h> 32 #define PCMK__XML_PARSE_OPTS_WITHOUT_RECOVER (XML_PARSE_NOBLANKS) 33 #define PCMK__XML_PARSE_OPTS_WITH_RECOVER (XML_PARSE_NOBLANKS \ 54 }
while ((feof(stdin) == 0) && (ferror(stdin) == 0));
56 if (ferror(stdin) != 0) {
57 crm_err(
"Error reading input from stdin");
79 decompress_file(
const char *filename)
84 BZFILE *bz_file = NULL;
85 FILE *
input = fopen(filename,
"r");
88 crm_perror(LOG_ERR,
"Could not open %s for reading", filename);
92 bz_file = BZ2_bzReadOpen(&rc,
input, 0, 0, NULL, 0);
95 crm_err(
"Could not prepare to read compressed %s: %s " 108 if ((rc == BZ_OK) || (rc == BZ_STREAM_END)) {
109 crm_trace(
"Read %ld bytes from file: %d", (
long) read_len, rc);
112 }
while (rc == BZ_OK);
122 buffer[length] =
'\0';
126 BZ2_bzReadClose(&rc, bz_file);
141 #define parse_xml_recover(result, fn, ...) do { \ 142 *result = fn(__VA_ARGS__, PCMK__XML_PARSE_OPTS_WITHOUT_RECOVER); \ 143 if (*result == NULL) { \ 144 *result = fn(__VA_ARGS__, PCMK__XML_PARSE_OPTS_WITH_RECOVER); \ 146 if (*result != NULL) { \ 147 crm_warn("Successfully recovered from XML errors " \ 148 "(note: a future release will treat this as a " \ 170 xmlDoc *output = NULL;
171 xmlParserCtxt *ctxt = NULL;
172 const xmlError *last_error = NULL;
175 ctxt = xmlNewParserCtxt();
178 xmlCtxtResetLastError(ctxt);
188 char *
input = read_stdin();
197 char *
input = decompress_file(filename);
209 if (output != NULL) {
211 xml = xmlDocGetRootElement(output);
224 last_error = xmlCtxtGetLastError(ctxt);
225 if (last_error != NULL) {
231 xmlFreeParserCtxt(ctxt);
248 xmlDoc *output = NULL;
249 xmlParserCtxt *ctxt = NULL;
250 const xmlError *last_error = NULL;
256 ctxt = xmlNewParserCtxt();
261 xmlCtxtResetLastError(ctxt);
267 if (output != NULL) {
269 xml = xmlDocGetRootElement(output);
273 last_error = xmlCtxtGetLastError(ctxt);
274 if (last_error != NULL) {
280 xmlFreeParserCtxt(ctxt);
294 dump_xml_element(
const xmlNode *
data, uint32_t options, GString *buffer,
299 int spaces = pretty? (2 * depth) : 0;
301 for (
int lpc = 0; lpc < spaces; lpc++) {
302 g_string_append_c(buffer,
' ');
307 for (
const xmlAttr *attr = pcmk__xe_first_attr(
data); attr != NULL;
315 if (
data->children == NULL) {
316 g_string_append(buffer,
"/>");
319 g_string_append_c(buffer,
'>');
323 g_string_append_c(buffer,
'\n');
326 if (
data->children) {
327 for (
const xmlNode *child =
data->children; child != NULL;
328 child = child->next) {
332 for (
int lpc = 0; lpc < spaces; lpc++) {
333 g_string_append_c(buffer,
' ');
339 g_string_append_c(buffer,
'\n');
354 dump_xml_text(
const xmlNode *
data, uint32_t options, GString *buffer,
358 int spaces = pretty? (2 * depth) : 0;
359 const char *content = (
const char *)
data->content;
360 gchar *content_esc = NULL;
364 content = content_esc;
367 for (
int lpc = 0; lpc < spaces; lpc++) {
368 g_string_append_c(buffer,
' ');
371 g_string_append(buffer, content);
374 g_string_append_c(buffer,
'\n');
389 dump_xml_cdata(
const xmlNode *
data, uint32_t options, GString *buffer,
393 int spaces = pretty? (2 * depth) : 0;
395 for (
int lpc = 0; lpc < spaces; lpc++) {
396 g_string_append_c(buffer,
' ');
403 g_string_append_c(buffer,
'\n');
417 dump_xml_comment(
const xmlNode *
data, uint32_t options, GString *buffer,
421 int spaces = pretty? (2 * depth) : 0;
423 for (
int lpc = 0; lpc < spaces; lpc++) {
424 g_string_append_c(buffer,
' ');
430 g_string_append_c(buffer,
'\n');
443 xml_element_type_text(xmlElementType
type)
445 static const char *
const element_type_names[] = {
446 [XML_ELEMENT_NODE] =
"element",
447 [XML_ATTRIBUTE_NODE] =
"attribute",
448 [XML_TEXT_NODE] =
"text",
449 [XML_CDATA_SECTION_NODE] =
"CDATA section",
450 [XML_ENTITY_REF_NODE] =
"entity reference",
451 [XML_ENTITY_NODE] =
"entity",
452 [XML_PI_NODE] =
"PI",
453 [XML_COMMENT_NODE] =
"comment",
454 [XML_DOCUMENT_NODE] =
"document",
455 [XML_DOCUMENT_TYPE_NODE] =
"document type",
456 [XML_DOCUMENT_FRAG_NODE] =
"document fragment",
457 [XML_NOTATION_NODE] =
"notation",
458 [XML_HTML_DOCUMENT_NODE] =
"HTML document",
459 [XML_DTD_NODE] =
"DTD",
460 [XML_ELEMENT_DECL] =
"element declaration",
461 [XML_ATTRIBUTE_DECL] =
"attribute declaration",
462 [XML_ENTITY_DECL] =
"entity declaration",
463 [XML_NAMESPACE_DECL] =
"namespace declaration",
464 [XML_XINCLUDE_START] =
"XInclude start",
465 [XML_XINCLUDE_END] =
"XInclude end",
469 return "unrecognized type";
471 return element_type_names[
type];
502 case XML_ELEMENT_NODE:
504 dump_xml_element(
data, options, buffer, depth);
508 dump_xml_text(
data, options, buffer, depth);
511 case XML_COMMENT_NODE:
512 dump_xml_comment(
data, options, buffer, depth);
514 case XML_CDATA_SECTION_NODE:
515 dump_xml_cdata(
data, options, buffer, depth);
519 xml_element_type_text(
data->type),
data->type);
536 write_compressed_stream(
char *text,
const char *filename, FILE *stream,
537 unsigned int *bytes_out)
539 unsigned int bytes_in = 0;
543 BZFILE *bz_file = BZ2_bzWriteOpen(&rc, stream, 5, 0, 0);
547 crm_warn(
"Not compressing %s: could not prepare file stream: %s " 553 BZ2_bzWrite(&rc, bz_file, text, strlen(text));
556 crm_warn(
"Not compressing %s: could not compress data: %s " 562 BZ2_bzWriteClose(&rc, bz_file, 0, &bytes_in, bytes_out);
566 crm_warn(
"Not compressing %s: could not write compressed data: %s " 572 crm_trace(
"Compressed XML for %s from %u bytes to %u",
573 filename, bytes_in, *bytes_out);
576 if (bz_file != NULL) {
577 BZ2_bzWriteClose(&rc, bz_file, 0, NULL, NULL);
596 write_xml_stream(
const xmlNode *xml,
const char *filename, FILE *stream,
597 bool compress,
unsigned int *nbytes)
600 GString *buffer = g_string_sized_new(1024);
601 unsigned int bytes_out = 0;
613 && (write_compressed_stream(buffer->str, filename, stream,
618 rc = fprintf(stream,
"%s", buffer->str);
624 bytes_out = (
unsigned int) rc;
628 if (fflush(stream) != 0) {
634 if ((fsync(fileno(stream)) < 0) && (errno != EROFS) && (errno != EINVAL)) {
636 crm_perror(LOG_ERR,
"synchronizing %s", filename);
640 crm_trace(
"Saved %u bytes to %s as XML", bytes_out, filename);
642 if (nbytes != NULL) {
645 g_string_free(buffer, TRUE);
663 bool compress,
unsigned int *nbytes)
668 CRM_CHECK((xml != NULL) && (fd > 0),
return EINVAL);
669 stream = fdopen(fd,
"w");
670 if (stream == NULL) {
674 return write_xml_stream(xml, pcmk__s(filename,
"unnamed file"), stream,
691 unsigned int *nbytes)
696 CRM_CHECK((xml != NULL) && (filename != NULL),
return EINVAL);
697 stream = fopen(filename,
"w");
698 if (stream == NULL) {
702 return write_xml_stream(xml, filename, stream, compress, nbytes);
719 xmlOutputBuffer *fd_out = xmlOutputBufferCreateFd(fd, NULL);
723 success = xmlOutputBufferWrite(fd_out,
sizeof(
"\n") - 1,
"\n") != -1;
725 success = xmlOutputBufferClose(fd_out) != -1 && success;
740 if (filename == NULL) {
748 crm_info(
"Saving %s to %s", desc, filename);
781 GString *buffer = g_string_sized_new(1024);
786 g_string_free(buffer, TRUE);
794 GString *buffer = g_string_sized_new(1024);
799 g_string_free(buffer, TRUE);
807 GString *buffer = g_string_sized_new(1024);
812 g_string_free(buffer, TRUE);
820 unsigned int nbytes = 0;
832 unsigned int nbytes = 0;
#define CRM_CHECK(expr, failure_action)
int pcmk__xml_write_file(const xmlNode *xml, const char *filename, bool compress, unsigned int *nbytes)
char * pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type)
char * crm_generate_uuid(void)
int pcmk_rc2legacy(int rc)
xmlNode * stdin2xml(void)
char * dump_xml_formatted(const xmlNode *xml)
void pcmk__xml_string(const xmlNode *data, uint32_t options, GString *buffer, int depth)
int write_xml_fd(const xmlNode *xml, const char *filename, int fd, gboolean compress)
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)
int pcmk__xml_write_fd(const xmlNode *xml, const char *filename, int fd, bool compress, unsigned int *nbytes)
xmlNode * pcmk__xml_parse(const char *input)
xmlNode * string2xml(const char *input)
xmlNode * filename2xml(const char *filename)
enum crm_ais_msg_types type
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.
#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
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Wrappers for and extensions to libxml2.
#define parse_xml_recover(result, fn,...)
int write_xml_file(const xmlNode *xml, const char *filename, gboolean compress)
char * dump_xml_formatted_with_text(const xmlNode *xml)
xmlNode * pcmk__xml_read(const char *filename)
#define pcmk__str_copy(str)
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)
char * dump_xml_unformatted(const xmlNode *xml)
Deprecated Pacemaker XML I/O API.
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)