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) {
210 xml = xmlDocGetRootElement(output);
223 last_error = xmlCtxtGetLastError(ctxt);
224 if (last_error != NULL) {
230 xmlFreeParserCtxt(ctxt);
247 xmlDoc *output = NULL;
248 xmlParserCtxt *ctxt = NULL;
249 const xmlError *last_error = NULL;
255 ctxt = xmlNewParserCtxt();
260 xmlCtxtResetLastError(ctxt);
266 if (output != NULL) {
267 xml = xmlDocGetRootElement(output);
271 last_error = xmlCtxtGetLastError(ctxt);
272 if (last_error != NULL) {
278 xmlFreeParserCtxt(ctxt);
292 dump_xml_element(
const xmlNode *
data, uint32_t options, GString *buffer,
297 int spaces = pretty? (2 * depth) : 0;
299 for (
int lpc = 0; lpc < spaces; lpc++) {
300 g_string_append_c(buffer,
' ');
305 for (
const xmlAttr *attr = pcmk__xe_first_attr(
data); attr != NULL;
313 if (
data->children == NULL) {
314 g_string_append(buffer,
"/>");
317 g_string_append_c(buffer,
'>');
321 g_string_append_c(buffer,
'\n');
324 if (
data->children) {
325 for (
const xmlNode *child =
data->children; child != NULL;
326 child = child->next) {
330 for (
int lpc = 0; lpc < spaces; lpc++) {
331 g_string_append_c(buffer,
' ');
337 g_string_append_c(buffer,
'\n');
352 dump_xml_text(
const xmlNode *
data, uint32_t options, GString *buffer,
356 int spaces = pretty? (2 * depth) : 0;
357 const char *content = (
const char *)
data->content;
358 gchar *content_esc = NULL;
362 content = content_esc;
365 for (
int lpc = 0; lpc < spaces; lpc++) {
366 g_string_append_c(buffer,
' ');
369 g_string_append(buffer, content);
372 g_string_append_c(buffer,
'\n');
387 dump_xml_cdata(
const xmlNode *
data, uint32_t options, GString *buffer,
391 int spaces = pretty? (2 * depth) : 0;
393 for (
int lpc = 0; lpc < spaces; lpc++) {
394 g_string_append_c(buffer,
' ');
401 g_string_append_c(buffer,
'\n');
415 dump_xml_comment(
const xmlNode *
data, uint32_t options, GString *buffer,
419 int spaces = pretty? (2 * depth) : 0;
421 for (
int lpc = 0; lpc < spaces; lpc++) {
422 g_string_append_c(buffer,
' ');
428 g_string_append_c(buffer,
'\n');
441 xml_element_type_text(xmlElementType
type)
443 static const char *
const element_type_names[] = {
444 [XML_ELEMENT_NODE] =
"element",
445 [XML_ATTRIBUTE_NODE] =
"attribute",
446 [XML_TEXT_NODE] =
"text",
447 [XML_CDATA_SECTION_NODE] =
"CDATA section",
448 [XML_ENTITY_REF_NODE] =
"entity reference",
449 [XML_ENTITY_NODE] =
"entity",
450 [XML_PI_NODE] =
"PI",
451 [XML_COMMENT_NODE] =
"comment",
452 [XML_DOCUMENT_NODE] =
"document",
453 [XML_DOCUMENT_TYPE_NODE] =
"document type",
454 [XML_DOCUMENT_FRAG_NODE] =
"document fragment",
455 [XML_NOTATION_NODE] =
"notation",
456 [XML_HTML_DOCUMENT_NODE] =
"HTML document",
457 [XML_DTD_NODE] =
"DTD",
458 [XML_ELEMENT_DECL] =
"element declaration",
459 [XML_ATTRIBUTE_DECL] =
"attribute declaration",
460 [XML_ENTITY_DECL] =
"entity declaration",
461 [XML_NAMESPACE_DECL] =
"namespace declaration",
462 [XML_XINCLUDE_START] =
"XInclude start",
463 [XML_XINCLUDE_END] =
"XInclude end",
467 return "unrecognized type";
469 return element_type_names[
type];
500 case XML_ELEMENT_NODE:
502 dump_xml_element(
data, options, buffer, depth);
506 dump_xml_text(
data, options, buffer, depth);
509 case XML_COMMENT_NODE:
510 dump_xml_comment(
data, options, buffer, depth);
512 case XML_CDATA_SECTION_NODE:
513 dump_xml_cdata(
data, options, buffer, depth);
517 xml_element_type_text(
data->type),
data->type);
534 write_compressed_stream(
char *text,
const char *filename, FILE *stream,
535 unsigned int *bytes_out)
537 unsigned int bytes_in = 0;
541 BZFILE *bz_file = BZ2_bzWriteOpen(&rc, stream, 5, 0, 0);
545 crm_warn(
"Not compressing %s: could not prepare file stream: %s " 551 BZ2_bzWrite(&rc, bz_file, text, strlen(text));
554 crm_warn(
"Not compressing %s: could not compress data: %s " 560 BZ2_bzWriteClose(&rc, bz_file, 0, &bytes_in, bytes_out);
564 crm_warn(
"Not compressing %s: could not write compressed data: %s " 570 crm_trace(
"Compressed XML for %s from %u bytes to %u",
571 filename, bytes_in, *bytes_out);
574 if (bz_file != NULL) {
575 BZ2_bzWriteClose(&rc, bz_file, 0, NULL, NULL);
594 write_xml_stream(
const xmlNode *xml,
const char *filename, FILE *stream,
595 bool compress,
unsigned int *nbytes)
598 GString *buffer = g_string_sized_new(1024);
599 unsigned int bytes_out = 0;
611 && (write_compressed_stream(buffer->str, filename, stream,
616 rc = fprintf(stream,
"%s", buffer->str);
622 bytes_out = (
unsigned int) rc;
626 if (fflush(stream) != 0) {
632 if ((fsync(fileno(stream)) < 0) && (errno != EROFS) && (errno != EINVAL)) {
634 crm_perror(LOG_ERR,
"synchronizing %s", filename);
638 crm_trace(
"Saved %u bytes to %s as XML", bytes_out, filename);
640 if (nbytes != NULL) {
643 g_string_free(buffer, TRUE);
661 bool compress,
unsigned int *nbytes)
666 CRM_CHECK((xml != NULL) && (fd > 0),
return EINVAL);
667 stream = fdopen(fd,
"w");
668 if (stream == NULL) {
672 return write_xml_stream(xml, pcmk__s(filename,
"unnamed file"), stream,
689 unsigned int *nbytes)
694 CRM_CHECK((xml != NULL) && (filename != NULL),
return EINVAL);
695 stream = fopen(filename,
"w");
696 if (stream == NULL) {
700 return write_xml_stream(xml, filename, stream, compress, nbytes);
717 xmlOutputBuffer *fd_out = xmlOutputBufferCreateFd(fd, NULL);
721 success = xmlOutputBufferWrite(fd_out,
sizeof(
"\n") - 1,
"\n") != -1;
723 success = xmlOutputBufferClose(fd_out) != -1 && success;
738 if (filename == NULL) {
746 crm_info(
"Saving %s to %s", desc, filename);
779 GString *buffer = g_string_sized_new(1024);
784 g_string_free(buffer, TRUE);
792 GString *buffer = g_string_sized_new(1024);
797 g_string_free(buffer, TRUE);
805 GString *buffer = g_string_sized_new(1024);
810 g_string_free(buffer, TRUE);
818 unsigned int nbytes = 0;
830 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)
#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)
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)