[PATCH 1/2] lib: add xml logging

Colin King colin.king at canonical.com
Mon May 28 15:01:23 UTC 2012


From: Colin Ian King <colin.king at canonical.com>

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 doc/fwts.1                   |    2 +-
 src/lib/include/fwts_log.h   |    1 +
 src/lib/src/Makefile.am      |    1 +
 src/lib/src/fwts_framework.c |    4 +-
 src/lib/src/fwts_log.c       |    3 +
 src/lib/src/fwts_log_xml.c   |  186 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 195 insertions(+), 2 deletions(-)
 create mode 100644 src/lib/src/fwts_log_xml.c

diff --git a/doc/fwts.1 b/doc/fwts.1
index 0d773cd..09eee56 100644
--- a/doc/fwts.1
+++ b/doc/fwts.1
@@ -150,7 +150,7 @@ specify the information in each log line. The following specifiers are available
 e.g. \-\-log\-format="%date %time [%field] (%owner): "
 .TP
 .B \-\-log\-type
-specify the log type. Currently plaintext and json log types are available and the
+specify the log type. Currently plaintext, json and xml log types are available and the
 default is plaintext.
 .TP
 .B \-\-lp\-tags
diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h
index 8903bab..8027d41 100644
--- a/src/lib/include/fwts_log.h
+++ b/src/lib/include/fwts_log.h
@@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t {
 
 fwts_log_ops fwts_log_plaintext_ops;
 fwts_log_ops fwts_log_json_ops;
+fwts_log_ops fwts_log_xml_ops;
 
 extern fwts_log_field fwts_log_filter;
 extern const char *fwts_log_format;
diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am
index cae1f91..acea9cb 100644
--- a/src/lib/src/Makefile.am
+++ b/src/lib/src/Makefile.am
@@ -39,6 +39,7 @@ libfwts_la_SOURCES = \
 	fwts_log.c \
 	fwts_log_plaintext.c \
 	fwts_log_json.c \
+	fwts_log_xml.c \
 	fwts_memorymap.c \
 	fwts_microcode.c \
 	fwts_mmap.c \
diff --git a/src/lib/src/fwts_framework.c b/src/lib/src/fwts_framework.c
index 1fcd88e..2b42982 100644
--- a/src/lib/src/fwts_framework.c
+++ b/src/lib/src/fwts_framework.c
@@ -76,7 +76,7 @@ static fwts_option fwts_framework_options[] = {
 	{ "json-data-path", 	"j:", 1, "Specify path to fwts json data files - default is /usr/share/fwts." },
 	{ "lp-tags-log", 	"",   0, "Output LaunchPad bug tags in results log." },
 	{ "disassemble-aml", 	"",   0, "Disassemble AML from DSDT and SSDT tables." },
-	{ "log-type",		"",   1, "Specify log type (plaintext or json)." },
+	{ "log-type",		"",   1, "Specify log type (plaintext, json or xml)." },
 	{ NULL, NULL, 0, NULL }
 };
 
@@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar
 				fw->log_type = LOG_TYPE_PLAINTEXT;
 			else if (!strcmp(optarg, "json"))
 				fw->log_type = LOG_TYPE_JSON;
+			else if (!strcmp(optarg, "xml"))
+				fw->log_type = LOG_TYPE_XML;
 			else {
 				fprintf(stderr, "--log-type can be either plaintext or json.\n");
 				return FWTS_ERROR;
diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c
index 5331fff..2b11441 100644
--- a/src/lib/src/fwts_log.c
+++ b/src/lib/src/fwts_log.c
@@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char *name, const char *mode, f
 	case LOG_TYPE_PLAINTEXT:
 		newlog->ops = &fwts_log_plaintext_ops;
 		break;
+	case LOG_TYPE_XML:
+		newlog->ops = &fwts_log_xml_ops;
+		break;
 	case LOG_TYPE_NONE:
 	default:
 		newlog->ops = &fwts_log_plaintext_ops;
diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c
new file mode 100644
index 0000000..57b530b
--- /dev/null
+++ b/src/lib/src/fwts_log_xml.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2010-2012 Canonical
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <time.h>
+
+#include "fwts.h"
+
+#define MAX_XML_STACK	(64)
+#define XML_INDENT	(4)
+
+typedef struct {
+	const char *name;
+} fwts_log_xml_stack_t;
+
+static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK];
+static int xml_stack_index = 0;
+
+/*
+ *  fwts_log_vprintf_xml()
+ *	vprintf to a log
+ */
+static int fwts_log_vprintf_xml(fwts_log *log,
+	const fwts_log_field field,
+	const fwts_log_level level,
+	const char *status,
+	const char *label,
+	const char *prefix,
+	const char *fmt,
+	va_list args)
+{
+	char buffer[4096];
+	struct tm tm;
+	time_t now;
+	char *str;
+
+	if (!((field & LOG_FIELD_MASK) & fwts_log_filter))
+		return 0;
+
+	if (field & (LOG_NEWLINE | LOG_SEPARATOR | LOG_DEBUG))
+		return 0;
+
+	time(&now);
+	localtime_r(&now, &tm);
+
+	fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT, "");
+
+	fprintf(log->fp, "%*s<line_num>%d</line_num>\n",
+		(xml_stack_index + 1) * XML_INDENT,
+		"", log->line_number);
+
+	fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n",
+		(xml_stack_index + 1) * XML_INDENT,
+		"", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100);
+
+	fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n",
+		(xml_stack_index + 1) * XML_INDENT,
+		"", tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+	fprintf(log->fp, "%*s<field_type>%s</field_type>\n",
+		(xml_stack_index + 1) * XML_INDENT,
+		"", fwts_log_field_to_str_full(field));
+
+	str = fwts_log_level_to_str(level);
+	if (!strcmp(str, " "))
+		str = "None";
+
+	fprintf(log->fp, "%*s<level>%s</level>\n",
+		(xml_stack_index + 1) * XML_INDENT, "", str);
+
+	fprintf(log->fp, "%*s<status>%s</status>\n",
+		(xml_stack_index + 1) * XML_INDENT,
+		"", *status ? status : "None");
+
+	fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n",
+		(xml_stack_index + 1) * XML_INDENT,
+		"", label && *label ? label : "None");
+
+	vsnprintf(buffer, sizeof(buffer), fmt, args);
+	fprintf(log->fp, "%*s<log_text>%s</log_text>\n",
+		(xml_stack_index + 1) * XML_INDENT,
+		"", buffer);
+
+	fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT, "");
+	fflush(log->fp);
+
+	log->line_number++;
+
+	return 0;
+}
+
+/*
+ *  fwts_log_underline_xml()
+ *	write an underline across log, using character ch as the underline
+ */
+static void fwts_log_underline_xml(fwts_log *log, const int ch)
+{
+	/* No-op for xml */
+}
+
+/*
+ *  fwts_log_newline()
+ *	write newline to log
+ */
+static void fwts_log_newline_xml(fwts_log *log)
+{
+	/* No-op for xml */
+}
+
+static void fwts_log_section_begin_xml(fwts_log *log, const char *name)
+{
+	xml_stack[xml_stack_index].name = name;
+
+	fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "", name);
+	fflush(log->fp);
+
+	if (xml_stack_index < MAX_XML_STACK)
+		xml_stack_index++;
+	else  {
+		fprintf(stderr, "xml log stack overflow pushing section %s.\n", name);
+		exit(EXIT_FAILURE);
+	}
+}
+
+static void fwts_log_section_end_xml(fwts_log *log)
+{
+	if (xml_stack_index > 0) {
+		xml_stack_index--;
+		fprintf(log->fp, "%*s</%s>\n", xml_stack_index * XML_INDENT,
+			"", xml_stack[xml_stack_index].name);
+		fflush(log->fp);
+	} else {
+		fprintf(stderr, "xml log stack underflow.\n");
+		exit(EXIT_FAILURE);
+	}
+
+}
+
+static void fwts_log_open_xml(fwts_log *log)
+{
+	char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+
+	fwrite(xml_header, 1, strlen(xml_header), log->fp);
+	fflush(log->fp);
+
+	fwts_log_section_begin_xml(log, "fwts");
+}
+
+static void fwts_log_close_xml(fwts_log *log)
+{
+	fwts_log_section_end_xml(log);
+
+	fwrite("\n", 1, 1, log->fp);
+	fflush(log->fp);
+}
+
+fwts_log_ops fwts_log_xml_ops = {
+	.vprintf = 	 fwts_log_vprintf_xml,
+	.underline =	 fwts_log_underline_xml,
+	.newline =	 fwts_log_newline_xml,
+	.section_begin = fwts_log_section_begin_xml,
+	.section_end   = fwts_log_section_end_xml,
+	.open          = fwts_log_open_xml,
+	.close	       = fwts_log_close_xml
+};
-- 
1.7.10





More information about the fwts-devel mailing list