Refactor the XPath lookup to use the internal helper. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- tools/virsh-domain.c | 93 ++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 55 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 9baab2672a..2fb1751f25 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -3133,18 +3133,17 @@ cmdDomIfSetLink(vshControl *ctl, const vshCmd *cmd) g_autoptr(virshDomain) dom = NULL; const char *iface; const char *state; - virMacAddr macaddr; - const char *element; - const char *attr; - bool config; unsigned int flags = 0; unsigned int xmlflags = 0; size_t i; g_autoptr(xmlDoc) xml = NULL; g_autoptr(xmlXPathContext) ctxt = NULL; - g_autoptr(xmlXPathObject) obj = NULL; - xmlNodePtr cur = NULL; g_autofree char *xml_buf = NULL; + g_autofree xmlNodePtr *nodes = NULL; + ssize_t nnodes; + xmlNodePtr ifaceNode = NULL; + xmlNodePtr linkNode = NULL; + xmlAttrPtr stateAttr; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; @@ -3153,14 +3152,12 @@ cmdDomIfSetLink(vshControl *ctl, const vshCmd *cmd) vshCommandOptStringReq(ctl, cmd, "state", &state) < 0) return false; - config = vshCommandOptBool(cmd, "config"); - if (STRNEQ(state, "up") && STRNEQ(state, "down")) { vshError(ctl, _("invalid link state '%s'"), state); return false; } - if (config) { + if (vshCommandOptBool(cmd, "config")) { flags = VIR_DOMAIN_AFFECT_CONFIG; xmlflags |= VIR_DOMAIN_XML_INACTIVE; } else { @@ -3173,70 +3170,56 @@ cmdDomIfSetLink(vshControl *ctl, const vshCmd *cmd) if (virshDomainGetXMLFromDom(ctl, dom, xmlflags, &xml, &ctxt) < 0) return false; - obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt); - if (obj == NULL || obj->type != XPATH_NODESET || - obj->nodesetval == NULL || obj->nodesetval->nodeNr == 0) { + if ((nnodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes)) <= 0) { vshError(ctl, _("Failed to extract interface information or no interfaces found")); return false; } - if (virMacAddrParse(iface, &macaddr) == 0) { - element = "mac"; - attr = "address"; - } else { - element = "target"; - attr = "dev"; - } + for (i = 0; i < nnodes; i++) { + g_autofree char *macaddr = NULL; + g_autofree char *target = NULL; - /* find interface with matching mac addr */ - for (i = 0; i < obj->nodesetval->nodeNr; i++) { - cur = obj->nodesetval->nodeTab[i]->children; + ctxt->node = nodes[i]; - while (cur) { - if (cur->type == XML_ELEMENT_NODE && - virXMLNodeNameEqual(cur, element)) { - g_autofree char *value = virXMLPropString(cur, attr); + if ((macaddr = virXPathString("string(./mac/@address)", ctxt)) && + STRCASEEQ(macaddr, iface)) { + ifaceNode = nodes[i]; + break; + } - if (STRCASEEQ(value, iface)) - goto hit; - } - cur = cur->next; + if ((target = virXPathString("string(./target/@dev)", ctxt)) && + STRCASEEQ(target, iface)) { + ifaceNode = nodes[i]; + break; } } - vshError(ctl, _("interface (%s: %s) not found"), element, iface); - return false; - - hit: - /* find and modify/add link state node */ - /* try to find <link> element */ - cur = obj->nodesetval->nodeTab[i]->children; + if (!ifaceNode) { + vshError(ctl, _("interface '%s' not found"), iface); + return false; + } - while (cur) { - if (cur->type == XML_ELEMENT_NODE && - virXMLNodeNameEqual(cur, "link")) { - /* found, just modify the property */ - xmlSetProp(cur, BAD_CAST "state", BAD_CAST state); + ctxt->node = ifaceNode; - break; + /* try to find <link> element or create new one */ + if (!(linkNode = virXPathNode("./link", ctxt))) { + if (!(linkNode = xmlNewChild(ifaceNode, NULL, BAD_CAST "link", NULL))) { + vshError(ctl, _("failed to create XML node")); + return false; } - cur = cur->next; } - if (!cur) { - /* element <link> not found, add one */ - cur = xmlNewChild(obj->nodesetval->nodeTab[i], - NULL, - BAD_CAST "link", - NULL); - if (!cur) - return false; + if (xmlHasProp(linkNode, BAD_CAST "link")) + stateAttr = xmlSetProp(linkNode, BAD_CAST "state", BAD_CAST state); + else + stateAttr = xmlNewProp(linkNode, BAD_CAST "state", BAD_CAST state); - if (xmlNewProp(cur, BAD_CAST "state", BAD_CAST state) == NULL) - return false; + if (!stateAttr) { + vshError(ctl, _("Failed to create or modify the state XML attribute")); + return false; } - if (!(xml_buf = virXMLNodeToString(xml, obj->nodesetval->nodeTab[i]))) { + if (!(xml_buf = virXMLNodeToString(xml, ifaceNode))) { vshSaveLibvirtError(); vshError(ctl, _("Failed to create XML")); return false; -- 2.38.1