diff --git a/build/lib.linux-x86_64-cpython-313/dmidecode.py b/build/lib.linux-x86_64-cpython-313/dmidecode.py new file mode 100644 index 0000000..ac81365 --- /dev/null +++ b/build/lib.linux-x86_64-cpython-313/dmidecode.py @@ -0,0 +1,89 @@ +# +# dmidecode.py +# Module front-end for the python-dmidecode module. +# +# Copyright 2009 David Sommerseth +# +# 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. +# + +import libxml2 +from dmidecodemod import * + +DMIXML_NODE='n' +DMIXML_DOC='d' + +class dmidecodeXML: + "Native Python API for retrieving dmidecode information as XML" + + def __init__(self): + self.restype = DMIXML_NODE; + + def SetResultType(self, type): + """ + Sets the result type of queries. The value can be DMIXML_NODE or DMIXML_DOC, + which will return an libxml2::xmlNode or libxml2::xmlDoc object, respectively + """ + + if type == DMIXML_NODE: + self.restype = DMIXML_NODE + elif type == DMIXML_DOC: + self.restype = DMIXML_DOC + else: + raise TypeError("Invalid result type value") + return True + + def QuerySection(self, sectname): + """ + Queries the DMI data structure for a given section name. A section + can often contain several DMI type elements + """ + if self.restype == DMIXML_NODE: + ret = libxml2.xmlNode( _obj = xmlapi(query_type='s', + result_type=self.restype, + section=sectname) ) + elif self.restype == DMIXML_DOC: + ret = libxml2.xmlDoc( _obj = xmlapi(query_type='s', + result_type=self.restype, + section=sectname) ) + else: + raise TypeError("Invalid result type value") + + return ret + + + def QueryTypeId(self, tpid): + """ + Queries the DMI data structure for a specific DMI type. + """ + if self.restype == DMIXML_NODE: + ret = libxml2.xmlNode( _obj = xmlapi(query_type='t', + result_type=self.restype, + typeid=tpid)) + elif self.restype == DMIXML_DOC: + ret = libxml2.xmlDoc( _obj = xmlapi(query_type='t', + result_type=self.restype, + typeid=tpid)) + else: + raise TypeError("Invalid result type value") + + return ret + diff --git a/build/lib.linux-x86_64-cpython-313/dmidecodemod.cpython-313-x86_64-linux-gnu.so b/build/lib.linux-x86_64-cpython-313/dmidecodemod.cpython-313-x86_64-linux-gnu.so new file mode 100755 index 0000000..98dc31d Binary files /dev/null and b/build/lib.linux-x86_64-cpython-313/dmidecodemod.cpython-313-x86_64-linux-gnu.so differ diff --git a/build/temp.linux-x86_64-cpython-313/src/dmidecode.o b/build/temp.linux-x86_64-cpython-313/src/dmidecode.o new file mode 100644 index 0000000..f5b8a2a Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/dmidecode.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/dmidecodemodule.o b/build/temp.linux-x86_64-cpython-313/src/dmidecodemodule.o new file mode 100644 index 0000000..dc73bea Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/dmidecodemodule.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/dmidump.o b/build/temp.linux-x86_64-cpython-313/src/dmidump.o new file mode 100644 index 0000000..00b0dc8 Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/dmidump.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/dmierror.o b/build/temp.linux-x86_64-cpython-313/src/dmierror.o new file mode 100644 index 0000000..f71de89 Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/dmierror.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/dmilog.o b/build/temp.linux-x86_64-cpython-313/src/dmilog.o new file mode 100644 index 0000000..3250b25 Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/dmilog.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/dmioem.o b/build/temp.linux-x86_64-cpython-313/src/dmioem.o new file mode 100644 index 0000000..f9c8e58 Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/dmioem.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/dmixml.o b/build/temp.linux-x86_64-cpython-313/src/dmixml.o new file mode 100644 index 0000000..696f570 Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/dmixml.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/efi.o b/build/temp.linux-x86_64-cpython-313/src/efi.o new file mode 100644 index 0000000..feea84c Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/efi.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/util.o b/build/temp.linux-x86_64-cpython-313/src/util.o new file mode 100644 index 0000000..1b48a95 Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/util.o differ diff --git a/build/temp.linux-x86_64-cpython-313/src/xmlpythonizer.o b/build/temp.linux-x86_64-cpython-313/src/xmlpythonizer.o new file mode 100644 index 0000000..9f46dc1 Binary files /dev/null and b/build/temp.linux-x86_64-cpython-313/src/xmlpythonizer.o differ diff --git a/dmidecode.py b/dmidecode.py index ac81365..19379f4 100644 --- a/dmidecode.py +++ b/dmidecode.py @@ -25,24 +25,25 @@ # are deemed to be part of the source code. # -import libxml2 +try: + from lxml import etree +except ImportError: + raise ImportError("lxml is required. Install with: pip install lxml") + from dmidecodemod import * +from lxml import etree +from dmidecodemod import xmlapi -DMIXML_NODE='n' -DMIXML_DOC='d' +DMIXML_NODE = 'n' +DMIXML_DOC = 'd' class dmidecodeXML: "Native Python API for retrieving dmidecode information as XML" - + def __init__(self): - self.restype = DMIXML_NODE; + self.restype = DMIXML_NODE def SetResultType(self, type): - """ - Sets the result type of queries. The value can be DMIXML_NODE or DMIXML_DOC, - which will return an libxml2::xmlNode or libxml2::xmlDoc object, respectively - """ - if type == DMIXML_NODE: self.restype = DMIXML_NODE elif type == DMIXML_DOC: @@ -52,38 +53,308 @@ def SetResultType(self, type): return True def QuerySection(self, sectname): - """ - Queries the DMI data structure for a given section name. A section - can often contain several DMI type elements - """ - if self.restype == DMIXML_NODE: - ret = libxml2.xmlNode( _obj = xmlapi(query_type='s', - result_type=self.restype, - section=sectname) ) - elif self.restype == DMIXML_DOC: - ret = libxml2.xmlDoc( _obj = xmlapi(query_type='s', - result_type=self.restype, - section=sectname) ) - else: - raise TypeError("Invalid result type value") + try: + query_args = { + 'query_type': 's', + 'result_type': 'n' if self.restype == DMIXML_NODE else 'd', + 'section': sectname + } + + xml_string = xmlapi(**query_args) - return ret + if not xml_string or not isinstance(xml_string, str): + raise RuntimeError("C module did not return a valid XML string") + if self.restype == DMIXML_NODE: + return etree.fromstring(xml_string) + elif self.restype == DMIXML_DOC: + return etree.ElementTree(etree.fromstring(xml_string)) + else: + raise TypeError("Invalid result type value") + + except Exception as e: + raise RuntimeError(f"Failed to query section '{sectname}': {str(e)}") def QueryTypeId(self, tpid): - """ - Queries the DMI data structure for a specific DMI type. - """ - if self.restype == DMIXML_NODE: - ret = libxml2.xmlNode( _obj = xmlapi(query_type='t', - result_type=self.restype, - typeid=tpid)) - elif self.restype == DMIXML_DOC: - ret = libxml2.xmlDoc( _obj = xmlapi(query_type='t', - result_type=self.restype, - typeid=tpid)) - else: - raise TypeError("Invalid result type value") + try: + tpid = int(tpid) + query_args = { + 'query_type': 't', + 'result_type': 'n' if self.restype == DMIXML_NODE else 'd', + 'typeid': tpid + } + + xml_string = xmlapi(**query_args) + + if not xml_string or not isinstance(xml_string, str): + raise RuntimeError("C module did not return a valid XML string") + + if self.restype == DMIXML_NODE: + return etree.fromstring(xml_string) + elif self.restype == DMIXML_DOC: + return etree.ElementTree(etree.fromstring(xml_string)) + else: + raise TypeError("Invalid result type value") + + except Exception as e: + raise RuntimeError(f"Failed to query type ID '{tpid}': {str(e)}") + +# Convenience functions for backward compatibility +def query_section(sectname, result_type=DMIXML_NODE): + """ + Convenience function to query a section and return lxml object + """ + dmi = dmidecodeXML() + dmi.SetResultType(result_type) + return dmi.QuerySection(sectname) + +def query_type_id(tpid, result_type=DMIXML_NODE): + """ + Convenience function to query a type ID and return lxml object + """ + dmi = dmidecodeXML() + dmi.SetResultType(result_type) + return dmi.QueryTypeId(tpid) + +# Backward compatibility class for older API +class DMIDecode: + def __init__(self): + self.dmi = dmidecodeXML() + + def get(self, section=None, type_id=None): + try: + if section is not None: + section = str(section) + xml_data = self.dmi.QuerySection(section) + elif type_id is not None: + if isinstance(type_id, dict): + try: + type_id = int(list(type_id.keys())[0], 16) + except Exception as e: + raise ValueError(f"Invalid type_id dict format: {type_id}") from e + else: + type_id = int(type_id) + xml_data = self.dmi.QueryTypeId(type_id) + else: + raise ValueError("Either section or type_id must be specified") + + if xml_data is None: + return {} + + return self._xml_to_dict(xml_data) + + except Exception as e: + import traceback + traceback.print_exc() + return {} + + def _xml_to_dict(self, xml_element): + result = {} + if xml_element.attrib: + result.update(xml_element.attrib) + if xml_element.text and xml_element.text.strip(): + if len(xml_element) == 0: + return xml_element.text.strip() + else: + result['_text'] = xml_element.text.strip() + for child in xml_element: + child_data = self._xml_to_dict(child) + if child.tag in result: + if not isinstance(result[child.tag], list): + result[child.tag] = [result[child.tag]] + result[child.tag].append(child_data) + else: + result[child.tag] = child_data + return result + + def system(self): + """Get system information""" + return self.get(section="system") + + def bios(self): + """Get BIOS information""" + return self.get(type_id=0) + + def baseboard(self): + """Get baseboard information""" + return self.get(type_id=2) + + def chassis(self): + """Get chassis information""" + return self.get(type_id=3) + + def processor(self): + """Get processor information""" + return self.get(type_id=4) + + def memory(self): + """Get memory information""" + return self.get(section="memory") + + def model(self): + """Get system model information""" + try: + system_info = self.get(section="system") + if system_info and isinstance(system_info, dict): + # Try to find model/product name in the system info + # Look for common keys that might contain model info + for key in ['product', 'model', 'product_name', 'system_product_name']: + if key in system_info: + return system_info[key] + + # If it's nested, try to find it in nested structures + for value in system_info.values(): + if isinstance(value, dict): + for subkey in ['product', 'model', 'product_name']: + if subkey in value: + return value[subkey] + + return "Unknown" + except Exception as e: + print(f"Error getting model info: {e}") + return "Unknown" + + def manufacturer(self): + """Get system manufacturer""" + try: + system_info = self.get(section="system") + if system_info and isinstance(system_info, dict): + for key in ['manufacturer', 'vendor', 'system_manufacturer']: + if key in system_info: + return system_info[key] + + # Check nested structures + for value in system_info.values(): + if isinstance(value, dict): + for subkey in ['manufacturer', 'vendor']: + if subkey in value: + return value[subkey] + + return "Unknown" + except Exception as e: + print(f"Error getting manufacturer info: {e}") + return "Unknown" + + def version(self): + """Get system version""" + try: + system_info = self.get(section="system") + if system_info and isinstance(system_info, dict): + for key in ['version', 'system_version']: + if key in system_info: + return system_info[key] + + # Check nested structures + for value in system_info.values(): + if isinstance(value, dict): + if 'version' in value: + return value['version'] + + return "Unknown" + except Exception as e: + print(f"Error getting version info: {e}") + return "Unknown" + + def serial(self): + """Get system serial number""" + try: + system_info = self.get(section="system") + if system_info and isinstance(system_info, dict): + for key in ['serial', 'serial_number', 'system_serial']: + if key in system_info: + return system_info[key] + + # Check nested structures + for value in system_info.values(): + if isinstance(value, dict): + for subkey in ['serial', 'serial_number']: + if subkey in value: + return value[subkey] + + return "Unknown" + except Exception as e: + print(f"Error getting serial info: {e}") + return "Unknown" + + def cpu_type(self): + """Get CPU type/model information""" + try: + # Try processor section first + proc_info = self.get(type_id=4) # Type 4 is processor + if proc_info and isinstance(proc_info, dict): + # Look for CPU model/type info + for key in ['version', 'model', 'name', 'processor_version', 'processor_name']: + if key in proc_info: + return proc_info[key] + + # Check nested structures + for value in proc_info.values(): + if isinstance(value, dict): + for subkey in ['version', 'model', 'name']: + if subkey in value: + return value[subkey] + + # If that fails, try a different approach + return "Unknown" + except Exception as e: + print(f"Error getting CPU type: {e}") + return "Unknown" + + def cpu(self): + """Alias for cpu_type() for compatibility""" + return self.cpu_type() - return ret +# Example usage functions +def get_system_info(): + """ + Get system information as a convenient dictionary + """ + try: + root = query_section("system") + if root is None: + return None + + system_info = {} + + # Extract common system information + for elem in root.iter(): + if elem.tag == "manufacturer": + system_info["manufacturer"] = elem.text + elif elem.tag == "product": + system_info["product"] = elem.text + elif elem.tag == "version": + system_info["version"] = elem.text + elif elem.tag == "serial": + system_info["serial"] = elem.text + elif elem.tag == "uuid": + system_info["uuid"] = elem.text + elif elem.tag == "family": + system_info["family"] = elem.text + + return system_info + except Exception as e: + print(f"Error getting system info: {e}") + return None +def get_memory_info(): + """ + Get memory information as a list of memory modules + """ + try: + root = query_section("memory") + if root is None: + return None + + memory_modules = [] + + # This is a simplified example - you'd need to adjust based on actual XML structure + for device in root.findall(".//memory_device"): + module = {} + for child in device: + module[child.tag] = child.text + memory_modules.append(module) + + return memory_modules + except Exception as e: + print(f"Error getting memory info: {e}") + return None diff --git a/src/dmidecode.c b/src/dmidecode.c index d40f0ee..d1a10c1 100644 --- a/src/dmidecode.c +++ b/src/dmidecode.c @@ -1843,6 +1843,8 @@ void dmi_cache_size_2(xmlNode *node, const char *tagname, u32 code) size.l = code << 6; size.h = code >> 26; } else { + dmixml_AddAttribute(caches_n, "unit", "KB"); + dmixml_AddTextContent(caches_n, "%i", code); size.l = code; size.h = 0; } diff --git a/src/dmidecodemodule.c b/src/dmidecodemodule.c index efa730b..2b3f67f 100644 --- a/src/dmidecodemodule.c +++ b/src/dmidecodemodule.c @@ -42,8 +42,6 @@ #include #include -#include "libxml_wrap.h" - #include "dmidecodemodule.h" #include "dmixml.h" #include "dmierror.h" @@ -431,6 +429,7 @@ xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) { dmixml_n = xmlNewNode(NULL, (xmlChar *) "dmidecode"); assert( dmixml_n != NULL ); + // Append DMI version info if( opt->dmiversion_n != NULL ) { xmlAddChild(dmixml_n, xmlCopyNode(opt->dmiversion_n, 1)); @@ -439,7 +438,6 @@ xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) { // Fetch the Mapping XML file if( (group_n = load_mappingxml(opt)) == NULL) { xmlFreeNode(dmixml_n); - // Exception already set by calling function return NULL; } @@ -468,36 +466,35 @@ xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) { continue; } - // The children of tags must only be and - // they must have an 'id' attribute if( (typeid == NULL) || (xmlStrcmp(group_n->name, (xmlChar *) "TypeMap") != 0) ) { PyReturnError(PyExc_RuntimeError, "Invalid TypeMap node in mapping XML"); } - // Parse the typeid string to a an integer opt->type = parse_opt_type(opt->logdata, typeid); if(opt->type == -1) { 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); + PyErr_Format(PyExc_RuntimeError, "Invalid type id '%s' -- %s", typeid, err); free(err); return NULL; } - // Parse the DMI data and put the result into dmixml_n node chain. if( dmidecode_get_xml(opt, dmixml_n) != 0 ) { - PyReturnError(PyExc_RuntimeError, "Error decoding DMI data"); + return NULL; } } + #if 0 // DEBUG - will dump generated XML to stdout xmlDoc *doc = xmlNewDoc((xmlChar *) "1.0"); xmlDocSetRootElement(doc, xmlCopyNode(dmixml_n, 1)); xmlSaveFormatFileEnc("-", doc, "UTF-8", 1); xmlFreeDoc(doc); #endif + return dmixml_n; } + static PyObject *dmidecode_get_group(options *opt, const char *section) { int efi; @@ -692,73 +689,127 @@ static PyObject *dmidecode_get_type(PyObject * self, PyObject * args) static PyObject *dmidecode_xmlapi(PyObject *self, PyObject *args, PyObject *keywds) { - static char *keywordlist[] = {"query_type", "result_type", "section", "typeid", NULL}; - PyObject *pydata = NULL; - xmlDoc *dmixml_doc = NULL; - xmlNode *dmixml_n = NULL; - char *sect_query = NULL, *qtype = NULL, *rtype = NULL; - int type_query = -1; + static char *keywordlist[] = {"query_type", "result_type", "section", "typeid", NULL}; + PyObject *pydata = NULL; + xmlDoc *dmixml_doc = NULL; + xmlNode *dmixml_n = NULL; + char *sect_query = NULL, *qtype = NULL, *rtype = NULL; + int type_query = -1; + xmlBuffer *buffer = NULL; + xmlChar *xml_string = NULL; + int xml_size = 0; + + if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|si", keywordlist, + &qtype, &rtype, §_query, &type_query)) + return NULL; + + if (!qtype || !rtype) { + PyErr_SetString(PyExc_TypeError, "query_type and result_type cannot be NULL"); + return NULL; + } + + switch (*qtype) { + case 's': + if (!sect_query) { + PyErr_SetString(PyExc_TypeError, "section keyword cannot be NULL"); + return NULL; + } + dmixml_n = __dmidecode_xml_getsection(global_options, sect_query); + if (!dmixml_n) { + PyErr_Format(PyExc_RuntimeError, "DMI section '%s' returned NULL - possibly unsupported or bad permissions", sect_query); + return NULL; + } + break; + case 't': + if (type_query < 0) { + PyErr_SetString(PyExc_TypeError, "typeid keyword must be set and positive integer"); + return NULL; + } + if (type_query > 255) { + PyErr_SetString(PyExc_ValueError, "typeid must be between 0 and 255"); + return NULL; + } + dmixml_n = __dmidecode_xml_gettypeid(global_options, type_query); + if (!dmixml_n) { + PyErr_Format(PyExc_RuntimeError, "DMI type '%d' returned NULL - possibly unsupported or bad permissions", type_query); + return NULL; + } + break; + default: + PyErr_Format(PyExc_TypeError, "Invalid query type '%c' - must be 's' or 't'", *qtype); + return NULL; + } + + if (!dmixml_n) // ekstra kontrol, zaten hata set edildi + return NULL; - // Parse the keywords - we only support keywords, as this is an internal API - if( !PyArg_ParseTupleAndKeywords(args, keywds, "ss|si", keywordlist, - &qtype, &rtype, §_query, &type_query) ) { + switch (*rtype) { + case 'n': // XML node string + buffer = xmlBufferCreate(); + if (!buffer) { + xmlFreeNode(dmixml_n); + PyErr_SetString(PyExc_MemoryError, "Could not create XML buffer"); return NULL; - } + } - // Check for sensible arguments and retrieve the xmlNode with DMI data - switch( *qtype ) { - case 's': // Section / GroupName - if( sect_query == NULL ) { - PyReturnError(PyExc_TypeError, "section keyword cannot be NULL") - } - dmixml_n = __dmidecode_xml_getsection(global_options, sect_query); - break; - - case 't': // TypeID / direct TypeMap - if( type_query < 0 ) { - PyReturnError(PyExc_TypeError, - "typeid keyword must be set and must be a positive integer"); - } else if( type_query > 255 ) { - PyReturnError(PyExc_ValueError, - "typeid keyword must be an integer between 0 and 255"); - } - dmixml_n = __dmidecode_xml_gettypeid(global_options, type_query); - break; + if (xmlNodeDump(buffer, dmixml_n->doc, dmixml_n, 0, 1) < 0) { + xmlBufferFree(buffer); + xmlFreeNode(dmixml_n); + PyErr_SetString(PyExc_RuntimeError, "Could not dump XML node to buffer"); + return NULL; + } - default: - PyReturnError(PyExc_TypeError, "Internal error - invalid query type '%c'", *qtype); - } + pydata = PyUnicode_FromString((const char *)xmlBufferContent(buffer)); + xmlBufferFree(buffer); + xmlFreeNode(dmixml_n); + break; - // Check if we got any data - if( dmixml_n == NULL ) { - // Exception already set + case 'd': // Full XML document string + dmixml_doc = xmlNewDoc((xmlChar *)"1.0"); + if (!dmixml_doc) { + xmlFreeNode(dmixml_n); + PyErr_SetString(PyExc_MemoryError, "Could not create new XML document"); return NULL; - } + } - // Check for sensible return type and wrap the correct type into a Python Object - switch( *rtype ) { - case 'n': - pydata = libxml_xmlNodePtrWrap((xmlNode *) dmixml_n); - break; + xmlNode *root_node = xmlCopyNode(dmixml_n, 1); + if (!root_node) { + xmlFreeDoc(dmixml_doc); + xmlFreeNode(dmixml_n); + PyErr_SetString(PyExc_MemoryError, "Could not copy XML node"); + return NULL; + } - case 'd': - dmixml_doc = xmlNewDoc((xmlChar *) "1.0"); - if( dmixml_doc == NULL ) { - PyReturnError(PyExc_MemoryError, "Could not create new XML document"); - } - xmlDocSetRootElement(dmixml_doc, dmixml_n); - pydata = libxml_xmlDocPtrWrap((xmlDoc *) dmixml_doc); - break; + xmlDocSetRootElement(dmixml_doc, root_node); + + xmlDocDumpMemory(dmixml_doc, &xml_string, &xml_size); + if (!xml_string) { + xmlFreeDoc(dmixml_doc); + xmlFreeNode(dmixml_n); + PyErr_SetString(PyExc_RuntimeError, "Could not dump XML document to memory"); + return NULL; + } + + pydata = PyUnicode_FromString((const char *)xml_string); + + xmlFree(xml_string); + xmlFreeDoc(dmixml_doc); + xmlFreeNode(dmixml_n); + break; default: - PyReturnError(PyExc_TypeError, "Internal error - invalid result type '%c'", *rtype); - } + xmlFreeNode(dmixml_n); + PyErr_Format(PyExc_TypeError, "Invalid result type '%c' - must be 'n' or 'd'", *rtype); + return NULL; + } - // Return XML data - Py_INCREF(pydata); - return pydata; -} + if (!pydata) { + PyErr_SetString(PyExc_RuntimeError, "Could not create Python string from XML data"); + return NULL; + } + return pydata; +} static PyObject *dmidecode_dump(PyObject * self, PyObject * null) @@ -913,8 +964,12 @@ static PyMethodDef DMIDataMethods[] = { {(char *)"pythonmap", dmidecode_set_pythonxmlmap, METH_O, (char *) "Use another python dict map definition. The default file is " PYTHON_XML_MAP}, - {(char *)"xmlapi", dmidecode_xmlapi, METH_VARARGS | METH_KEYWORDS, - (char *) "Internal API for retrieving data as raw XML data"}, + { + .ml_name = "xmlapi", + .ml_meth = (PyCFunction)(void(*)(void))dmidecode_xmlapi, + .ml_flags = METH_VARARGS | METH_KEYWORDS, + .ml_doc = "Get DMI data as XML" + }, {(char *)"get_warnings", dmidecode_get_warnings, METH_NOARGS, @@ -926,48 +981,49 @@ static PyMethodDef DMIDataMethods[] = { {NULL, NULL, 0, NULL} }; -void destruct_options(void *ptr) +void destruct_options(PyObject *capsule) { -#ifdef IS_PY3K - ptr = PyCapsule_GetPointer(ptr, NULL); -#endif + void *ptr = PyCapsule_GetPointer(capsule, NULL); + if (ptr) { options *opt = (options *) ptr; if( opt->mappingxml != NULL ) { - xmlFreeDoc(opt->mappingxml); - opt->mappingxml = NULL; + xmlFreeDoc(opt->mappingxml); + opt->mappingxml = NULL; } if( opt->python_xml_map != NULL ) { - free(opt->python_xml_map); - opt->python_xml_map = NULL; + free(opt->python_xml_map); + opt->python_xml_map = NULL; } if( opt->dmiversion_n != NULL ) { - xmlFreeNode(opt->dmiversion_n); - opt->dmiversion_n = NULL; + xmlFreeNode(opt->dmiversion_n); + opt->dmiversion_n = NULL; } if( opt->dumpfile != NULL ) { - free(opt->dumpfile); - opt->dumpfile = NULL; + free(opt->dumpfile); + opt->dumpfile = NULL; } if( opt->logdata != NULL ) { - char *warn = 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); + 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); + } } + #ifdef IS_PY3K static struct PyModuleDef dmidecodemod_def = { PyModuleDef_HEAD_INIT, diff --git a/src/setup_common.py b/src/setup_common.py index aec1f9b..90d88c3 100644 --- a/src/setup_common.py +++ b/src/setup_common.py @@ -69,7 +69,7 @@ def libxml2_lib(libdir, libs): libs.append(l.replace("-l", "", 1)) # this library is not reported and we need it anyway - libs.append('xml2mod') + #libs.append('xml2mod')