summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--src/dmidecode.c49
-rw-r--r--src/dmidecode.h5
-rw-r--r--src/dmidecodemodule.c110
-rw-r--r--src/dmidecodemodule.h8
-rw-r--r--src/dmidump.c8
-rw-r--r--src/dmihelper.h2
-rw-r--r--src/dmilog.c222
-rw-r--r--src/dmilog.h63
-rw-r--r--src/dmixml.c9
-rw-r--r--src/dmixml.h2
-rw-r--r--src/efi.c9
-rw-r--r--src/efi.h2
-rw-r--r--src/setup-dbg.py1
-rw-r--r--src/setup.py1
-rw-r--r--src/util.c22
-rw-r--r--src/util.h3
-rw-r--r--src/xmlpythonizer.c108
-rw-r--r--src/xmlpythonizer.h8
19 files changed, 501 insertions, 135 deletions
diff --git a/Makefile b/Makefile
index fce6c72..1d82922 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ $(PY)-dmidecodemod.so: $(SO)
$(SO):
$(PY) src/setup.py build
-dmidump : src/util.o src/efi.o
+dmidump : src/util.o src/efi.o src/dmilog.o
$(CC) -o $@ src/dmidump.c $^ -g -Wall -D_DMIDUMP_MAIN_
install:
@@ -35,7 +35,7 @@ uninstall:
clean:
-$(PY) src/setup.py clean --all
- -rm -f *.so lib/*.o core dmidump
+ -rm -f *.so lib/*.o core dmidump src/*.o
-rm -rf build
-rm -rf rpm
-rm -rf src/setup_common.py[oc]
diff --git a/src/dmidecode.c b/src/dmidecode.c
index 704294b..02dd9b0 100644
--- a/src/dmidecode.c
+++ b/src/dmidecode.c
@@ -4842,7 +4842,7 @@ dmi_codes_major *find_dmiMajor(const struct dmi_header *h)
return NULL;
}
-static void dmi_table(int type, u32 base, u16 len, u16 num, u16 ver, const char *devmem, xmlNode *xmlnode)
+static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver, const char *devmem, xmlNode *xmlnode)
{
u8 *buf;
u8 *data;
@@ -4865,12 +4865,12 @@ static void dmi_table(int type, u32 base, u16 len, u16 num, u16 ver, const char
info_n = NULL;
}
- if((buf = mem_chunk(base, len, devmem)) == NULL) {
- fprintf(stderr, "Table is unreachable, sorry."
+ if((buf = mem_chunk(logp, base, len, devmem)) == NULL) {
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING, "Table is unreachable, sorry."
#ifndef USE_MMAP
- "Try compiling dmidecode with -DUSE_MMAP.";
+ "Try compiling dmidecode with -DUSE_MMAP."
#endif
- "\n");
+ );
return;
}
@@ -4889,8 +4889,9 @@ static void dmi_table(int type, u32 base, u16 len, u16 num, u16 ver, const char
** table is broken.
*/
if(h.length < 4) {
- fprintf(stderr, "Invalid entry length (%i). DMI table is broken! Stop.",
- (unsigned int)h.length);
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING,
+ "Invalid entry length (%i). DMI table is broken! Stop.",
+ (unsigned int)h.length);
break;
}
@@ -4933,9 +4934,17 @@ static void dmi_table(int type, u32 base, u16 len, u16 num, u16 ver, const char
} else {
handle_n = xmlNewChild(xmlnode, NULL, (xmlChar *) "DMIerror", NULL);
assert( handle_n != NULL );
- dmixml_AddTextContent(handle_n, "Data is truncated");
+ dmixml_AddTextContent(handle_n, "Data is truncated %i bytes on type 0x%02X",
+ (next - buf - len), h.type);
dmixml_AddAttribute(handle_n, "type", "%i", h.type);
dmixml_AddAttribute(handle_n, "truncated", "1");
+ dmixml_AddAttribute(handle_n, "length", "%i", (next - buf));
+ dmixml_AddAttribute(handle_n, "expected_length", "%i", len);
+
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING,
+ "DMI/SMBIOS type 0x%02X is exceeding the expected buffer "
+ "size by %i bytes. Will not decode this entry.",
+ h.type, (next - buf - len));
}
dmixml_AddAttribute(handle_n, "handle", "0x%04x", h.handle);
dmixml_AddAttribute(handle_n, "size", "%d", h.length);
@@ -4954,14 +4963,16 @@ static void dmi_table(int type, u32 base, u16 len, u16 num, u16 ver, const char
dmixml_AddAttribute(handle_n, "notfound", "1");
}
- if(i != num)
- fprintf(stderr, "Wrong DMI structures count: %d announced, only %d decoded.\n", num,
- i);
- if(data - buf != len)
- fprintf(stderr,
- "Wrong DMI structures length: %d bytes announced, structures occupy %d bytes.\n",
- len, (unsigned int)(data - buf));
+ if(i != num) {
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING,
+ "Wrong DMI structures count: %d announced, only %d decoded.", num, i);
+ }
+ if(data - buf != len) {
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING,
+ "Wrong DMI structures length: %d bytes announced, structures occupy %d bytes.",
+ len, (unsigned int)(data - buf));
+ }
free(buf);
}
@@ -5017,7 +5028,7 @@ xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem)
return data_n;
}
-int smbios_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
+int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
{
int check = _smbios_decode_check(buf);
@@ -5033,7 +5044,7 @@ int smbios_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
break;
}
//printf(">>%d @ %d, %d<<\n", DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C));
- dmi_table(type, DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C), ver, devmem,
+ dmi_table(logp, type, DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C), ver, devmem,
xmlnode);
}
return check;
@@ -5072,12 +5083,12 @@ xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem)
return data_n;
}
-int legacy_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
+int legacy_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode)
{
int check = _legacy_decode_check(buf);
if(check == 1)
- dmi_table(type, DWORD(buf + 0x08), WORD(buf + 0x06), WORD(buf + 0x0C),
+ dmi_table(logp, type, DWORD(buf + 0x08), WORD(buf + 0x06), WORD(buf + 0x0C),
((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F), devmem, xmlnode);
return check;
}
diff --git a/src/dmidecode.h b/src/dmidecode.h
index 10412c6..926bd5d 100644
--- a/src/dmidecode.h
+++ b/src/dmidecode.h
@@ -21,6 +21,7 @@
#include <libxml/tree.h>
#include "dmihelper.h"
+#include "dmierror.h"
struct dmi_header {
u8 type;
@@ -35,8 +36,8 @@ void to_dmi_header(struct dmi_header *h, u8 * data);
xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem);
xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem);
-int smbios_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
-int legacy_decode(int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
+int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
+int legacy_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *xmlnode);
const char *dmi_string(const struct dmi_header *dm, u8 s);
void dmi_system_uuid(xmlNode *node, const u8 * p, u16 ver);
diff --git a/src/dmidecodemodule.c b/src/dmidecodemodule.c
index 003051b..1056a8f 100644
--- a/src/dmidecodemodule.c
+++ b/src/dmidecodemodule.c
@@ -44,20 +44,17 @@
#include <libxml/tree.h>
#include "libxml_wrap.h"
-#include "xmlpythonizer.h"
#include "dmidecodemodule.h"
#include "dmixml.h"
#include "dmierror.h"
+#include "dmilog.h"
+#include "xmlpythonizer.h"
#include "version.h"
#include "dmidump.h"
#include <mcheck.h>
static void init(options *opt)
{
- /* sanity check */
- if(sizeof(u8) != 1 || sizeof(u16) != 2 || sizeof(u32) != 4 || '\0' != 0)
- fprintf(stderr, "%s: compiler incompatibility\n", "dmidecodemodule");
-
opt->devmem = DEFAULT_MEM_DEV;
opt->dumpfile = NULL;
opt->flags = 0;
@@ -65,9 +62,16 @@ static void init(options *opt)
opt->dmiversion_n = NULL;
opt->mappingxml = NULL;
opt->python_xml_map = strdup(PYTHON_XML_MAP);
+ opt->logdata = log_init();
+
+ /* sanity check */
+ if(sizeof(u8) != 1 || sizeof(u16) != 2 || sizeof(u32) != 4 || '\0' != 0) {
+ log_append(opt->logdata, LOGFL_NORMAL, LOG_WARNING,
+ "%s: compiler incompatibility", "dmidecodemodule");
+ }
}
-int parse_opt_type(const char *arg)
+int parse_opt_type(Log_t *logp, const char *arg)
{
while(*arg != '\0') {
int val;
@@ -75,11 +79,11 @@ int parse_opt_type(const char *arg)
val = strtoul(arg, &next, 0);
if(next == arg) {
- fprintf(stderr, "Invalid type keyword: %s\n", arg);
+ log_append(logp, LOGFL_NODUPS, LOG_ERR, "Invalid type keyword: %s", arg);
return -1;
}
if(val > 0xff) {
- fprintf(stderr, "Invalid type number: %i\n", val);
+ log_append(logp, LOGFL_NODUPS, LOG_ERR, "Invalid type number: %i", val);
return -1;
}
@@ -110,7 +114,7 @@ xmlNode *dmidecode_get_version(options *opt)
/* Read from dump if so instructed */
if(opt->dumpfile != NULL) {
//. printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
- if((buf = mem_chunk(0, 0x20, opt->dumpfile)) != NULL) {
+ if((buf = mem_chunk(opt->logdata, 0, 0x20, opt->dumpfile)) != NULL) {
if(memcmp(buf, "_SM_", 4) == 0) {
ver_n = smbios_decode_get_version(buf, opt->dumpfile);
if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
@@ -125,10 +129,10 @@ xmlNode *dmidecode_get_version(options *opt)
}
} else { /* Read from /dev/mem */
/* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
+ efi = address_from_efi(opt->logdata, &fp);
if(efi == EFI_NOT_FOUND) {
/* Fallback to memory scan (x86, x86_64) */
- if((buf = mem_chunk(0xF0000, 0x10000, opt->devmem)) != NULL) {
+ if((buf = mem_chunk(opt->logdata, 0xF0000, 0x10000, opt->devmem)) != NULL) {
for(fp = 0; fp <= 0xFFF0; fp += 16) {
if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) {
ver_n = smbios_decode_get_version(buf + fp, opt->devmem);
@@ -148,7 +152,7 @@ xmlNode *dmidecode_get_version(options *opt)
ver_n = NULL;
} else {
// Process as EFI
- if((buf = mem_chunk(fp, 0x20, opt->devmem)) != NULL) {
+ if((buf = mem_chunk(opt->logdata, fp, 0x20, opt->devmem)) != NULL) {
ver_n = smbios_decode_get_version(buf, opt->devmem);
if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
found++;
@@ -161,7 +165,8 @@ xmlNode *dmidecode_get_version(options *opt)
free(buf);
}
if( !found ) {
- fprintf(stderr, "No SMBIOS nor DMI entry point found, sorry.");
+ log_append(opt->logdata, LOGFL_NODUPS, LOG_WARNING,
+ "No SMBIOS nor DMI entry point found, sorry.");
}
return ver_n;
}
@@ -182,19 +187,20 @@ int dmidecode_get_xml(options *opt, xmlNode* dmixml_n)
const char *f = opt->dumpfile ? opt->dumpfile : opt->devmem;
if(access(f, R_OK) < 0) {
- fprintf(stderr, "Permission denied to memory file/device (%s)", f);
+ log_append(opt->logdata, LOGFL_NORMAL,
+ LOG_WARNING, "Permission denied to memory file/device (%s)", f);
return 0;
}
/* Read from dump if so instructed */
if(opt->dumpfile != NULL) {
// printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
- if((buf = mem_chunk(0, 0x20, opt->dumpfile)) != NULL) {
+ if((buf = mem_chunk(opt->logdata, 0, 0x20, opt->dumpfile)) != NULL) {
if(memcmp(buf, "_SM_", 4) == 0) {
- if(smbios_decode(opt->type, buf, opt->dumpfile, dmixml_n))
+ if(smbios_decode(opt->logdata, opt->type, buf, opt->dumpfile, dmixml_n))
found++;
} else if(memcmp(buf, "_DMI_", 5) == 0) {
- if(legacy_decode(opt->type, buf, opt->dumpfile, dmixml_n))
+ if(legacy_decode(opt->logdata, opt->type, buf, opt->dumpfile, dmixml_n))
found++;
}
} else {
@@ -202,18 +208,20 @@ int dmidecode_get_xml(options *opt, xmlNode* dmixml_n)
}
} else { /* Read from /dev/mem */
/* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
+ efi = address_from_efi(opt->logdata, &fp);
if(efi == EFI_NOT_FOUND) {
/* Fallback to memory scan (x86, x86_64) */
- if((buf = mem_chunk(0xF0000, 0x10000, opt->devmem)) != NULL) {
+ if((buf = mem_chunk(opt->logdata, 0xF0000, 0x10000, opt->devmem)) != NULL) {
for(fp = 0; fp <= 0xFFF0; fp += 16) {
if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) {
- if(smbios_decode(opt->type, buf + fp, opt->devmem, dmixml_n)) {
+ if(smbios_decode(opt->logdata, opt->type,
+ buf + fp, opt->devmem, dmixml_n)) {
found++;
fp += 16;
}
} else if(memcmp(buf + fp, "_DMI_", 5) == 0) {
- if(legacy_decode(opt->type, buf + fp, opt->devmem, dmixml_n))
+ if(legacy_decode(opt->logdata, opt->type,
+ buf + fp, opt->devmem, dmixml_n))
found++;
}
}
@@ -222,9 +230,9 @@ int dmidecode_get_xml(options *opt, xmlNode* dmixml_n)
} else if(efi == EFI_NO_SMBIOS) {
ret = 1;
} else {
- if((buf = mem_chunk(fp, 0x20, opt->devmem)) == NULL)
+ if((buf = mem_chunk(opt->logdata, fp, 0x20, opt->devmem)) == NULL)
ret = 1;
- else if(smbios_decode(opt->type, buf, opt->devmem, dmixml_n))
+ else if(smbios_decode(opt->logdata, opt->type, buf, opt->devmem, dmixml_n))
found++;
// TODO: dmixml_AddAttribute(dmixml_n, "efi_address", "0x%08x", efiAddress);
}
@@ -297,9 +305,11 @@ xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) {
}
// Parse the typeid string to a an integer
- opt->type = parse_opt_type(typeid);
+ opt->type = parse_opt_type(opt->logdata, typeid);
if(opt->type == -1) {
- PyReturnError(PyExc_RuntimeError, "Invalid type id '%s'", typeid);
+ char *err = log_retrieve(opt->logdata, LOG_ERR);
+ log_clear_partial(opt->logdata, LOG_ERR, 0);
+ PyReturnError(PyExc_RuntimeError, "Invalid type id '%s' -- %s", typeid, err);
}
// Parse the DMI data and put the result into dmixml_n node chain.
@@ -336,7 +346,7 @@ static PyObject *dmidecode_get_group(options *opt, const char *section)
}
// Convert the retrieved XML nodes to a Python dictionary
- mapping = dmiMAP_ParseMappingXML_GroupName(opt->mappingxml, section);
+ mapping = dmiMAP_ParseMappingXML_GroupName(opt->logdata, opt->mappingxml, section);
if( mapping == NULL ) {
// Exception already set
xmlFreeNode(dmixml_n);
@@ -344,7 +354,7 @@ static PyObject *dmidecode_get_group(options *opt, const char *section)
}
// Generate Python dict out of XML node
- pydata = pythonizeXMLnode(mapping, dmixml_n);
+ pydata = pythonizeXMLnode(opt->logdata, mapping, dmixml_n);
// Clean up and return the resulting Python dictionary
ptzmap_Free(mapping);
@@ -399,7 +409,7 @@ static PyObject *dmidecode_get_typeid(options *opt, int typeid)
}
// Convert the retrieved XML nodes to a Python dictionary
- mapping = dmiMAP_ParseMappingXML_TypeID(opt->mappingxml, opt->type);
+ mapping = dmiMAP_ParseMappingXML_TypeID(opt->logdata, opt->mappingxml, opt->type);
if( mapping == NULL ) {
// FIXME: Should we raise an exception here?
// Now it passes the unit-test
@@ -407,7 +417,7 @@ static PyObject *dmidecode_get_typeid(options *opt, int typeid)
}
// Generate Python dict out of XML node
- pydata = pythonizeXMLnode(mapping, dmixml_n);
+ pydata = pythonizeXMLnode(opt->logdata, mapping, dmixml_n);
// Clean up and return the resulting Python dictionary
ptzmap_Free(mapping);
@@ -647,6 +657,29 @@ static PyObject *dmidecode_set_pythonxmlmap(PyObject * self, PyObject * arg)
}
+static PyObject * dmidecode_get_warnings(PyObject *self, PyObject *null)
+{
+ char *warn = NULL;
+ PyObject *ret = NULL;
+
+ warn = log_retrieve(global_options->logdata, LOG_WARNING);
+ if( warn ) {
+ ret = PyString_FromString(warn);
+ free(warn);
+ } else {
+ ret = Py_None;
+ }
+ return ret;
+}
+
+
+static PyObject * dmidecode_clear_warnings(PyObject *self, PyObject *null)
+{
+ log_clear_partial(global_options->logdata, LOG_WARNING, 1);
+ Py_RETURN_TRUE;
+}
+
+
static PyMethodDef DMIDataMethods[] = {
{(char *)"dump", dmidecode_dump, METH_NOARGS, (char *)"Dump dmidata to set file"},
{(char *)"get_dev", dmidecode_get_dev, METH_NOARGS,
@@ -681,6 +714,13 @@ static PyMethodDef DMIDataMethods[] = {
{(char *)"xmlapi", dmidecode_xmlapi, METH_KEYWORDS,
(char *) "Internal API for retrieving data as raw XML data"},
+
+ {(char *)"get_warnings", dmidecode_get_warnings, METH_NOARGS,
+ (char *) "Retrieve warnings from operations"},
+
+ {(char *)"clear_warnings", dmidecode_clear_warnings, METH_NOARGS,
+ (char *) "Clear all warnings"},
+
{NULL, NULL, 0, NULL}
};
@@ -708,6 +748,18 @@ void destruct_options(void *ptr)
opt->dumpfile = NULL;
}
+ if( opt->logdata != NULL ) {
+ char *warn = NULL;
+
+ log_clear_partial(opt->logdata, LOG_WARNING, 0);
+ warn = log_retrieve(opt->logdata, LOG_WARNING);
+ if( warn ) {
+ fprintf(stderr, "\n** COLLECTED WARNINGS **\n%s** END OF WARNINGS **\n\n", warn);
+ free(warn);
+ }
+ log_close(opt->logdata);
+ }
+
free(ptr);
}
diff --git a/src/dmidecodemodule.h b/src/dmidecodemodule.h
index c0be3a1..3600ba9 100644
--- a/src/dmidecodemodule.h
+++ b/src/dmidecodemodule.h
@@ -66,12 +66,12 @@
xmlNode *dmidecode_get_version(options *);
extern void dmi_dump(xmlNode *node, struct dmi_header *h);
-extern int address_from_efi(size_t * address);
+extern int address_from_efi(Log_t *logp, size_t * address);
extern void to_dmi_header(struct dmi_header *h, u8 * data);
-extern int smbios_decode(int type, u8 *buf, const char *devmem, xmlNode *node);
-extern int legacy_decode(int type, u8 *buf, const char *devmem, xmlNode *node);
+extern int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *node);
+extern int legacy_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *node);
extern xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem);
extern xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem);
-extern void *mem_chunk(size_t base, size_t len, const char *devmem);
+extern void *mem_chunk(Log_t *logp, size_t base, size_t len, const char *devmem);
PyMODINIT_FUNC initdmidecode(void);
diff --git a/src/dmidump.c b/src/dmidump.c
index 641b937..fc67481 100644
--- a/src/dmidump.c
+++ b/src/dmidump.c
@@ -109,7 +109,7 @@ int dumpling(u8 * buf, const char *dumpfile, u8 mode)
u8 *buff;
- if((buff = mem_chunk(base, len, DEFAULT_MEM_DEV)) != NULL) {
+ if((buff = mem_chunk(NULL, base, len, DEFAULT_MEM_DEV)) != NULL) {
//. Part 1.
#ifdef NDEBUG
printf("# Writing %d bytes to %s.\n", len, dumpfile);
@@ -156,10 +156,10 @@ int dump(const char *memdev, const char *dumpfile)
u8 *buf;
/* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
+ efi = address_from_efi(NULL, &fp);
if(efi == EFI_NOT_FOUND) {
/* Fallback to memory scan (x86, x86_64) */
- if((buf = mem_chunk(0xF0000, 0x10000, memdev)) != NULL) {
+ if((buf = mem_chunk(NULL, 0xF0000, 0x10000, memdev)) != NULL) {
for(fp = 0; fp <= 0xFFF0; fp += 16) {
if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) {
if(dumpling(buf + fp, dumpfile, NON_LEGACY))
@@ -175,7 +175,7 @@ int dump(const char *memdev, const char *dumpfile)
} else if(efi == EFI_NO_SMBIOS) {
ret = -1;
} else {
- if((buf = mem_chunk(fp, 0x20, memdev)) == NULL)
+ if((buf = mem_chunk(NULL, fp, 0x20, memdev)) == NULL)
ret = -1;
else if(dumpling(buf, dumpfile, NON_LEGACY))
found++;
diff --git a/src/dmihelper.h b/src/dmihelper.h
index 55a2843..8d07feb 100644
--- a/src/dmihelper.h
+++ b/src/dmihelper.h
@@ -53,6 +53,7 @@
#include <libxml/tree.h>
#include "types.h"
+#include "dmilog.h"
#define MAXVAL 1024
@@ -120,6 +121,7 @@ typedef struct _options {
char *python_xml_map;
xmlNode *dmiversion_n;
char *dumpfile;
+ Log_t *logdata;
} options;
#endif
diff --git a/src/dmilog.c b/src/dmilog.c
new file mode 100644
index 0000000..f7ade5d
--- /dev/null
+++ b/src/dmilog.c
@@ -0,0 +1,222 @@
+/*
+ * 2009 (C) David Sommerseth <davids@redhat.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+/**
+ * @file dmilog.h
+ * @brief A simple log module
+ * @author David Sommerseth <davids@redhat.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "dmilog.h"
+
+/**
+ * Allocates memory for a new Log_t record
+ *
+ * @return Returns a pointer to a new Log_t record, otherwise NULL on error
+ */
+Log_t * log_init()
+{
+ Log_t *ret = NULL;
+
+ ret = (Log_t *) calloc(1, sizeof(Log_t)+2);
+ if( !ret ) {
+ fprintf(stderr, "** ERROR ** Could not allocate memory for log data\n");
+ }
+ ret->level = -1; // Initialised - chain header pointer always have -1.
+ return ret;
+}
+
+
+
+
+/**
+ * Registers a new log entry
+ *
+ * @param logp Pointer to an allocated Log_t record. New records will be appended to the end
+ * @param flags Log flags, to specify logging behaviour
+ * @param level syslog log level values. LOG_ERR and LOG_WARNING are allowed
+ * @param fmt stdarg based string with the log contents
+ *
+ * @return Returns 1 on successful registration of log entry, otherwise -1 and error is printed to stderr
+ * unless LOGFL_NOSTDERR is set in flags.
+ */
+int log_append(Log_t *logp, Log_f flags, int level, const char *fmt, ...)
+{
+ Log_t *ptr = NULL;
+ va_list ap;
+ char logmsg[4098];
+
+ // Prepare log message
+ memset(&logmsg, 0, 4098);
+ va_start(ap, fmt);
+ vsnprintf(logmsg, 4096, fmt, ap);
+ va_end(ap);
+
+ // Go the end of the record chain
+ ptr = logp;
+ while( ptr && ptr->next ) {
+ // Ignore duplicated messages if LOGFL_NODUPS is set
+ if( (flags & LOGFL_NODUPS) && ptr->next && ptr->next->message
+ && (strcmp(ptr->next->message, logmsg) == 0) ) {
+ return 1;
+ }
+ ptr = ptr->next;
+ }
+
+ if( ptr && ((level == LOG_ERR) || (level == LOG_WARNING)) ) {
+ ptr->next = log_init();
+ if( ptr->next ) {
+ ptr->next->level = level;
+ ptr->next->message = strdup(logmsg);
+ return 1;
+ }
+ }
+
+ if( !(flags & LOGFL_NOSTDERR) ) {
+ if( logp ) {
+ // Only print this if we logp is pointing somewhere.
+ // If it is NULL, the caller did not establish a log
+ // buffer on purpose (like dmidump.c) - thus this is
+ // not an error with saving the log entry.
+ fprintf(stderr, "** ERROR ** Failed to save log entry\n");
+ }
+ fprintf(stderr, "%s\n", logmsg);
+ }
+ return -1;
+}
+
+
+/**
+ * Retrieve all log entries in the Log_t record chain with the corresponding log level.
+ * One string will be returned, with all log entries separated with newline.
+ *
+ * @param logp Pointer to Log_t record chain with log data
+ * @param level Log entries to retrieve
+ *
+ * @return Returns a pointer to a buffer with all log lines. This must be freed after usage.
+ */
+char * log_retrieve(Log_t *logp, int level)
+{
+ char *ret = NULL;
+ size_t len = 0;
+ Log_t *ptr = NULL;
+
+ if( !logp ) {
+ return NULL;
+ }
+
+ for( ptr = logp; ptr != NULL; ptr = ptr->next ) {
+ if( ptr && ptr->level == level ) {
+ if( ret ) {
+ ret = realloc(ret, strlen(ptr->message)+len+3);
+ } else {
+ ret = calloc(1, strlen(ptr->message)+2);
+ }
+
+ if( !ret ) {
+ fprintf(stderr,
+ "** ERROR ** Could not allocate log retrieval memory buffer\n");
+ return NULL;
+ }
+ strcat(ret, ptr->message);
+ strcat(ret, "\n");
+ ptr->read++;
+ len = strlen(ret);
+ }
+ }
+ return ret;
+}
+
+
+/**
+ * Remove only log records of a particular log level from the log chain. Only
+ * records that have been read (by using log_retrieve()) will be removed unless
+ * the unread argument == 1.
+ *
+ * @param logp Pointer to log chain to work on
+ * @param level Log level to remove
+ * @param unread Set to 1 to also clear unread log entriesz
+ *
+ * @return Returns number of removed elements.
+ */
+size_t log_clear_partial(Log_t *logp, int level, int unread)
+{
+ Log_t *ptr = NULL, *prev = NULL;
+ size_t elmnt = 0;
+
+ if( !logp ) {
+ return 0;
+ }
+
+ prev = logp;
+ for( ptr = logp->next; ptr != NULL; ptr = ptr->next ) {
+ if( !ptr ) {
+ break;
+ }
+
+ // Only remove log entries which is of the expected log level
+ // and that have been read.
+ if( (ptr->level == level) && ((unread == 1) || (ptr->read > 0)) ) {
+ prev->next = ptr->next;
+ if( ptr->message ) {
+ free(ptr->message);
+ ptr->message = NULL;
+ }
+ free(ptr);
+ ptr = prev;
+ elmnt++;
+ }
+ prev = ptr;
+ }
+
+ return elmnt;
+}
+
+
+/**
+ * Free all memory used by a Log_t pointer chain.
+ *
+ * @param logp Pointer to log entries to free up.
+ */
+void log_close(Log_t *logp)
+{
+ Log_t *ptr = NULL, *next = NULL;
+
+ ptr = logp;
+ while( ptr ) {
+ next = ptr->next;
+ ptr->next = NULL;
+ if( ptr->message ) {
+ free(ptr->message);
+ ptr->message = NULL;
+ }
+ free(ptr);
+ ptr = next;
+ }
+}
diff --git a/src/dmilog.h b/src/dmilog.h
new file mode 100644
index 0000000..76c87b6
--- /dev/null
+++ b/src/dmilog.h
@@ -0,0 +1,63 @@
+/*
+ * 2009 (C) David Sommerseth <davids@redhat.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open unpatent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+
+/**
+ * @file dmilog.h
+ * @brief A simple log module
+ * @author David Sommerseth <davids@redhat.com>
+ */
+
+
+#ifndef DMILOG_H
+#define DMILOG_H
+
+#include <stdarg.h>
+#include <syslog.h>
+
+/**
+ * Struct defining log records. Organised as a pointer chain.
+ */
+struct _Log_t {
+ int level; /**< Log type, based on syslog levels (LOG_ERR|LOG_WARNING) */
+ char *message; /**< Formated log text */
+ unsigned int read; /**< Number of times this log entry has been read */
+ struct _Log_t *next; /**< Next log entry */
+};
+typedef struct _Log_t Log_t;
+
+/**
+ * Log flags. These flags can be OR'ed together
+ */
+typedef enum { LOGFL_NORMAL = 1, /**< Normal behaviour, log everything and use stderr on errors */
+ LOGFL_NODUPS = 2, /**< Don't log messages we already have logged */
+ LOGFL_NOSTDERR = 4 /**< Don't use stderr even if log functions fails */
+} Log_f;
+
+Log_t * log_init();
+int log_append(Log_t *logp, Log_f flags, int level, const char *fmt, ...);
+char * log_retrieve(Log_t *logp, int level);
+size_t log_clear_partial(Log_t *logp, int level, int unread);
+void log_close(Log_t *logp);
+
+#endif
diff --git a/src/dmixml.c b/src/dmixml.c
index 5d9f1a1..ba285e8 100644
--- a/src/dmixml.c
+++ b/src/dmixml.c
@@ -41,6 +41,7 @@
#include <libxml/xpath.h>
#include <libxml/xmlstring.h>
+#include "dmilog.h"
#include "dmixml.h"
/**
@@ -323,7 +324,7 @@ inline char *dmixml_GetNodeContent(xmlNode *node, const char *key) {
* which of the elements to be extracted.
* @return char* Points at the return buffer if a value is found, otherwise NULL is returned.
*/
-char *dmixml_GetXPathContent(char *buf, size_t buflen, xmlXPathObject *xpo, int idx) {
+char *dmixml_GetXPathContent(Log_t *logp, char *buf, size_t buflen, xmlXPathObject *xpo, int idx) {
memset(buf, 0, buflen);
if( xpo == NULL ) {
@@ -351,9 +352,9 @@ char *dmixml_GetXPathContent(char *buf, size_t buflen, xmlXPathObject *xpo, int
break;
default:
- fprintf(stderr, "dmixml_GetXPathContent(...):: "
- "Do not know how to handle XPath type %i\n",
- xpo->type);
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING, "dmixml_GetXPathContent(...):: "
+ "Do not know how to handle XPath type %i",
+ xpo->type);
return NULL;
}
return buf;
diff --git a/src/dmixml.h b/src/dmixml.h
index 3dc32e5..7bbbb76 100644
--- a/src/dmixml.h
+++ b/src/dmixml.h
@@ -74,6 +74,6 @@ xmlNode *__dmixml_FindNodeByAttr(xmlNode *, const char *, const char *, const ch
xmlNode *dmixml_FindNode(xmlNode *, const char *key);
inline char *dmixml_GetContent(xmlNode *node);
inline char *dmixml_GetNodeContent(xmlNode *node, const char *key);
-char *dmixml_GetXPathContent(char *buf, size_t buflen, xmlXPathObject *xpo, int idx);
+char *dmixml_GetXPathContent(Log_t *logp, char *buf, size_t buflen, xmlXPathObject *xpo, int idx);
#endif
diff --git a/src/efi.c b/src/efi.c
index 8c38e38..ae8d0db 100644
--- a/src/efi.c
+++ b/src/efi.c
@@ -28,6 +28,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#include "dmilog.h"
#include "efi.h"
/**
@@ -42,7 +44,7 @@
* @param size_t*
* @return returns EFI_NOT_FOUND or EFI_NO_SMBIOS
*/
-int address_from_efi(size_t * address)
+int address_from_efi(Log_t *logp, size_t * address)
{
FILE *efi_systab;
const char *filename = NULL;
@@ -74,8 +76,9 @@ int address_from_efi(size_t * address)
if(fclose(efi_systab) != 0)
perror(filename);
- if(ret == EFI_NO_SMBIOS)
- fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
+ if(ret == EFI_NO_SMBIOS) {
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING, "%s: SMBIOS entry point missing", filename);
+ }
return ret;
}
diff --git a/src/efi.h b/src/efi.h
index 240fb01..dc03834 100644
--- a/src/efi.h
+++ b/src/efi.h
@@ -30,6 +30,6 @@
#define EFI_NOT_FOUND (-1)
#define EFI_NO_SMBIOS (-2)
-int address_from_efi(size_t * address);
+int address_from_efi(Log_t *logp, size_t * address);
#endif
diff --git a/src/setup-dbg.py b/src/setup-dbg.py
index b91e3e0..9bbeb21 100644
--- a/src/setup-dbg.py
+++ b/src/setup-dbg.py
@@ -67,6 +67,7 @@ setup(
"src/dmidecode.c",
"src/dmixml.c",
"src/dmierror.c",
+ "src/dmilog.c",
"src/xmlpythonizer.c",
"src/efi.c",
"src/dmidump.c"
diff --git a/src/setup.py b/src/setup.py
index b65957c..aecad71 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -67,6 +67,7 @@ setup(
"src/dmidecode.c",
"src/dmixml.c",
"src/dmierror.c",
+ "src/dmilog.c",
"src/xmlpythonizer.c",
"src/efi.c",
"src/dmidump.c"
diff --git a/src/util.c b/src/util.c
index 9bd86c5..2eebf30 100644
--- a/src/util.c
+++ b/src/util.c
@@ -47,9 +47,10 @@
#include "types.h"
#include "util.h"
+#include "dmilog.h"
#ifndef USE_MMAP
-static int myread(int fd, u8 * buf, size_t count, const char *prefix)
+static int myread(Log_t *logp, int fd, u8 * buf, size_t count, const char *prefix)
{
ssize_t r = 1;
size_t r2 = 0;
@@ -68,7 +69,7 @@ static int myread(int fd, u8 * buf, size_t count, const char *prefix)
if(r2 != count) {
close(fd);
- fprintf(stderr, "%s: Unexpected end of file\n", prefix);
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING, "%s: Unexpected end of file", prefix);
return -1;
}
@@ -90,7 +91,7 @@ int checksum(const u8 * buf, size_t len)
* Copy a physical memory chunk into a memory buffer.
* This function allocates memory.
*/
-void *mem_chunk(size_t base, size_t len, const char *devmem)
+void *mem_chunk(Log_t *logp, size_t base, size_t len, const char *devmem)
{
void *p;
int fd;
@@ -101,12 +102,12 @@ void *mem_chunk(size_t base, size_t len, const char *devmem)
#endif
if((fd = open(devmem, O_RDONLY)) == -1) {
- perror(devmem);
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING, "%s: %s", devmem, strerror(errno));
return NULL;
}
if((p = malloc(len)) == NULL) {
- perror("malloc");
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING, "malloc: %s", strerror(errno));
return NULL;
}
#ifdef USE_MMAP
@@ -122,8 +123,7 @@ void *mem_chunk(size_t base, size_t len, const char *devmem)
*/
mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
if(mmp == MAP_FAILED) {
- fprintf(stderr, "%s: ", devmem);
- perror("mmap");
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING, "%s (mmap): %s", devmem, strerror(errno));
free(p);
return NULL;
}
@@ -131,18 +131,16 @@ void *mem_chunk(size_t base, size_t len, const char *devmem)
memcpy(p, (u8 *) mmp + mmoffset, len);
if(munmap(mmp, mmoffset + len) == -1) {
- fprintf(stderr, "%s: ", devmem);
- perror("munmap");
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING, "%s (munmap): %s", devmem, strerror(errno));
}
#else /* USE_MMAP */
if(lseek(fd, base, SEEK_SET) == -1) {
- fprintf(stderr, "%s: ", devmem);
- perror("lseek");
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING, "%s (lseek): %s", devmem, strerror(errno));
free(p);
return NULL;
}
- if(myread(fd, p, len, devmem) == -1) {
+ if(myread(logp, fd, p, len, devmem) == -1) {
free(p);
return NULL;
}
diff --git a/src/util.h b/src/util.h
index 3effd0c..a93af6b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -22,9 +22,10 @@
#include <sys/types.h>
#include "types.h"
+#include "dmilog.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
int checksum(const u8 * buf, size_t len);
-void *mem_chunk(size_t base, size_t len, const char *devmem);
+void *mem_chunk(Log_t *logp, size_t base, size_t len, const char *devmem);
int write_dump(size_t base, size_t len, const void *data, const char *dumpfile, int add);
diff --git a/src/xmlpythonizer.c b/src/xmlpythonizer.c
index c4c6cb7..e318023 100644
--- a/src/xmlpythonizer.c
+++ b/src/xmlpythonizer.c
@@ -82,6 +82,7 @@
#include "util.h"
#include "dmixml.h"
#include "dmierror.h"
+#include "dmilog.h"
#include "xmlpythonizer.h"
#include "version.h"
@@ -279,7 +280,7 @@ void ptzmap_Dump_func(const ptzMAP *ptr, int level)
* @param const char* String value containing the key/value type
* @return ptzTYPES The type value
*/
-inline ptzTYPES _convert_maptype(const char *str) {
+inline ptzTYPES _convert_maptype(Log_t *logp, const char *str) {
if( strcmp(str, "string") == 0 ) {
return ptzSTR;
} else if( strcmp(str, "constant") == 0 ) {
@@ -303,7 +304,8 @@ inline ptzTYPES _convert_maptype(const char *str) {
} else if( strcmp(str, "list:dict") == 0 ) {
return ptzLIST_DICT;
} else {
- fprintf(stderr, "Unknown field type: %s - defaulting to 'constant'\n", str);
+ log_append(logp, LOGFL_NORMAL, LOG_WARNING,
+ "Unknown field type: %s - defaulting to 'constant'", str);
return ptzCONST;
}
}
@@ -315,7 +317,7 @@ inline ptzTYPES _convert_maptype(const char *str) {
* @param xmlNode* Node of the starting point for the parsing
* @return ptzMAP* The ptzMAP version of the XML definition
*/
-ptzMAP *_do_dmimap_parsing_typeid(xmlNode *node) {
+ptzMAP *_do_dmimap_parsing_typeid(Log_t *logp, xmlNode *node) {
ptzMAP *retmap = NULL;
xmlNode *ptr_n = NULL, *map_n = NULL;;
@@ -352,10 +354,10 @@ ptzMAP *_do_dmimap_parsing_typeid(xmlNode *node) {
// Get the attributes defining key, keytype, value and valuetype
key = dmixml_GetAttrValue(ptr_n, "key");
- type_key = _convert_maptype(dmixml_GetAttrValue(ptr_n, "keytype"));
+ type_key = _convert_maptype(logp, dmixml_GetAttrValue(ptr_n, "keytype"));
value = dmixml_GetAttrValue(ptr_n, "value");
- type_value = _convert_maptype(dmixml_GetAttrValue(ptr_n, "valuetype"));
+ type_value = _convert_maptype(logp, dmixml_GetAttrValue(ptr_n, "valuetype"));
rootpath = dmixml_GetAttrValue(ptr_n, "rootpath");
@@ -374,7 +376,7 @@ ptzMAP *_do_dmimap_parsing_typeid(xmlNode *node) {
// Recursion
retmap = ptzmap_Add(retmap, rootpath, type_key, key, type_value,
(type_value == ptzLIST_DICT ? value : NULL),
- _do_dmimap_parsing_typeid(ptr_n->children->next));
+ _do_dmimap_parsing_typeid(logp, ptr_n->children->next));
} else {
char *tmpstr = NULL;
@@ -452,7 +454,7 @@ xmlNode *dmiMAP_GetRootElement(xmlDoc *mapdoc) {
* @param const char* The typeid to parse to a ptzMAP
* @return ptzMAP* The parsed result of the XML nodes
*/
-ptzMAP *_dmimap_parse_mapping_node_typeid(xmlNode *mapnode, const char *typeid) {
+ptzMAP *_dmimap_parse_mapping_node_typeid(Log_t *logp, xmlNode *mapnode, const char *typeid) {
xmlNode *node = NULL;
assert( mapnode != NULL);
@@ -461,12 +463,12 @@ ptzMAP *_dmimap_parse_mapping_node_typeid(xmlNode *mapnode, const char *typeid)
node = dmixml_FindNodeByAttr_NoCase(mapnode, "TypeMap", "id", typeid);
if( node == NULL ) {
// No exception handling possible here, as we don't return PyObject
- fprintf(stderr,"** WARNING: Could not find any XML->Python "
- "mapping for type ID '%s'", typeid);
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING, "** WARNING: Could not find any XML->Python "
+ "mapping for type ID '%s'", typeid);
return NULL;
}
// Create an internal map structure and return this structure
- return _do_dmimap_parsing_typeid(node);
+ return _do_dmimap_parsing_typeid(logp, node);
}
@@ -477,7 +479,7 @@ ptzMAP *_dmimap_parse_mapping_node_typeid(xmlNode *mapnode, const char *typeid)
* @param const char* The Type ID to create the map for
* @return ptzMAP* The parsed XML containing as a ptzMAP
*/
-ptzMAP *dmiMAP_ParseMappingXML_TypeID(xmlDoc *xmlmap, int typeid) {
+ptzMAP *dmiMAP_ParseMappingXML_TypeID(Log_t *logp, xmlDoc *xmlmap, int typeid) {
xmlNode *node = NULL;
char typeid_s[16];
@@ -492,7 +494,7 @@ ptzMAP *dmiMAP_ParseMappingXML_TypeID(xmlDoc *xmlmap, int typeid) {
// Find the <TypeMapping> section
node = dmixml_FindNode(node, "TypeMapping");
assert( node != NULL );
- return _dmimap_parse_mapping_node_typeid(node, typeid_s);
+ return _dmimap_parse_mapping_node_typeid(logp, node, typeid_s);
}
@@ -505,7 +507,7 @@ ptzMAP *dmiMAP_ParseMappingXML_TypeID(xmlDoc *xmlmap, int typeid) {
* @param xmlDoc* A pointer to the source map, used for further parsing of each type defined in the GroupMapping
* @return ptzMAP* The resulting ptzMAP of the parsed xmlNode group mapping
*/
-ptzMAP *_do_dmimap_parsing_group(xmlNode *node, xmlDoc *xmlmap) {
+ptzMAP *_do_dmimap_parsing_group(Log_t *logp, xmlNode *node, xmlDoc *xmlmap) {
ptzMAP *retmap = NULL;
xmlNode *ptr_n = NULL, *map_n = NULL, *typemap = NULL;
char *type_id;
@@ -548,7 +550,7 @@ ptzMAP *_do_dmimap_parsing_group(xmlNode *node, xmlDoc *xmlmap) {
if( (type_id = dmixml_GetAttrValue(ptr_n, "id")) != NULL) {
ptzMAP *map = NULL;
- map = _dmimap_parse_mapping_node_typeid(typemap, type_id);
+ map = _dmimap_parse_mapping_node_typeid(logp, typemap, type_id);
if( map ) {
retmap = ptzmap_AppendMap(retmap, map);
}
@@ -566,7 +568,7 @@ ptzMAP *_do_dmimap_parsing_group(xmlNode *node, xmlDoc *xmlmap) {
* @param const char* Defines which group mapping to parse to a ptzMAP
* @return ptzMAP* The parsed XML mapping in a ptzMAP
*/
-ptzMAP *dmiMAP_ParseMappingXML_GroupName(xmlDoc *xmlmap, const char *mapname) {
+ptzMAP *dmiMAP_ParseMappingXML_GroupName(Log_t *logp, xmlDoc *xmlmap, const char *mapname) {
xmlNode *node = NULL;
// Validate the XML mapping document and get the root element
@@ -589,7 +591,7 @@ ptzMAP *dmiMAP_ParseMappingXML_GroupName(xmlDoc *xmlmap, const char *mapname) {
}
// Create an internal map structure and return this structure
- return _do_dmimap_parsing_group(node, xmlmap);
+ return _do_dmimap_parsing_group(logp, node, xmlmap);
}
@@ -600,7 +602,7 @@ ptzMAP *dmiMAP_ParseMappingXML_GroupName(xmlDoc *xmlmap, const char *mapname) {
* @param const char * String which contains the value to be converted to a Python value
* @return PyObject * The converted value as a Python object
*/
-inline PyObject *StringToPyObj(ptzMAP *val_m, const char *instr) {
+inline PyObject *StringToPyObj(Log_t *logp, ptzMAP *val_m, const char *instr) {
PyObject *value;
const char *workstr = NULL;
@@ -663,7 +665,9 @@ inline PyObject *StringToPyObj(ptzMAP *val_m, const char *instr) {
break;
default:
- fprintf(stderr, "Invalid type '%i' for value '%s'\n", val_m->type_value, instr);
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING,
+ "Invalid type '%i' for value '%s'",
+ val_m->type_value, instr);
value = Py_None;
}
return value;
@@ -706,7 +710,9 @@ xmlXPathObject *_get_xpath_values(xmlXPathContext *xpctx, const char *xpath) {
* @returns char* Returns a pointer to the return buffer (parameter 1) if key value
* is found, or NULL if not found
*/
-char *_get_key_value(char *key, size_t buflen, ptzMAP *map_p, xmlXPathContext *xpctx, int idx) {
+char *_get_key_value(Log_t *logp, char *key, size_t buflen,
+ ptzMAP *map_p, xmlXPathContext *xpctx, int idx)
+{
xmlXPathObject *xpobj = NULL;
memset(key, 0, buflen);
@@ -723,7 +729,7 @@ char *_get_key_value(char *key, size_t buflen, ptzMAP *map_p, xmlXPathContext *x
if( xpobj == NULL ) {
return NULL;
}
- if( dmixml_GetXPathContent(key, buflen, xpobj, idx) == NULL ) {
+ if( dmixml_GetXPathContent(logp, key, buflen, xpobj, idx) == NULL ) {
xmlXPathFreeObject(xpobj);
return NULL;
}
@@ -731,7 +737,7 @@ char *_get_key_value(char *key, size_t buflen, ptzMAP *map_p, xmlXPathContext *x
break;
default:
- fprintf(stderr, "Unknown key type: %i\n", map_p->type_key);
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING, "Unknown key type: %i", map_p->type_key);
return NULL;
}
// We consider to have a key, if the first byte is a readable
@@ -765,7 +771,7 @@ char *_get_key_value(char *key, size_t buflen, ptzMAP *map_p, xmlXPathContext *x
* @param ptzMAP* Pointer to the current mapping entry being parsed
* @param xmlXPathObject* Pointer to XPath object containing the data value(s) for the dictionary
*/
-inline void _add_xpath_result(PyObject *pydat, xmlXPathContext *xpctx, ptzMAP *map_p, xmlXPathObject *value) {
+inline void _add_xpath_result(Log_t *logp, PyObject *pydat, xmlXPathContext *xpctx, ptzMAP *map_p, xmlXPathObject *value) {
int i = 0;
char *key = NULL;
char *val = NULL;
@@ -784,22 +790,22 @@ inline void _add_xpath_result(PyObject *pydat, xmlXPathContext *xpctx, ptzMAP *m
break;
}
if( value->nodesetval->nodeNr == 0 ) {
- if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ if( _get_key_value(logp, key, 256, map_p, xpctx, 0) != NULL ) {
PyADD_DICT_VALUE(pydat, key, Py_None);
}
} else {
for( i = 0; i < value->nodesetval->nodeNr; i++ ) {
- if( _get_key_value(key, 256, map_p, xpctx, i) != NULL ) {
- dmixml_GetXPathContent(val, 4097, value, i);
- PyADD_DICT_VALUE(pydat, key, StringToPyObj(map_p, val));
+ if( _get_key_value(logp, key, 256, map_p, xpctx, i) != NULL ) {
+ dmixml_GetXPathContent(logp, val, 4097, value, i);
+ PyADD_DICT_VALUE(pydat, key, StringToPyObj(logp, map_p, val));
}
}
}
break;
default:
- if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
- dmixml_GetXPathContent(val, 4097, value, 0);
- PyADD_DICT_VALUE(pydat, key, StringToPyObj(map_p, val));
+ if( _get_key_value(logp, key, 256, map_p, xpctx, 0) != NULL ) {
+ dmixml_GetXPathContent(logp, val, 4097, value, 0);
+ PyADD_DICT_VALUE(pydat, key, StringToPyObj(logp, map_p, val));
}
break;
}
@@ -819,7 +825,9 @@ inline void _add_xpath_result(PyObject *pydat, xmlXPathContext *xpctx, ptzMAP *m
* @param int For debug purpose only, to keep track of which element being parsed
* @return PyObject* Pointer to the input Python dictionary
*/
-PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int elmtid) {
+PyObject *_deep_pythonize(Log_t *logp, PyObject *retdata,
+ ptzMAP *map_p, xmlNode *data_n, int elmtid)
+{
char *key = NULL;
xmlXPathContext *xpctx = NULL;
xmlDoc *xpdoc = NULL;
@@ -841,7 +849,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
// Extract value
switch( map_p->type_value ) {
case ptzCONST:
- if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ if( _get_key_value(logp, key, 256, map_p, xpctx, 0) != NULL ) {
value = PyString_FromString(map_p->value);
PyADD_DICT_VALUE(retdata, key, value);
} else {
@@ -856,7 +864,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
case ptzBOOL:
xpo = _get_xpath_values(xpctx, map_p->value);
if( xpo != NULL ) {
- _add_xpath_result(retdata, xpctx, map_p, xpo);
+ _add_xpath_result(logp, retdata, xpctx, map_p, xpo);
xmlXPathFreeObject(xpo);
}
break;
@@ -867,7 +875,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
case ptzLIST_BOOL:
xpo = _get_xpath_values(xpctx, map_p->value);
if( xpo != NULL ) {
- if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
+ if( _get_key_value(logp, key, 256, map_p, xpctx, 0) != NULL ) {
if( (xpo->nodesetval != NULL) && (xpo->nodesetval->nodeNr > 0) ) {
value = PyList_New(0);
@@ -883,7 +891,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
for( i = 0; i < xpo->nodesetval->nodeNr; i++ ) {
char *valstr = NULL;
valstr = (char *) malloc(4098);
- dmixml_GetXPathContent(valstr, 4097, xpo, i);
+ dmixml_GetXPathContent(logp, valstr, 4097, xpo, i);
// If we have a fixed list and we have a index value for the list
if( (map_p->fixed_list_size > 0) && (map_p->list_index != NULL) ) {
@@ -893,12 +901,13 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
map_p->list_index);
if( idx != NULL ) {
PyList_SetItem(value, atoi(idx)-1,
- StringToPyObj(map_p, valstr)
+ StringToPyObj(logp,
+ map_p, valstr)
);
}
} else {
// No list index - append the value
- PyList_Append(value, StringToPyObj(map_p, valstr));
+ PyList_Append(value,StringToPyObj(logp,map_p,valstr));
}
free(valstr);
}
@@ -920,13 +929,13 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
if( map_p->child == NULL ) {
break;
}
- if( _get_key_value(key, 256, map_p, xpctx, 0) == NULL ) {
+ if( _get_key_value(logp, key, 256, map_p, xpctx, 0) == NULL ) {
PyReturnError(PyExc_ValueError,
"Could not get key value: %s [%i] (Defining key: %s)",
map_p->rootpath, elmtid, map_p->key);
}
// Use recursion when procession child elements
- value = pythonizeXMLnode(map_p->child, data_n);
+ value = pythonizeXMLnode(logp, map_p->child, data_n);
PyADD_DICT_VALUE(retdata, key, (value != NULL ? value : Py_None));
break;
@@ -934,7 +943,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
if( map_p->child == NULL ) {
break;
}
- if( _get_key_value(key, 256, map_p, xpctx, 0) == NULL ) {
+ if( _get_key_value(logp, key, 256, map_p, xpctx, 0) == NULL ) {
PyReturnError(PyExc_ValueError,
"Could not get key value: %s [%i] (Defining key: %s)",
map_p->rootpath, elmtid, map_p->key);
@@ -966,7 +975,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
for( i = 0; i < xpo->nodesetval->nodeNr; i++ ) {
PyObject *dataset = NULL;
- dataset = pythonizeXMLnode(map_p->child, xpo->nodesetval->nodeTab[i]);
+ dataset = pythonizeXMLnode(logp, map_p->child, xpo->nodesetval->nodeTab[i]);
if( dataset != NULL ) {
// If we have a fixed list and we have a index value for the list
if( (map_p->fixed_list_size > 0) && (map_p->list_index != NULL) ) {
@@ -990,7 +999,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
break;
default:
- fprintf(stderr, "Unknown value type: %i\n", map_p->type_value);
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING, "Unknown value type: %i", map_p->type_value);
break;
}
@@ -1007,7 +1016,7 @@ PyObject *_deep_pythonize(PyObject *retdata, ptzMAP *map_p, xmlNode *data_n, int
* @param ptzMAP* The map descriping the resulting Python dictionary
* @param xmlNode* XML node pointer to the source data to be used for populating the Python dictionary
*/
-PyObject *pythonizeXMLnode(ptzMAP *in_map, xmlNode *data_n) {
+PyObject *pythonizeXMLnode(Log_t *logp, ptzMAP *in_map, xmlNode *data_n) {
xmlXPathContext *xpctx = NULL;
xmlDoc *xpdoc = NULL;
PyObject *retdata = NULL;
@@ -1046,8 +1055,8 @@ PyObject *pythonizeXMLnode(ptzMAP *in_map, xmlNode *data_n) {
for( i = 0; i < xpo->nodesetval->nodeNr; i++ ) {
xpctx->node = xpo->nodesetval->nodeTab[i];
- if( _get_key_value(key, 256, map_p, xpctx, 0) != NULL ) {
- PyObject *res = _deep_pythonize(retdata, map_p,
+ if( _get_key_value(logp, key, 256, map_p, xpctx, 0) != NULL ) {
+ PyObject *res = _deep_pythonize(logp, retdata, map_p,
xpo->nodesetval->nodeTab[i], i);
if( res == NULL ) {
// Exit if we get NULL - something is wrong
@@ -1061,15 +1070,16 @@ PyObject *pythonizeXMLnode(ptzMAP *in_map, xmlNode *data_n) {
}
#ifdef DEBUG
else {
- fprintf(stderr, "** pythonizeXMLnode :: Could not locate node for key value: "
- "root path '%s', key '%s'\n", map_p->rootpath, map_p->key);
+ log_append(logp, LOGFL_NODUPS, LOG_WARNING,
+ "** pythonizeXMLnode :: Could not locate node for key value: "
+ "root path '%s', key '%s'", map_p->rootpath, map_p->key);
}
#endif
if( xpo != NULL ) {
xmlXPathFreeObject(xpo); xpo = NULL;
}
} else {
- PyObject *res = _deep_pythonize(retdata, map_p, data_n, 0);
+ PyObject *res = _deep_pythonize(logp, retdata, map_p, data_n, 0);
if( res == NULL ) {
// Exit if we get NULL - something is wrong
//and exception is set
@@ -1088,12 +1098,12 @@ PyObject *pythonizeXMLnode(ptzMAP *in_map, xmlNode *data_n) {
* @param ptzMAP* The map descriping the resulting Python dictionary
* @param xmlDoc* XML document pointer to the source data to be used for populating the Python dictionary
*/
-PyObject *pythonizeXMLdoc(ptzMAP *map, xmlDoc *doc)
+PyObject *pythonizeXMLdoc(Log_t *logp, ptzMAP *map, xmlDoc *doc)
{
xmlNode *node = NULL;
node = xmlDocGetRootElement(doc);
- return pythonizeXMLnode(map, node);
+ return pythonizeXMLnode(logp, map, node);
}
diff --git a/src/xmlpythonizer.h b/src/xmlpythonizer.h
index df60140..e6c58bc 100644
--- a/src/xmlpythonizer.h
+++ b/src/xmlpythonizer.h
@@ -49,12 +49,12 @@ typedef struct ptzMAP_s {
} ptzMAP;
xmlNode *dmiMAP_GetRootElement(xmlDoc *mapdoc);
-ptzMAP *dmiMAP_ParseMappingXML_TypeID(xmlDoc *xmlmap, int typeid);
-ptzMAP *dmiMAP_ParseMappingXML_GroupName(xmlDoc *xmlmap, const char *mapname);
+ptzMAP *dmiMAP_ParseMappingXML_TypeID(Log_t *logp, xmlDoc *xmlmap, int typeid);
+ptzMAP *dmiMAP_ParseMappingXML_GroupName(Log_t *logp, xmlDoc *xmlmap, const char *mapname);
#define ptzmap_Free(ptr) { ptzmap_Free_func(ptr); ptr = NULL; }
void ptzmap_Free_func(ptzMAP *ptr);
-PyObject *pythonizeXMLdoc(ptzMAP *map, xmlDoc *xmldoc);
-PyObject *pythonizeXMLnode(ptzMAP *map, xmlNode *nodes);
+PyObject *pythonizeXMLdoc(Log_t *logp, ptzMAP *map, xmlDoc *xmldoc);
+PyObject *pythonizeXMLnode(Log_t *logp, ptzMAP *map, xmlNode *nodes);
#endif // _XMLPYTHONIZER_H