16#include <sys/utsname.h>
37#ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS
38#define TIMESTAMP_FORMAT_SPEC "%%T"
41#define TIMESTAMP_FORMAT_SPEC "%%t"
49static unsigned int crm_log_priority = LOG_NOTICE;
50static guint pcmk__log_id = 0;
51static guint pcmk__glib_log_id = 0;
52static guint pcmk__gio_log_id = 0;
53static guint pcmk__gmodule_log_id = 0;
54static guint pcmk__gthread_log_id = 0;
62static gboolean crm_tracing_enabled(
void);
65crm_glib_handler(
const gchar * log_domain, GLogLevelFlags
flags,
const gchar * message,
68 int log_level = LOG_WARNING;
69 GLogLevelFlags msg_level = (
flags & G_LOG_LEVEL_MASK);
70 static struct qb_log_callsite *glib_cs = NULL;
72 if (glib_cs == NULL) {
73 glib_cs = qb_log_callsite_get(__func__, __FILE__,
"glib-handler",
78 case G_LOG_LEVEL_CRITICAL:
83 crm_abort(__FILE__, __func__, __LINE__, message, TRUE, TRUE);
87 case G_LOG_LEVEL_ERROR:
90 case G_LOG_LEVEL_MESSAGE:
91 log_level = LOG_NOTICE;
93 case G_LOG_LEVEL_INFO:
96 case G_LOG_LEVEL_DEBUG:
97 log_level = LOG_DEBUG;
100 case G_LOG_LEVEL_WARNING:
101 case G_LOG_FLAG_RECURSION:
102 case G_LOG_FLAG_FATAL:
103 case G_LOG_LEVEL_MASK:
104 log_level = LOG_WARNING;
108 do_crm_log(log_level,
"%s: %s", log_domain, message);
124crm_trigger_blackbox(
int nsig)
126 if(nsig == SIGTRAP) {
136 if (pcmk__log_id == 0) {
142 g_log_remove_handler(
"GLib", pcmk__glib_log_id);
143 pcmk__glib_log_id = 0;
144 g_log_remove_handler(
"GLib-GIO", pcmk__gio_log_id);
145 pcmk__gio_log_id = 0;
146 g_log_remove_handler(
"GModule", pcmk__gmodule_log_id);
147 pcmk__gmodule_log_id = 0;
148 g_log_remove_handler(
"GThread", pcmk__gthread_log_id);
149 pcmk__gthread_log_id = 0;
167set_format_string(
int method,
const char *daemon, pid_t use_pid,
168 const char *use_nodename)
170 if (method == QB_LOG_SYSLOG) {
172 qb_log_ctl(method, QB_LOG_CONF_EXTENDED, QB_FALSE);
173 qb_log_format_set(method,
"%g %p: %b");
181 if (method > QB_LOG_STDERR) {
183 offset += snprintf(fmt + offset,
FMT_MAX - offset,
185 use_nodename, daemon, (
unsigned long) use_pid);
189 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"(%%n");
190 if (crm_tracing_enabled()) {
192 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"@%%f:%%l");
194 offset += snprintf(fmt + offset,
FMT_MAX - offset,
")");
197 offset += snprintf(fmt + offset,
FMT_MAX - offset,
" %%g\t%%p: %%b");
200 qb_log_format_set(method, fmt);
204#define DEFAULT_LOG_FILE CRM_LOG_DIR "/pacemaker.log"
207logfile_disabled(
const char *filename)
223chown_logfile(
const char *filename,
int logfd)
231 if (fstat(logfd, &
st) < 0) {
240 crm_warn(
"Not changing '%s' ownership because user information "
244 if ((
st.st_gid == pcmk_gid)
245 && ((
st.st_mode & S_IRWXG) == (S_IRGRP|S_IWGRP))) {
248 if (fchown(logfd, pcmk_uid, pcmk_gid) < 0) {
249 crm_warn(
"Couldn't change '%s' ownership to user %s gid %d: %s",
257chmod_logfile(
const char *filename,
int logfd)
260 mode_t filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
262 if (modestr != NULL) {
263 long filemode_l = strtol(modestr, NULL, 8);
265 if ((filemode_l != LONG_MIN) && (filemode_l != LONG_MAX)) {
266 filemode = (mode_t) filemode_l;
269 if ((filemode != 0) && (fchmod(logfd, filemode) < 0)) {
270 crm_warn(
"Couldn't change '%s' mode to %04o: %s",
271 filename, filemode, strerror(errno));
277set_logfile_permissions(
const char *filename, FILE *logfile)
279 if (geteuid() == 0) {
280 int logfd = fileno(logfile);
281 int rc = chown_logfile(filename, logfd);
286 chmod_logfile(filename, logfd);
293enable_logfile(
int fd)
295 qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
297 qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1);
300#ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN
302 qb_log_ctl(fd, QB_LOG_CONF_MAX_LINE_LEN, 800);
309disable_logfile(
int fd)
311 qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_FALSE);
315setenv_logfile(
const char *filename)
340 FILE *logfile = NULL;
341 bool is_default =
false;
343 static int default_fd = -1;
344 static bool have_logfile =
false;
347 if (filename == NULL) {
355 if (logfile_disabled(filename)) {
361 if (is_default && (default_fd >= 0)) {
366 logfile = fopen(filename,
"a");
367 if (logfile == NULL) {
369 crm_warn(
"Logging to '%s' is disabled: %s " QB_XS
" uid=%u gid=%u",
370 filename, strerror(rc), geteuid(), getegid());
374 rc = set_logfile_permissions(filename, logfile);
376 crm_warn(
"Logging to '%s' is disabled: %s " QB_XS
" permissions",
377 filename, strerror(rc));
384 fd = qb_log_file_open(filename);
386 crm_warn(
"Logging to '%s' is disabled: %s " QB_XS
" qb_log_file_open",
387 filename, strerror(-fd));
393 setenv_logfile(filename);
395 }
else if (default_fd >= 0) {
396 crm_notice(
"Switching logging to %s", filename);
397 disable_logfile(default_fd);
400 crm_notice(
"Additional logging available in %s", filename);
417 if (log_files == NULL) {
421 for (gchar **fname = log_files; *fname != NULL; fname++) {
425 out->
err(out,
"Logging to %s is disabled: %s",
431static int blackbox_trigger = 0;
432static volatile char *blackbox_file_prefix = NULL;
435blackbox_logger(int32_t t,
struct qb_log_callsite *cs,
log_time_t timestamp,
438 if(cs && cs->priority < LOG_ERR) {
446crm_control_blackbox(
int nsig,
bool enable)
450 if (blackbox_file_prefix == NULL) {
451 pid_t
pid = getpid();
456 (
unsigned long)
pid);
459 if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
460 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024);
461 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
464 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
465 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
468 crm_notice(
"Initiated blackbox recorder: %s", blackbox_file_prefix);
479 blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
480 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
481 crm_trace(
"Trigger: %d is %d %d", blackbox_trigger,
482 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
486 }
else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
487 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
490 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
491 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_FALSE);
499 crm_control_blackbox(nsig, TRUE);
505 crm_control_blackbox(nsig, FALSE);
521 static volatile int counter = 1;
522 static volatile time_t last = 0;
525 time_t now = time(NULL);
527 if (blackbox_file_prefix == NULL) {
536 if (nsig == 0 && now == last) {
541 snprintf(buffer,
NAME_MAX,
"%s.%d", blackbox_file_prefix, counter++);
542 if (nsig == SIGTRAP) {
543 crm_notice(
"Blackbox dump requested, please see %s for contents", buffer);
547 "Problem detected at %s:%d (%s), please see %s for additional details",
548 cs->function, cs->lineno, cs->filename, buffer);
550 crm_notice(
"Problem detected, please see %s for additional details", buffer);
554 qb_log_blackbox_write_to_file(buffer);
559 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
560 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
568 qb_log_blackbox_write_to_file((
const char *)blackbox_file_prefix);
569 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
576crm_quark_to_string(uint32_t tag)
578 const char *text = g_quark_to_string(tag);
587crm_log_filter_source(
int source,
const char *trace_files,
const char *trace_fns,
588 const char *trace_fmts,
const char *trace_tags,
const char *trace_blackbox,
589 struct qb_log_callsite *cs)
591 if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
595 qb_bit_set(cs->targets, source);
597 }
else if (source == blackbox_trigger && blackbox_trigger > 0) {
599 if (cs->priority <= LOG_ERR) {
600 qb_bit_set(cs->targets, source);
602 }
else if (trace_blackbox) {
605 if (strstr(trace_blackbox, key) != NULL) {
606 qb_bit_set(cs->targets, source);
611 }
else if (source == QB_LOG_SYSLOG) {
612 if (cs->priority <= crm_log_priority && cs->priority <=
crm_log_level) {
613 qb_bit_set(cs->targets, source);
617 qb_bit_set(cs->targets, source);
618 }
else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
619 qb_bit_set(cs->targets, source);
620 }
else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
621 qb_bit_set(cs->targets, source);
622 }
else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
623 qb_bit_set(cs->targets, source);
624 }
else if (trace_tags
627 qb_bit_set(cs->targets, source);
631#ifndef HAVE_STRCHRNUL
636strchrnul(
const char *s,
int c)
638 while ((*s != c) && (*s !=
'\0')) {
646crm_log_filter(
struct qb_log_callsite *cs)
649 static int need_init = 1;
650 static const char *trace_fns = NULL;
651 static const char *trace_tags = NULL;
652 static const char *trace_fmts = NULL;
653 static const char *trace_files = NULL;
654 static const char *trace_blackbox = NULL;
664 if (trace_tags != NULL) {
667 const char *offset = NULL;
668 const char *next = trace_tags;
672 next = strchrnul(offset,
',');
673 snprintf(token,
sizeof(token),
"%.*s", (
int)(next - offset), offset);
675 tag = g_quark_from_string(token);
676 crm_info(
"Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
682 }
while (next != NULL && next[0] != 0);
687 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
688 crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
696 gboolean refilter = FALSE;
702 if (cs->priority != level) {
703 cs->priority = level;
707 if (cs->tags != tags) {
716 if (cs->targets == 0) {
725 static gboolean log = TRUE;
730 (
"Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
736 qb_log_filter_fn_set(crm_log_filter);
740crm_tracing_enabled(
void)
750crm_priority2int(
const char *
name)
752 struct syslog_names {
756 static struct syslog_names p_names[] = {
757 {
"emerg", LOG_EMERG},
758 {
"alert", LOG_ALERT},
761 {
"warning", LOG_WARNING},
762 {
"notice", LOG_NOTICE},
764 {
"debug", LOG_DEBUG},
769 for (lpc = 0;
name != NULL && p_names[lpc].name != NULL; lpc++) {
771 return p_names[lpc].priority;
774 return crm_log_priority;
795set_identity(
const char *entity,
int argc,
char *
const *argv)
801 if (entity != NULL) {
804 }
else if ((argc > 0) && (argv != NULL)) {
805 char *
mutable = strdup(argv[0]);
806 char *modified = basename(
mutable);
808 if (strstr(modified,
"lt-") == modified) {
829 int32_t qb_facility = 0;
830 pid_t
pid = getpid();
831 const char *nodename =
"localhost";
832 static bool have_logging =
false;
833 GLogLevelFlags log_levels;
848 crm_trace_nonlog = g_quark_from_static_string(
"Pacemaker non-logging tracepoint");
851 umask(S_IWGRP | S_IWOTH | S_IROTH);
854 log_levels = G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION;
855 pcmk__log_id = g_log_set_handler(
G_LOG_DOMAIN, log_levels, crm_glib_handler, NULL);
857 pcmk__glib_log_id = g_log_set_handler(
"GLib", log_levels, crm_glib_handler, NULL);
858 pcmk__gio_log_id = g_log_set_handler(
"GLib-GIO", log_levels, crm_glib_handler, NULL);
859 pcmk__gmodule_log_id = g_log_set_handler(
"GModule", log_levels, crm_glib_handler, NULL);
860 pcmk__gthread_log_id = g_log_set_handler(
"GThread", log_levels, crm_glib_handler, NULL);
872 set_identity(entity, argc, argv);
874 qb_facility = qb_log_facility2int(
"local0");
879 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
880#ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN
882 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_MAX_LINE_LEN, 256);
884 if (
uname(memset(&res, 0,
sizeof(res))) == 0 && *res.nodename !=
'\0') {
885 nodename = res.nodename;
891 qb_log_tags_stringify_fn_set(crm_quark_to_string);
892 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
893 qb_log_ctl(lpc, QB_LOG_CONF_THREADED, QB_FALSE);
894#ifdef HAVE_qb_log_conf_QB_LOG_CONF_ELLIPSIS
896 qb_log_ctl(lpc, QB_LOG_CONF_ELLIPSIS, QB_TRUE);
909 setlocale(LC_ALL,
"");
923crm_log_init(
const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr,
924 int argc,
char **argv, gboolean quiet)
926 const char *syslog_priority = NULL;
928 const char *f_copy = facility;
941 if (facility == NULL) {
955 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(facility));
965 if (syslog_priority) {
966 crm_log_priority = crm_priority2int(syslog_priority);
968 qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
"*",
973 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
1000 crm_trace(
"Quiet: %d, facility %s", quiet, f_copy);
1010 const char *user = getenv(
"USER");
1013 crm_trace(
"Not switching to corefile directory for %s", user);
1019 int user = getuid();
1020 struct passwd *pwent = getpwuid(user);
1022 if (pwent == NULL) {
1023 crm_perror(LOG_ERR,
"Cannot get name for uid: %d", user);
1026 crm_trace(
"Don't change active directory for regular user: %s", pwent->pw_name);
1048 }
else if (!quiet) {
1073 if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
1074 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
1077 }
else if (enable == FALSE) {
1078 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
1094 if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0)
1095 != QB_LOG_STATE_ENABLED) {
1120 static bool logged =
false;
1121 gchar *arg_string = NULL;
1123 if ((argc == 0) || (argv == NULL) || logged) {
1127 arg_string = g_strjoinv(
" ", argv);
1136 const char *next = NULL;
1137 const char *offset = NULL;
1143 if (output == NULL) {
1147 output =
"-- empty --";
1153 next = strchrnul(offset,
'\n');
1155 (
int)(next - offset), offset);
1160 }
while (next != NULL && next[0] != 0);
1168 for (
int i = 0; i < verbosity; i++) {
1191 uint32_t tags, uint8_t level,
const char *text,
const xmlNode *xml)
1194 do_crm_log(level,
"%s%sNo data to dump as XML",
1195 pcmk__s(text,
""), pcmk__str_empty(text)?
"" :
" ");
1198 if (logger_out == NULL) {
1228 uint32_t tags, uint8_t level,
const xmlNode *xml)
1235 if (logger_out == NULL) {
1259 uint32_t tags, uint8_t level,
const xmlNode *patchset)
1261 if (patchset == NULL) {
1266 if (logger_out == NULL) {
1271 logger_out->
message(logger_out,
"xml-patchset", patchset);
1282 if (logger_out != NULL) {
int pcmk_daemon_user(uid_t *uid, gid_t *gid)
Get user and group IDs of pacemaker daemon user.
#define bind_textdomain_codeset(Domainname, Codeset)
#define textdomain(Domainname)
#define bindtextdomain(Domainname, Dirname)
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
unsigned int get_crm_log_level(void)
int pcmk__add_logfile(const char *filename)
Add a file to be used as a Pacemaker detail log.
void pcmk__free_common_logger(void)
pcmk__config_warning_func pcmk__config_warning_handler
void crm_log_deinit(void)
gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr, int argc, char **argv, gboolean quiet)
void pcmk__log_xml_patchset_as(const char *file, const char *function, uint32_t line, uint32_t tags, uint8_t level, const xmlNode *patchset)
void crm_disable_blackbox(int nsig)
void crm_update_callsites(void)
void * pcmk__config_warning_context
void pcmk__add_logfiles(gchar **log_files, pcmk__output_t *out)
Add multiple additional log files.
void pcmk_log_xml_as(const char *file, const char *function, uint32_t line, uint32_t tags, uint8_t level, const char *text, const xmlNode *xml)
Log XML line-by-line in a formatted fashion.
void crm_enable_stderr(int enable)
void pcmk__set_config_error_handler(pcmk__config_error_func error_handler, void *error_context)
void pcmk__set_config_warning_handler(pcmk__config_warning_func warning_handler, void *warning_context)
void * pcmk__config_error_context
void crm_enable_blackbox(int nsig)
unsigned int crm_trace_nonlog
void pcmk__log_xml_changes_as(const char *file, const char *function, uint32_t line, uint32_t tags, uint8_t level, const xmlNode *xml)
void crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix, const char *output)
void pcmk__cli_init_logging(const char *name, unsigned int verbosity)
unsigned int set_crm_log_level(unsigned int level)
#define TIMESTAMP_FORMAT_SPEC
void crm_log_args(int argc, char **argv)
Log the command line (once)
void crm_bump_log_level(int argc, char **argv)
Make logging more verbose.
void crm_write_blackbox(int nsig, const struct qb_log_callsite *cs)
unsigned int crm_log_level
void crm_log_preinit(const char *entity, int argc, char *const *argv)
Initializes the logging system and defaults to the least verbose output level.
#define crm_info(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
#define crm_warn(fmt, args...)
#define CRM_LOG_ASSERT(expr)
#define crm_notice(fmt, args...)
#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_debug(fmt, args...)
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
#define crm_trace(fmt, args...)
void(* pcmk__config_error_func)(void *ctx, const char *msg,...) G_GNUC_PRINTF(2
void typedef void pcmk__config_error_func pcmk__config_error_handler
void typedef void(* pcmk__config_warning_func)(void *ctx, const char *msg,...) G_GNUC_PRINTF(2
Wrappers for and extensions to glib mainloop.
gboolean mainloop_add_signal(int sig, void(*dispatch)(int sig))
sighandler_t crm_signal_handler(int sig, sighandler_t dispatch)
#define PCMK__ENV_TRACE_BLACKBOX
#define PCMK__ENV_SERVICE
void pcmk__set_env_option(const char *option, const char *value, bool compat)
Set or unset a Pacemaker environment variable option.
#define PCMK__ENV_LOGPRIORITY
bool pcmk__env_option_enabled(const char *daemon, const char *option)
#define PCMK__ENV_LOGFILE
#define PCMK__ENV_LOGFACILITY
#define PCMK__ENV_TRACE_TAGS
const char * pcmk__env_option(const char *option)
#define PCMK__ENV_TRACE_FORMATS
#define PCMK__ENV_TRACE_FILES
#define PCMK__ENV_LOGFILE_MODE
#define PCMK__ENV_BLACKBOX
#define PCMK__ENV_TRACE_FUNCTIONS
void pcmk__output_set_log_level(pcmk__output_t *out, uint8_t log_level)
void pcmk__output_free(pcmk__output_t *out)
int pcmk__log_output_new(pcmk__output_t **out)
void pcmk__output_set_log_filter(pcmk__output_t *out, const char *file, const char *function, uint32_t line, uint32_t tags)
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
int pcmk_legacy2rc(int legacy_rc)
#define pcmk__assert(expr)
void pcmk__schema_init(void)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
#define pcmk__str_copy(str)
This structure contains everything that makes up a single output formatter.
int(* message)(pcmk__output_t *out, const char *message_id,...)
int int void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest)
@ pcmk__xml_fmt_close
Include the closing tag of an XML element.
@ pcmk__xml_fmt_children
Include the children of an XML element.
@ pcmk__xml_fmt_open
Include the opening tag of an XML element, and include XML comments.
@ pcmk__xml_fmt_pretty
Include indentation and newlines.
int pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml)
int pcmk__xml_show(pcmk__output_t *out, const char *prefix, const xmlNode *data, int depth, uint32_t options)