summaryrefslogtreecommitdiffstats
path: root/src/dmidecodemodule.c
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2009-08-11 11:34:21 +0200
committerDavid Sommerseth <davids@redhat.com>2009-08-11 11:34:21 +0200
commiteb08fd406370a81172d7fdd0663233a5f140b784 (patch)
treec50e19f2b873441672b20a7e339c176d9a4a7cbf /src/dmidecodemodule.c
parent39cbdfb56e80cabbd67754d8d77f781e14eaa3da (diff)
parent3165a97a06f891622b913714bc4f8ca54565f9cc (diff)
downloadpython-dmidecode-eb08fd406370a81172d7fdd0663233a5f140b784.tar.gz
python-dmidecode-eb08fd406370a81172d7fdd0663233a5f140b784.tar.xz
python-dmidecode-eb08fd406370a81172d7fdd0663233a5f140b784.zip
Merge commit 'nima/xml'
Conflicts: debian/changelog Had the same changelog entry in both xml and master branch, with a minor wording difference. Removed the duplicate and merged in the changelog entries from the XML branch src/dmidecode.c Merge process got confused by some functions which was not changed. Removed the code coming from the master branch and let the XML be the base. src/setup-dbg.py src/setup.py In the XML branch, the version of the python-dmidecode is now a function which retrieves the version number from src/version.h. Merged in this feature to master as well.
Diffstat (limited to 'src/dmidecodemodule.c')
-rw-r--r--src/dmidecodemodule.c964
1 files changed, 695 insertions, 269 deletions
diff --git a/src/dmidecodemodule.c b/src/dmidecodemodule.c
index 345b151..5c74124 100644
--- a/src/dmidecodemodule.c
+++ b/src/dmidecodemodule.c
@@ -1,305 +1,731 @@
+
+/*. ******* coding:utf-8 AUTOHEADER START v1.1 *******
+ *. vim: fileencoding=utf-8 syntax=c sw=8 ts=8 et
+ *.
+ *. © 2007-2009 Nima Talebi <nima@autonomy.net.au>
+ *. © 2009 David Sommerseth <davids@redhat.com>
+ *. © 2002-2008 Jean Delvare <khali@linux-fr.org>
+ *. © 2000-2002 Alan Cox <alan@redhat.com>
+ *.
+ *. This file is part of Python DMI-Decode.
+ *.
+ *. Python DMI-Decode 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.
+ *.
+ *. Python DMI-Decode 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 Python DMI-Decode. If not, see <http://www.gnu.org/licenses/>.
+ *.
+ *. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ *. EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ *. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *.
+ *. ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
+ *. AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
+ *.
+ *. $AutoHeaderSerial::20090522 $
+ *. ******* AUTOHEADER END v1.1 ******* */
+
+#include <Python.h>
+
+#include <libxml/tree.h>
+#include "libxml_wrap.h"
+
+#include "xmlpythonizer.h"
#include "dmidecodemodule.h"
+#include "dmixml.h"
+#include "dmierror.h"
+#include "version.h"
+#include "dmidump.h"
#include <mcheck.h>
-options opt;
-static void init(void) {
- /* sanity check */
- if(sizeof(u8)!=1 || sizeof(u16)!=2 || sizeof(u32)!=4 || '\0'!=0)
- fprintf(stderr, "%s: compiler incompatibility\n", "dmidecodemodule");
+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;
+ opt->type = -1;
+ opt->dmiversion_n = NULL;
+ opt->mappingxml = NULL;
+ opt->python_xml_map = strdup(PYTHON_XML_MAP);
+}
- opt.devmem = DEFAULT_MEM_DEV;
- opt.dumpfile = NULL;
- opt.flags=0;
- opt.type = NULL;
+int parse_opt_type(const char *arg)
+{
+ while(*arg != '\0') {
+ int val;
+ char *next;
+
+ val = strtoul(arg, &next, 0);
+ if(next == arg) {
+ fprintf(stderr, "Invalid type keyword: %s\n", arg);
+ return -1;
+ }
+ if(val > 0xff) {
+ fprintf(stderr, "Invalid type number: %i\n", val);
+ return -1;
+ }
+
+ if( val >= 0 ) {
+ return val;
+ }
+ arg = next;
+ while(*arg == ',' || *arg == ' ')
+ arg++;
+ }
+ return -1;
}
-u8 *parse_opt_type(u8 *p, const char *arg) {
-
- /* Allocate memory on first call only */
- if(p == NULL) {
- if(!(p = (u8 *)calloc(256, sizeof(u8)))) {
- perror("calloc");
- return NULL;
- }
- }
-
- unsigned int i, j;
- /* First try as a keyword */
- for(i = 0; i < ARRAY_SIZE(opt_type_keyword); i++) {
- if(!strcasecmp(arg, opt_type_keyword[i].keyword)) {
- j = 0;
- while(opt_type_keyword[i].type[j] != 255)
- p[opt_type_keyword[i].type[j++]] = 1;
- return p;
- }
- }
-
- /* Else try as a number */
- while(*arg != '\0') {
- unsigned long val;
- char *next;
-
- val = strtoul(arg, &next, 0);
- if(next == arg) {
- fprintf(stderr, "Invalid type keyword: %s\n", arg);
- free(p);
- return NULL;
- }
- if (val > 0xff) {
- fprintf(stderr, "Invalid type number: %lu\n", val);
- free(p);
- return NULL;
- }
-
- p[val] = 1;
- arg = next;
- while(*arg == ',' || *arg == ' ')
- arg++;
- }
-
- return p;
+xmlNode *dmidecode_get_version(options *opt)
+{
+ int found = 0;
+ size_t fp;
+ int efi;
+ u8 *buf = NULL;
+ xmlNode *ver_n = NULL;
+
+ /* Set default option values */
+ if( opt->devmem == NULL ) {
+ opt->devmem = DEFAULT_MEM_DEV;
+ }
+
+ /* 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(memcmp(buf, "_SM_", 4) == 0) {
+ ver_n = smbios_decode_get_version(buf, opt->dumpfile);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ } else if(memcmp(buf, "_DMI_", 5) == 0) {
+ ver_n = legacy_decode_get_version(buf, opt->dumpfile);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ }
+ }
+ } else { /* Read from /dev/mem */
+ /* First try EFI (ia64, Intel-based Mac) */
+ efi = address_from_efi(&fp);
+ if(efi == EFI_NOT_FOUND) {
+ /* Fallback to memory scan (x86, x86_64) */
+ if((buf = mem_chunk(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);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ fp += 16;
+ } else if(memcmp(buf + fp, "_DMI_", 5) == 0) {
+ ver_n = legacy_decode_get_version (buf + fp, opt->devmem);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ }
+ }
+ }
+ } else if(efi == EFI_NO_SMBIOS) {
+ ver_n = NULL;
+ } else {
+ // Process as EFI
+ if((buf = mem_chunk(fp, 0x20, opt->devmem)) != NULL) {
+ ver_n = smbios_decode_get_version(buf, opt->devmem);
+ if( dmixml_GetAttrValue(ver_n, "unknown") == NULL ) {
+ found++;
+ }
+ //. TODO: dmixml_AddAttribute(dmixml_n, "efi_address", efiAddress);
+ }
+ }
+ }
+ if( buf != NULL ) {
+ free(buf);
+ }
+ if( !found ) {
+ fprintf(stderr, "No SMBIOS nor DMI entry point found, sorry.");
+ }
+ return ver_n;
}
+int dmidecode_get_xml(options *opt, xmlNode* dmixml_n)
+{
+ assert(dmixml_n != NULL);
+ if(dmixml_n == NULL) {
+ return 0;
+ }
+ //mtrace();
+
+ int ret = 0;
+ int found = 0;
+ size_t fp;
+ int efi;
+ u8 *buf = NULL;
+
+ 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);
+ 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(memcmp(buf, "_SM_", 4) == 0) {
+ if(smbios_decode(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))
+ found++;
+ }
+ } else {
+ ret = 1;
+ }
+ } else { /* Read from /dev/mem */
+ /* First try EFI (ia64, Intel-based Mac) */
+ efi = address_from_efi(&fp);
+ if(efi == EFI_NOT_FOUND) {
+ /* Fallback to memory scan (x86, x86_64) */
+ if((buf = mem_chunk(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)) {
+ found++;
+ fp += 16;
+ }
+ } else if(memcmp(buf + fp, "_DMI_", 5) == 0) {
+ if(legacy_decode(opt->type, buf + fp, opt->devmem, dmixml_n))
+ found++;
+ }
+ }
+ } else
+ ret = 1;
+ } else if(efi == EFI_NO_SMBIOS) {
+ ret = 1;
+ } else {
+ if((buf = mem_chunk(fp, 0x20, opt->devmem)) == NULL)
+ ret = 1;
+ else if(smbios_decode(opt->type, buf, opt->devmem, dmixml_n))
+ found++;
+ // TODO: dmixml_AddAttribute(dmixml_n, "efi_address", "0x%08x", efiAddress);
+ }
+ }
+ if(ret == 0) {
+ free(buf);
+ }
+ //muntrace();
+ return ret;
+}
-static int dmidecode_set_version(PyObject** pydata) {
- int ret=0;
- int found=0;
- size_t fp;
- int efi;
- u8 *buf;
-
- /* Set default option values */
- opt.devmem = DEFAULT_MEM_DEV;
-
- /***********************************/
- /* Read from dump if so instructed */
- if(opt.dumpfile != NULL) {
- const char *dumpfile = PyString_AS_STRING(opt.dumpfile);
- //. printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
- if((buf = mem_chunk(0, 0x20, dumpfile))!=NULL) {
- if(memcmp(buf, "_SM_", 4)==0) {
- if(smbios_decode_set_version(buf, dumpfile, pydata)) found++;
- } else if (memcmp(buf, "_DMI_", 5)==0) {
- if(legacy_decode_set_version(buf, dumpfile, pydata)) found++;
- }
- } else ret = 1;
- } else { /* Read from /dev/mem */
- /* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
- if(efi == EFI_NOT_FOUND) {
- /* Fallback to memory scan (x86, x86_64) */
- if((buf=mem_chunk(0xF0000, 0x10000, opt.devmem))!=NULL) {
- for(fp=0; fp<=0xFFF0; fp+=16) {
- if(memcmp(buf+fp, "_SM_", 4)==0 && fp<=0xFFE0) {
- if(smbios_decode_set_version(buf+fp, opt.devmem, pydata)) found++;
- fp+=16;
- } else if(memcmp(buf+fp, "_DMI_", 5)==0) {
- if(legacy_decode_set_version(buf+fp, opt.devmem, pydata)) found++;
- }
- }
- } else ret = 1;
- } else if(efi == EFI_NO_SMBIOS) {
- ret = 1;
- } else {
- if((buf=mem_chunk(fp, 0x20, opt.devmem))==NULL) ret = 1;
- else if(smbios_decode_set_version(buf, opt.devmem, pydata)) found++;
- //. TODO: dmiSetItem(pydata, "efi_address", efiAddress);
- }
- }
-
- if(ret==0) {
- free(buf);
- if(!found) {
- fprintf(stderr, "No SMBIOS nor DMI entry point found, sorry G.");
- }
- }
- free(opt.type);
- return ret;
+xmlNode* load_mappingxml(options *opt) {
+ if( opt->mappingxml == NULL ) {
+ // Load mapping into memory
+ opt->mappingxml = xmlReadFile(opt->python_xml_map, NULL, 0);
+ if( opt->mappingxml == NULL ) {
+ PyReturnError(PyExc_IOError, "Could not open tje XML mapping file '%s'",
+ opt->python_xml_map);
+ }
+ }
+ return dmiMAP_GetRootElement(opt->mappingxml);
}
+xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) {
+ xmlNode *dmixml_n = NULL;
+ xmlNode *group_n = NULL;
+
+ 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));
+ }
+
+ // Fetch the Mapping XML file
+ if( (group_n = load_mappingxml(opt)) == NULL) {
+ // Exception already set by calling function
+ return NULL;
+ }
+
+ // Find the section in the XML containing the group mappings
+ if( (group_n = dmixml_FindNode(group_n, "GroupMapping")) == NULL ) {
+ PyReturnError(PyExc_LookupError,
+ "Could not find the GroupMapping section in the XML mapping");
+ }
+
+ // Find the XML node containing the Mapping section requested to be decoded
+ if( (group_n = dmixml_FindNodeByAttr(group_n, "Mapping", "name", section)) == NULL ) {
+ PyReturnError(PyExc_LookupError,
+ "Could not find the XML->Python Mapping section for '%s'", section);
+ }
+
+ if( group_n->children == NULL ) {
+ PyReturnError(PyExc_RuntimeError,
+ "Mapping is empty for the '%s' section in the XML mapping", section);
+ }
-static PyObject* dmidecode_get(PyObject *self, const char* section) {
- //mtrace();
-
- int ret=0;
- int found=0;
- size_t fp;
- int efi;
- u8 *buf;
-
- /* Set default option values */
- opt.devmem = DEFAULT_MEM_DEV;
- opt.flags = 0;
- opt.type = NULL;
- opt.type = parse_opt_type(opt.type, section);
- if(opt.type==NULL) return NULL;
-
- const char *f = opt.dumpfile ? PyString_AsString(opt.dumpfile) : opt.devmem;
- if(access(f, R_OK) < 0)
- PyErr_SetString(PyExc_IOError, "Permission denied to memory file/device");
-
- PyObject* pydata = PyDict_New();
-
- /***********************************/
- /* Read from dump if so instructed */
- if(opt.dumpfile != NULL) {
- const char *dumpfile = PyString_AS_STRING(opt.dumpfile);
- //. printf("Reading SMBIOS/DMI data from file %s.\n", dumpfile);
- if((buf = mem_chunk(0, 0x20, dumpfile))!=NULL) {
- if(memcmp(buf, "_SM_", 4)==0) {
- if(smbios_decode(buf, dumpfile, pydata)) found++;
- } else if (memcmp(buf, "_DMI_", 5)==0) {
- if(legacy_decode(buf, dumpfile, pydata)) found++;
- }
- } else ret = 1;
- } else { /* Read from /dev/mem */
- /* First try EFI (ia64, Intel-based Mac) */
- efi = address_from_efi(&fp);
- if(efi == EFI_NOT_FOUND) {
- /* Fallback to memory scan (x86, x86_64) */
- if((buf=mem_chunk(0xF0000, 0x10000, opt.devmem))!=NULL) {
- for(fp=0; fp<=0xFFF0; fp+=16) {
- if(memcmp(buf+fp, "_SM_", 4)==0 && fp<=0xFFE0) {
- if(smbios_decode(buf+fp, opt.devmem, pydata)) {
- found++;
- fp+=16;
- }
- } else if(memcmp(buf+fp, "_DMI_", 5)==0) {
- if(legacy_decode(buf+fp, opt.devmem, pydata)) found++;
- }
- }
- } else ret = 1;
- } else if(efi == EFI_NO_SMBIOS) {
- ret = 1;
- } else {
- if((buf=mem_chunk(fp, 0x20, opt.devmem))==NULL) ret = 1;
- else if(smbios_decode(buf, opt.devmem, pydata)) found++;
- //. TODO: dmiSetItem(pydata, "efi_address", efiAddress);
- }
- }
-
- free(opt.type);
- if(ret==0) {
- free(buf);
- } else {
- Py_DECREF(pydata);
- pydata = NULL;
- }
-
- //muntrace();
- return pydata;
+ // Go through all TypeMap's belonging to this Mapping section
+ foreach_xmlnode(dmixml_FindNode(group_n, "TypeMap"), group_n) {
+ char *typeid = dmixml_GetAttrValue(group_n, "id");
+
+ if( group_n->type != XML_ELEMENT_NODE ) {
+ continue;
+ }
+
+ // The children of <Mapping> tags must only be <TypeMap> 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(typeid);
+ if(opt->type == -1) {
+ PyReturnError(PyExc_RuntimeError, "Invalid type id '%s'", typeid);
+ }
+
+ // 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");
+ }
+ }
+#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_bios(PyObject *self, PyObject *args) { return dmidecode_get(self, "bios"); }
-static PyObject* dmidecode_get_system(PyObject *self, PyObject *args) { return dmidecode_get(self, "system"); }
-static PyObject* dmidecode_get_baseboard(PyObject *self, PyObject *args) { return dmidecode_get(self, "baseboard"); }
-static PyObject* dmidecode_get_chassis(PyObject *self, PyObject *args) { return dmidecode_get(self, "chassis"); }
-static PyObject* dmidecode_get_processor(PyObject *self, PyObject *args) { return dmidecode_get(self, "processor"); }
-static PyObject* dmidecode_get_memory(PyObject *self, PyObject *args) { return dmidecode_get(self, "memory"); }
-static PyObject* dmidecode_get_cache(PyObject *self, PyObject *args) { return dmidecode_get(self, "cache"); }
-static PyObject* dmidecode_get_connector(PyObject *self, PyObject *args) { return dmidecode_get(self, "connector"); }
-static PyObject* dmidecode_get_slot(PyObject *self, PyObject *args) { return dmidecode_get(self, "slot"); }
-static PyObject* dmidecode_get_type(PyObject *self, PyObject *args) {
- long unsigned int lu;
- if(PyArg_ParseTuple(args, (char *)"i", &lu)) {
- if(lu < 256) {
- char s[8];
- sprintf(s, "%lu", lu);
- return dmidecode_get(self, s);
- }
- return Py_False;
- }
- return Py_None;
+static PyObject *dmidecode_get_group(options *opt, const char *section)
+{
+ PyObject *pydata = NULL;
+ xmlNode *dmixml_n = NULL;
+ ptzMAP *mapping = NULL;
+
+ /* Set default option values */
+ if( opt->devmem == NULL ) {
+ opt->devmem = DEFAULT_MEM_DEV;
+ }
+ opt->flags = 0;
+
+ // Decode the dmidata into an XML node
+ dmixml_n = __dmidecode_xml_getsection(opt, section);
+ if( dmixml_n == NULL ) {
+ // Exception already set
+ return NULL;
+ }
+
+ // Convert the retrieved XML nodes to a Python dictionary
+ mapping = dmiMAP_ParseMappingXML_GroupName(opt->mappingxml, section);
+ if( mapping == NULL ) {
+ // Exception already set
+ xmlFreeNode(dmixml_n);
+ return NULL;
+ }
+
+ // Generate Python dict out of XML node
+ pydata = pythonizeXMLnode(mapping, dmixml_n);
+
+ // Clean up and return the resulting Python dictionary
+ ptzmap_Free(mapping);
+ xmlFreeNode(dmixml_n);
+
+ return pydata;
}
-static PyObject* dmidecode_dump(PyObject *self, PyObject *null) {
- const char *f;
- f = opt.dumpfile ? PyString_AsString(opt.dumpfile) : opt.devmem;
- struct stat _buf;
- stat(f, &_buf);
- if((access(f, F_OK) != 0) || ((access(f, W_OK) == 0) && S_ISREG(_buf.st_mode)))
- if(dump(PyString_AS_STRING(opt.dumpfile)))
- Py_RETURN_TRUE;
- Py_RETURN_FALSE;
+xmlNode *__dmidecode_xml_gettypeid(options *opt, int typeid)
+{
+ xmlNode *dmixml_n = NULL;
+
+ /* Set default option values */
+ if( opt->devmem == NULL ) {
+ opt->devmem = DEFAULT_MEM_DEV;
+ }
+ opt->flags = 0;
+
+ 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));
+ }
+
+ // Fetch the Mapping XML file
+ if( load_mappingxml(opt) == NULL) {
+ return NULL;
+ }
+
+ // Parse the DMI data and put the result into dmixml_n node chain.
+ opt->type = typeid;
+ if( dmidecode_get_xml(opt, dmixml_n) != 0 ) {
+ PyReturnError(PyExc_RuntimeError, "Error decoding DMI data");
+ }
+
+ return dmixml_n;
}
-static PyObject* dmidecode_get_dev(PyObject *self, PyObject *null) {
- PyObject *dev;
- if(opt.dumpfile != NULL) dev = opt.dumpfile;
- else dev = PyString_FromString(opt.devmem);
- Py_INCREF(dev);
- return dev;
+
+static PyObject *dmidecode_get_typeid(options *opt, int typeid)
+{
+ PyObject *pydata = NULL;
+ xmlNode *dmixml_n = NULL;
+ ptzMAP *mapping = NULL;
+
+ dmixml_n = __dmidecode_xml_gettypeid(opt, typeid);
+ if( dmixml_n == NULL ) {
+ // Exception already set
+ return NULL;
+ }
+
+ // Convert the retrieved XML nodes to a Python dictionary
+ mapping = dmiMAP_ParseMappingXML_TypeID(opt->mappingxml, opt->type);
+ if( mapping == NULL ) {
+ // FIXME: Should we raise an exception here?
+ // Now it passes the unit-test
+ return PyDict_New();
+ }
+
+ // Generate Python dict out of XML node
+ pydata = pythonizeXMLnode(mapping, dmixml_n);
+
+ // Clean up and return the resulting Python dictionary
+ ptzmap_Free(mapping);
+ xmlFreeNode(dmixml_n);
+
+ return pydata;
}
-static PyObject* dmidecode_set_dev(PyObject *self, PyObject *arg) {
- if(PyString_Check(arg)) {
- if(opt.dumpfile == arg) Py_RETURN_TRUE;
- struct stat buf;
- char *f = PyString_AsString(arg);
- stat(f, &buf);
- if(opt.dumpfile) { Py_DECREF(opt.dumpfile); }
+// This global variable should only be available for the "first-entry" functions
+// which is defined in PyMethodDef DMIDataMethods[].
+options *global_options = NULL;
- if(S_ISCHR(buf.st_mode)) {
- if(memcmp(PyString_AsString(arg), "/dev/mem", 8)==0) {
- opt.dumpfile = NULL;
- Py_RETURN_TRUE;
- } else {
+static PyObject *dmidecode_get_bios(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "bios");
+}
+static PyObject *dmidecode_get_system(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "system");
+}
+static PyObject *dmidecode_get_baseboard(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "baseboard");
+}
+static PyObject *dmidecode_get_chassis(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "chassis");
+}
+static PyObject *dmidecode_get_processor(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "processor");
+}
+static PyObject *dmidecode_get_memory(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "memory");
+}
+static PyObject *dmidecode_get_cache(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "cache");
+}
+static PyObject *dmidecode_get_connector(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "connector");
+}
+static PyObject *dmidecode_get_slot(PyObject * self, PyObject * args)
+{
+ return dmidecode_get_group(global_options, "slot");
+}
+
+static PyObject *dmidecode_get_section(PyObject *self, PyObject *args)
+{
+ char *section = PyString_AsString(args);
+
+ if( section != NULL ) {
+ return dmidecode_get_group(global_options, section);
+ }
+ PyReturnError(PyExc_RuntimeError, "No section name was given");
+}
+
+static PyObject *dmidecode_get_type(PyObject * self, PyObject * args)
+{
+ int typeid;
+ PyObject *pydata = NULL;
+
+ if( PyArg_ParseTuple(args, (char *)"i", &typeid) ) {
+ if( (typeid < 0) || (typeid > 255) ) {
+ Py_RETURN_FALSE;
+ // FIXME: Should send exception instead
+ // PyReturnError(PyExc_RuntimeError, "Types are bound between 0 and 255 (inclusive)."
+ // "Type value used was '%i'", typeid);
+ }
+ } else {
+ PyReturnError(PyExc_RuntimeError, "Type '%i' is not a valid type identifier%c", typeid);
+ }
+
+ pydata = dmidecode_get_typeid(global_options, typeid);
+ return pydata;
+}
+
+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;
+
+ // Parse the keywords - we only support keywords, as this is an internal API
+ if( !PyArg_ParseTupleAndKeywords(args, keywds, "ss|si", keywordlist,
+ &qtype, &rtype, &sect_query, &type_query) ) {
+ 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;
+
+ default:
+ PyReturnError(PyExc_TypeError, "Internal error - invalid query type '%c'", *qtype);
+ }
+
+ // Check if we got any data
+ if( dmixml_n == NULL ) {
+ // Exception already set
+ 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;
+
+ 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;
+
+ default:
+ PyReturnError(PyExc_TypeError, "Internal error - invalid result type '%c'", *rtype);
+ }
+
+ // Return XML data
+ Py_INCREF(pydata);
+ return pydata;
+}
+
+
+
+static PyObject *dmidecode_dump(PyObject * self, PyObject * null)
+{
+ const char *f;
+ struct stat _buf;
+
+ f = (global_options->dumpfile ? global_options->dumpfile : global_options->devmem);
+ stat(f, &_buf);
+
+ if( (access(f, F_OK) != 0) || ((access(f, W_OK) == 0) && S_ISREG(_buf.st_mode)) ) {
+ if( dump(DEFAULT_MEM_DEV, f) ) {
+ Py_RETURN_TRUE;
+ }
+ }
Py_RETURN_FALSE;
- }
- } else if(!S_ISDIR(buf.st_mode)) {
- opt.dumpfile = arg;
- Py_INCREF(opt.dumpfile);
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- //PyErr_Occurred();
}
-/*
-typedef struct {
- PyObject_HEAD char *version;
-} ivars;
+static PyObject *dmidecode_get_dev(PyObject * self, PyObject * null)
+{
+ PyObject *dev = NULL;
+ dev = PyString_FromString((global_options->dumpfile != NULL
+ ? global_options->dumpfile : global_options->devmem));
+ Py_INCREF(dev);
+ return dev;
+}
+
+static PyObject *dmidecode_set_dev(PyObject * self, PyObject * arg)
+{
+ if(PyString_Check(arg)) {
+ struct stat buf;
+ char *f = PyString_AsString(arg);
+
+ if( (f != NULL) && (global_options->dumpfile != NULL )
+ && (strcmp(global_options->dumpfile, f) == 0) ) {
+ Py_RETURN_TRUE;
+ }
+
+ stat(f, &buf);
+ if(S_ISCHR(buf.st_mode)) {
+ if(memcmp(PyString_AsString(arg), "/dev/mem", 8) == 0) {
+ if( global_options->dumpfile != NULL ) {
+ free(global_options->dumpfile);
+ global_options->dumpfile = NULL;
+ }
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+ } else if(!S_ISDIR(buf.st_mode)) {
+ global_options->dumpfile = strdup(f);
+ Py_RETURN_TRUE;
+ }
+ }
+ Py_RETURN_FALSE;
+}
+
+static PyObject *dmidecode_set_pythonxmlmap(PyObject * self, PyObject * arg)
+{
+ if(PyString_Check(arg)) {
+ struct stat fileinfo;
+ char *fname = PyString_AsString(arg);
+
+ memset(&fileinfo, 0, sizeof(struct stat));
+
+ if( stat(fname, &fileinfo) != 0 ) {
+ PyReturnError(PyExc_IOError, "Could not access the file '%s'", fname);
+ }
+
+ free(global_options->python_xml_map);
+ global_options->python_xml_map = strdup(fname);
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
-static PyMemberDef DMIDataMembers[] = {
- { (char *)"fred", T_STRING, offsetof(ivars, version), 0, "2.10" },
- { NULL }
-};
-*/
static PyMethodDef DMIDataMethods[] = {
- { (char *)"dump", dmidecode_dump, METH_NOARGS, (char *)"Dump dmidata to set file" },
- { (char *)"get_dev", dmidecode_get_dev, METH_NOARGS, (char *)"Get an alternative memory device file" },
- { (char *)"set_dev", dmidecode_set_dev, METH_O, (char *)"Set an alternative memory device file" },
-
- { (char *)"bios", dmidecode_get_bios, METH_VARARGS, (char *)"BIOS Data" },
- { (char *)"system", dmidecode_get_system, METH_VARARGS, (char *)"System Data" },
- { (char *)"baseboard", dmidecode_get_baseboard, METH_VARARGS, (char *)"Baseboard Data" },
- { (char *)"chassis", dmidecode_get_chassis, METH_VARARGS, (char *)"Chassis Data" },
- { (char *)"processor", dmidecode_get_processor, METH_VARARGS, (char *)"Processor Data" },
- { (char *)"memory", dmidecode_get_memory, METH_VARARGS, (char *)"Memory Data" },
- { (char *)"cache", dmidecode_get_cache, METH_VARARGS, (char *)"Cache Data" },
- { (char *)"connector", dmidecode_get_connector, METH_VARARGS, (char *)"Connector Data" },
- { (char *)"slot", dmidecode_get_slot, METH_VARARGS, (char *)"Slot Data" },
-
- { (char *)"type", dmidecode_get_type, METH_VARARGS, (char *)"By Type" },
-
- { NULL, NULL, 0, NULL }
+ {(char *)"dump", dmidecode_dump, METH_NOARGS, (char *)"Dump dmidata to set file"},
+ {(char *)"get_dev", dmidecode_get_dev, METH_NOARGS,
+ (char *)"Get an alternative memory device file"},
+ {(char *)"set_dev", dmidecode_set_dev, METH_O,
+ (char *)"Set an alternative memory device file"},
+
+ {(char *)"bios", dmidecode_get_bios, METH_VARARGS, (char *)"BIOS Data"},
+ {(char *)"system", dmidecode_get_system, METH_VARARGS, (char *)"System Data"},
+ {(char *)"baseboard", dmidecode_get_baseboard, METH_VARARGS, (char *)"Baseboard Data"},
+ {(char *)"chassis", dmidecode_get_chassis, METH_VARARGS, (char *)"Chassis Data"},
+ {(char *)"processor", dmidecode_get_processor, METH_VARARGS, (char *)"Processor Data"},
+ {(char *)"memory", dmidecode_get_memory, METH_VARARGS, (char *)"Memory Data"},
+ {(char *)"cache", dmidecode_get_cache, METH_VARARGS, (char *)"Cache Data"},
+ {(char *)"connector", dmidecode_get_connector, METH_VARARGS, (char *)"Connector Data"},
+ {(char *)"slot", dmidecode_get_slot, METH_VARARGS, (char *)"Slot Data"},
+
+ {(char *)"QuerySection", dmidecode_get_section, METH_O,
+ (char *) "Queries the DMI data structure for a given section name. A section"
+ "can often contain several DMI type elements"
+ },
+
+ {(char *)"type", dmidecode_get_type, METH_VARARGS, (char *)"By Type"},
+
+ {(char *)"QueryTypeId", dmidecode_get_type, METH_VARARGS,
+ (char *) "Queries the DMI data structure for a specific DMI type."
+ },
+
+ {(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_KEYWORDS,
+ (char *) "Internal API for retrieving data as raw XML data"},
+
+ {NULL, NULL, 0, NULL}
};
-PyMODINIT_FUNC initdmidecode(void) {
- init();
+void destruct_options(void *ptr)
+{
+ options *opt = (options *) ptr;
+
+ if( 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;
+ }
+
+ if( opt->dmiversion_n != NULL ) {
+ xmlFreeNode(opt->dmiversion_n);
+ opt->dmiversion_n = NULL;
+ }
+
+ if( opt->dumpfile != NULL ) {
+ free(opt->dumpfile);
+ opt->dumpfile = NULL;
+ }
+
+ free(ptr);
+}
+
+
+PyMODINIT_FUNC initdmidecodemod(void)
+{
+ char *dmiver = NULL;
+ PyObject *module = NULL;
+ PyObject *version = NULL;
+ options *opt;
+
+ xmlInitParser();
+ xmlXPathInit();
+
+ opt = (options *) malloc(sizeof(options)+2);
+ memset(opt, 0, sizeof(options)+2);
+ init(opt);
+ module = Py_InitModule3((char *)"dmidecodemod", DMIDataMethods,
+ "Python extension module for dmidecode");
- PyObject *module = Py_InitModule3((char *)"dmidecode", DMIDataMethods, "Python extension module for dmidecode");
+ version = PyString_FromString(VERSION);
+ Py_INCREF(version);
+ PyModule_AddObject(module, "version", version);
- PyObject *version = PyString_FromString("2.10");
- Py_INCREF(version);
- PyModule_AddObject(module, "version", version);
+ opt->dmiversion_n = dmidecode_get_version(opt);
+ dmiver = dmixml_GetContent(opt->dmiversion_n);
+ PyModule_AddObject(module, "dmi", dmiver ? PyString_FromString(dmiver) : Py_None);
- PyObject *dmi_version = NULL;
- dmidecode_set_version(&dmi_version);
- PyModule_AddObject(module, "dmi", dmi_version?dmi_version:Py_None);
+ // Assign this options struct to the module as well with a destructor, that way it will
+ // clean up the memory for us.
+ PyModule_AddObject(module, "options", PyCObject_FromVoidPtr(opt, destruct_options));
+ global_options = opt;
}