diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/dmidecode.c | 49 | ||||
-rw-r--r-- | src/dmidecode.h | 5 | ||||
-rw-r--r-- | src/dmidecodemodule.c | 110 | ||||
-rw-r--r-- | src/dmidecodemodule.h | 8 | ||||
-rw-r--r-- | src/dmidump.c | 8 | ||||
-rw-r--r-- | src/dmihelper.h | 2 | ||||
-rw-r--r-- | src/dmilog.c | 222 | ||||
-rw-r--r-- | src/dmilog.h | 63 | ||||
-rw-r--r-- | src/dmixml.c | 9 | ||||
-rw-r--r-- | src/dmixml.h | 2 | ||||
-rw-r--r-- | src/efi.c | 9 | ||||
-rw-r--r-- | src/efi.h | 2 | ||||
-rw-r--r-- | src/setup-dbg.py | 1 | ||||
-rw-r--r-- | src/setup.py | 1 | ||||
-rw-r--r-- | src/util.c | 22 | ||||
-rw-r--r-- | src/util.h | 3 | ||||
-rw-r--r-- | src/xmlpythonizer.c | 108 | ||||
-rw-r--r-- | src/xmlpythonizer.h | 8 |
19 files changed, 501 insertions, 135 deletions
@@ -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 @@ -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; } @@ -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" @@ -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; } @@ -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 |