/* 'top'-like tool for libvirt domains. (C) Copyright 2007-2021 Richard W.M. Jones, Red Hat Inc. http://libvirt.org/ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include /* xpathobj contains a list of dev attributes, return the list * as an OCaml array of strings. */ static value get_devs (xmlDocPtr doc, xmlXPathObjectPtr xpathobj) { CAMLparam0 (); CAMLlocal2 (rv, nodev); const xmlNodeSetPtr nodes = xpathobj->nodesetval; size_t i, nr_nodes; xmlNodePtr node; char *str; xmlAttrPtr attr; if (nodes == NULL || nodes->nodeNr == 0) rv = caml_alloc (0, 0); else { /* Count the nodes that contain data. */ nr_nodes = 0; for (i = 0; i < nodes->nodeNr; ++i) { node = nodes->nodeTab[i]; if (node->type != XML_ATTRIBUTE_NODE) continue; nr_nodes++; } rv = caml_alloc (nr_nodes, 0); nr_nodes = 0; for (i = 0; i < nodes->nodeNr; ++i) { node = nodes->nodeTab[i]; if (node->type != XML_ATTRIBUTE_NODE) continue; attr = (xmlAttrPtr) node; str = (char *) xmlNodeListGetString (doc, attr->children, 1); nodev = caml_copy_string (str); free (str); Store_field (rv, nr_nodes, nodev); nr_nodes++; } } CAMLreturn (rv); } /* external get_blk_net_devs : string -> string array * string array */ value get_blk_net_devs (value xmlv) { CAMLparam1 (xmlv); CAMLlocal3 (rv, blkdevs, netifs); xmlDocPtr doc; xmlXPathContextPtr xpathctx; xmlXPathObjectPtr xpathobj; const char *expr; /* For security reasons, call xmlReadMemory (not xmlParseMemory) and * pass XML_PARSE_NONET. */ doc = xmlReadMemory (String_val (xmlv), caml_string_length (xmlv), NULL, NULL, XML_PARSE_NONET); if (doc == NULL) caml_invalid_argument ("xmlReadMemory: unable to parse XML"); xpathctx = xmlXPathNewContext (doc); if (xpathctx == NULL) caml_invalid_argument ("xmlXPathNewContext: unable to create new context"); expr = "//devices/disk/target/@dev"; xpathobj = xmlXPathEvalExpression (BAD_CAST expr, xpathctx); if (xpathobj == NULL) caml_invalid_argument (expr); blkdevs = get_devs (doc, xpathobj); xmlXPathFreeObject (xpathobj); expr = "//devices/interface/target/@dev"; xpathobj = xmlXPathEvalExpression (BAD_CAST expr, xpathctx); if (xpathobj == NULL) caml_invalid_argument (expr); netifs = get_devs (doc, xpathobj); xmlXPathFreeObject (xpathobj); xmlXPathFreeContext (xpathctx); xmlFreeDoc (doc); rv = caml_alloc (2, 0); Store_field (rv, 0, blkdevs); Store_field (rv, 1, netifs); CAMLreturn (rv); }