[libvirt] [libvirt-php][PATCH 0/8] Couple of mem leak fixes

So, after I reviewed [1] I realized how big memory leaks we have there... 1: https://www.redhat.com/archives/libvir-list/2015-September/msg01045.html Since there is nobody to review, I'm pushing this. Michal Privoznik (8): libvirt_network_get_information: Be more tolerant to missing info examples: Resolve some warnings examples: Rework a bit to resolve some warnings Don't free() in RECREATE_STRING_WITH_E LONGLONG_INIT: Reformat virConnectGetHostname: free returned value virDomainGetXMLDesc: Free returned value virNodeDeviceGetXMLDesc: Free returned value examples/index.php | 90 +++--- examples/libvirt.php | 44 +-- src/libvirt-php.c | 900 +++++++++++++++++++++++++-------------------------- 3 files changed, 504 insertions(+), 530 deletions(-) -- 2.4.9

This function is really build in a way that only NATed networks can pass the function. Any other networks (and there's plenty of them) will make it fail immediately. So while we are in PHP, we can utilize array_key_exist() function and thus just fill just those info that we know for now. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt-php.c | 96 ++++++++++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 51 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index e85443f..a532525 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -8644,15 +8644,20 @@ PHP_FUNCTION(libvirt_network_get_information) zval *znetwork; int retval = 0; char *xml = NULL; - char *tmp = NULL; - char *tmp2 = NULL; + char *name = NULL; + char *ipaddr = NULL; + char *netmask = NULL; + char *mode = NULL; + char *dev = NULL; + char *dhcp_start = NULL; + char *dhcp_end = NULL; char fixedtemp[32] = { 0 }; GET_NETWORK_FROM_ARGS("r",&znetwork); xml=virNetworkGetXMLDesc(network->network, 0); - if (xml==NULL) { + if (xml == NULL) { set_error_if_unset("Cannot get network XML" TSRMLS_CC); RETURN_FALSE; } @@ -8660,8 +8665,8 @@ PHP_FUNCTION(libvirt_network_get_information) array_init(return_value); /* Get name */ - tmp = get_string_from_xpath(xml, "//network/name", NULL, &retval); - if (tmp == NULL) { + name = get_string_from_xpath(xml, "//network/name", NULL, &retval); + if (name == NULL) { set_error("Invalid XPath node for network name" TSRMLS_CC); RETURN_FALSE; } @@ -8671,63 +8676,52 @@ PHP_FUNCTION(libvirt_network_get_information) RETURN_FALSE; } - add_assoc_string_ex(return_value, "name", 5, tmp, 1); + add_assoc_string_ex(return_value, "name", 5, name, 1); /* Get gateway IP address */ - tmp = get_string_from_xpath(xml, "//network/ip/@address", NULL, &retval); - if (tmp == NULL) { - set_error("Invalid XPath node for network gateway IP address" TSRMLS_CC); - RETURN_FALSE; - } - - if (retval < 0) { - set_error("Cannot get XPath expression result for network gateway IP address" TSRMLS_CC); - RETURN_FALSE; - } - - add_assoc_string_ex(return_value, "ip", 3, tmp, 1); + ipaddr = get_string_from_xpath(xml, "//network/ip/@address", NULL, &retval); + if (ipaddr && retval > 0) + add_assoc_string_ex(return_value, "ip", 3, ipaddr, 1); /* Get netmask */ - tmp2 = get_string_from_xpath(xml, "//network/ip/@netmask", NULL, &retval); - if (tmp2 == NULL) { - set_error("Invalid XPath node for network mask" TSRMLS_CC); - RETURN_FALSE; + netmask = get_string_from_xpath(xml, "//network/ip/@netmask", NULL, &retval); + if (netmask && retval > 0) { + int subnet_bits = get_subnet_bits(netmask); + add_assoc_string_ex(return_value, "netmask", 8, netmask, 1); + add_assoc_long(return_value, "netmask_bits", (long) subnet_bits); + + /* Format CIDR address representation */ + ipaddr[strlen(ipaddr) - 1] = ipaddr[strlen(ipaddr) - 1] - 1; + snprintf(fixedtemp, sizeof(fixedtemp), "%s/%d", ipaddr, subnet_bits); + add_assoc_string_ex(return_value, "ip_range", 9, fixedtemp, 1); } - if (retval < 0) { - set_error("Cannot get XPath expression result for network mask" TSRMLS_CC); - RETURN_FALSE; - } - - add_assoc_string_ex(return_value, "netmask", 8, tmp2, 1); - add_assoc_long(return_value, "netmask_bits", (long)get_subnet_bits(tmp2)); - - /* Format CIDR address representation */ - tmp[strlen(tmp) - 1] = tmp[strlen(tmp) - 1] - 1; - snprintf(fixedtemp, sizeof(fixedtemp), "%s/%d", tmp, get_subnet_bits(tmp2)); - add_assoc_string_ex(return_value, "ip_range", 9, fixedtemp, 1); + /* Get forwarding settings */ + mode = get_string_from_xpath(xml, "//network/forward/@mode", NULL, &retval); + if (mode && retval > 0) + add_assoc_string_ex(return_value, "forwarding", 11, mode, 1); /* Get forwarding settings */ - tmp = get_string_from_xpath(xml, "//network/forward/@mode", NULL, &retval); - if ((tmp == NULL) || (retval < 0)) - add_assoc_string_ex(return_value, "forwarding", 11, "None", 1); - else - add_assoc_string_ex(return_value, "forwarding", 11, tmp, 1); - - /* Get forwarding settings */ - tmp = get_string_from_xpath(xml, "//network/forward/@dev", NULL, &retval); - if ((tmp == NULL) || (retval < 0)) - add_assoc_string_ex(return_value, "forward_dev", 12, "any interface", 1); - else - add_assoc_string_ex(return_value, "forward_dev", 12, tmp, 1); + dev = get_string_from_xpath(xml, "//network/forward/@dev", NULL, &retval); + if (dev && retval > 0) + add_assoc_string_ex(return_value, "forward_dev", 12, dev, 1); /* Get DHCP values */ - tmp = get_string_from_xpath(xml, "//network/ip/dhcp/range/@start", NULL, &retval); - tmp2 = get_string_from_xpath(xml, "//network/ip/dhcp/range/@end", NULL, &retval); - if ((retval > 0) && (tmp != NULL) && (tmp2 != NULL)) { - add_assoc_string_ex(return_value, "dhcp_start", 11, tmp, 1); - add_assoc_string_ex(return_value, "dhcp_end", 9, tmp2, 1); + dhcp_start = get_string_from_xpath(xml, "//network/ip/dhcp/range/@start", NULL, &retval); + dhcp_end = get_string_from_xpath(xml, "//network/ip/dhcp/range/@end", NULL, &retval); + if (dhcp_start && dhcp_end && retval > 0) { + add_assoc_string_ex(return_value, "dhcp_start", 11, dhcp_start, 1); + add_assoc_string_ex(return_value, "dhcp_end", 9, dhcp_end, 1); } + + free(dhcp_end); + free(dhcp_start); + free(dev); + free(mode); + free(netmask); + free(ipaddr); + free(name); + free(xml); } /* -- 2.4.9

So, I have a couple of networks and while testing the examples I've noticed that there are some warnings being printed out: [Wed Sep 30 15:53:13 2015] PHP Notice: Undefined index: forward_dev in /home/zippy/work/libvirt/libvirt-php.git/examples/index.php on line 283 [Wed Sep 30 15:53:13 2015] PHP Notice: Undefined index: forward_dev in /home/zippy/work/libvirt/libvirt-php.git/examples/index.php on line 283 [Wed Sep 30 15:53:13 2015] PHP Notice: Undefined index: forward_dev in /home/zippy/work/libvirt/libvirt-php.git/examples/index.php on line 283 [Wed Sep 30 15:53:13 2015] PHP Notice: Undefined index: ip in /home/zippy/work/libvirt/libvirt-php.git/examples/index.php on line 303 [Wed Sep 30 15:53:13 2015] PHP Notice: Undefined index: ip_range in /home/zippy/work/libvirt/libvirt-php.git/examples/index.php on line 304 Make the code work with missing info Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- examples/index.php | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/examples/index.php b/examples/index.php index 874803d..94badb6 100644 --- a/examples/index.php +++ b/examples/index.php @@ -279,32 +279,43 @@ for ($i = 0; $i < sizeof($tmp); $i++) { $tmp2 = $lv->get_network_information($tmp[$i]); - if ($tmp2['forwarding'] != 'None') - $forward = $tmp2['forwarding'].' to '.$tmp2['forward_dev']; - else - $forward = 'None'; + $ip = ''; + $ip_range = ''; + $activity = $tmp2['active'] ? 'Active' : 'Inactive'; + $dhcp = 'Disabled'; + $forward = 'None'; + if (array_key_exists('forwarding', $tmp2) && $tmp2['forwarding'] != 'None') { + if (array_key_exists('forward_dev', $tmp2)) + $forward = $tmp2['forwarding'].' to '.$tmp2['forward_dev']; + else + $forward = $tmp2['forwarding']; + } + if (array_key_exists('dhcp_start', $tmp2) && array_key_exists('dhcp_end', $tmp2)) $dhcp = $tmp2['dhcp_start'].' - '.$tmp2['dhcp_end']; - else - $dhcp = 'Disabled'; - $activity = $tmp2['active'] ? 'Active' : 'Inactive'; - $act = !$tmp2['active'] ? "<a href=\"?action={$_GET['action']}&subaction=start&name={$tmp2['name']}\">Start network</a>" : - "<a href=\"?action={$_GET['action']}&subaction=stop&name={$tmp2['name']}\">Stop network</a>"; - $act .= " | <a href=\"?action={$_GET['action']}&subaction=dumpxml&name={$tmp2['name']}\">Dump network XML</a>"; - if (!$tmp2['active']) { - $act .= ' | <a href="?action='.$_GET['action'].'&subaction=edit&name='.$tmp2['name'].'">Edit network</a>'; - } + if (array_key_exists('ip', $tmp2)) + $ip = $tmp2['ip']; + + if (array_key_exists('ip_range', $tmp2)) + $ip_range = $tmp2['ip_range']; + + $act = "<a href=\"?action={$_GET['action']}&subaction=" . ($tmp2['active'] ? "stop" : "start"); + $act .= "&name=" . urlencode($tmp2['name']) . "\">"; + $act .= ($tmp2['active'] ? "Stop" : "Start") . " network</a>"; + $act .= " | <a href=\"?action={$_GET['action']}&subaction=dumpxml&name=" . urlencode($tmp2['name']) . "\">Dump network XML</a>"; + if (!$tmp2['active']) + $act .= ' | <a href="?action='.$_GET['action'].'&subaction=edit&name='. urlencode($tmp2['name']) . '">Edit network</a>'; echo "<tr> <td>$spaces{$tmp2['name']}$spaces</td> <td align=\"center\">$spaces$activity$spaces</td> - <td align=\"center\">$spaces{$tmp2['ip']}$spaces</td> - <td align=\"center\">$spaces{$tmp2['ip_range']}$spaces</td> + <td align=\"center\">$spaces$ip$spaces</td> + <td align=\"center\">$spaces$ip_range$spaces</td> <td align=\"center\">$spaces$forward$spaces</td> <td align=\"center\">$spaces$dhcp$spaces</td> <td align=\"center\">$spaces$act$spaces</td> - </tr>"; + </tr>"; } echo "</table>"; -- 2.4.9

Not only you should not use virDomain object as index to an array in PHP where only strings and integers are allowed, you should avoid mixing types passed to domain_get_info(). At some point a domain name is passed, then virDomain is passed ... Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- examples/index.php | 47 ++++++++++++++++++++++------------------------- examples/libvirt.php | 44 ++++++++------------------------------------ 2 files changed, 30 insertions(+), 61 deletions(-) diff --git a/examples/index.php b/examples/index.php index 94badb6..381baef 100644 --- a/examples/index.php +++ b/examples/index.php @@ -511,14 +511,14 @@ } } - $res = $lv->get_domain_object($domName); - $dom = $lv->domain_get_info($res); - $mem = number_format($dom['memory'] / 1024, 2, '.', ' ').' MB'; - $cpu = $dom['nrVirtCpu']; - $state = $lv->domain_state_translate($dom['state']); - $id = $lv->domain_get_id($res); - $arch = $lv->domain_get_arch($res); - $vnc = $lv->domain_get_vnc_port($res); + $dom = $lv->get_domain_object($domName); + $info = $lv->domain_get_info($dom); + $mem = number_format($info['memory'] / 1024, 2, '.', ' ').' MB'; + $cpu = $info['nrVirtCpu']; + $state = $lv->domain_state_translate($info['state']); + $id = $lv->domain_get_id($dom); + $arch = $lv->domain_get_arch($dom); + $vnc = $lv->domain_get_vnc_port($dom); if (!$id) $id = 'N/A'; @@ -662,7 +662,6 @@ } $doms = $lv->get_domains(); - $domkeys = array_keys($doms); echo "<table> <tr> <th>Name</th> @@ -682,23 +681,21 @@ echo " <th>Action</th> </tr>"; - $active = $tmp['active']; - for ($i = 0; $i < sizeof($doms); $i++) { - $name = $doms[$i]; - $res = $lv->get_domain_by_name($name); - $uuid = libvirt_domain_get_uuid_string($res); - $dom = $lv->domain_get_info($name); - $mem = number_format($dom['memory'] / 1024, 2, '.', ' ').' MB'; - $cpu = $dom['nrVirtCpu']; - $state = $lv->domain_state_translate($dom['state']); - $id = $lv->domain_get_id($res); - $arch = $lv->domain_get_arch($res); - $vnc = $lv->domain_get_vnc_port($res); - $nics = $lv->get_network_cards($res); - if (($diskcnt = $lv->get_disk_count($res)) > 0) { - $disks = $diskcnt.' / '.$lv->get_disk_capacity($res); - $diskdesc = 'Current physical size: '.$lv->get_disk_capacity($res, true); + foreach ($doms as $name) { + $dom = $lv->get_domain_object($name); + $uuid = libvirt_domain_get_uuid_string($dom); + $info = $lv->domain_get_info($dom); + $mem = number_format($info['memory'] / 1024, 2, '.', ' ').' MB'; + $cpu = $info['nrVirtCpu']; + $state = $lv->domain_state_translate($info['state']); + $id = $lv->domain_get_id($dom); + $arch = $lv->domain_get_arch($dom); + $vnc = $lv->domain_get_vnc_port($dom); + $nics = $lv->get_network_cards($dom); + if (($diskcnt = $lv->get_disk_count($dom)) > 0) { + $disks = $diskcnt.' / '.$lv->get_disk_capacity($dom); + $diskdesc = 'Current physical size: '.$lv->get_disk_capacity($dom, true); } else { $disks = '-'; diff --git a/examples/libvirt.php b/examples/libvirt.php index 21e11d2..cb1a0ad 100644 --- a/examples/libvirt.php +++ b/examples/libvirt.php @@ -767,44 +767,17 @@ return libvirt_domain_get_name($res); } - function domain_get_info_call($name = false, $name_override = false) { - $ret = array(); - - if ($name != false) { - $dom = $this->get_domain_object($name); - if (!$dom) - return false; - - if ($name_override) - $name = $name_override; - - $ret[$name] = libvirt_domain_get_info($dom); - return $ret; - } - else { - $doms = libvirt_list_domains($this->conn); - foreach ($doms as $dom) { - $tmp = $this->domain_get_name($dom); - $ret[$tmp] = libvirt_domain_get_info($dom); - } - } - - ksort($ret); - return $ret; - } - - function domain_get_info($name = false, $name_override = false) { + function domain_get_info($dom) { if (!$this->allow_cached) - return $this->domain_get_info_call($name, $name_override); + return libvirt_domain_get_info($dom); - $domname = $name_override ? $name_override : $name; - $domkey = $name_override ? $name_override : $this->domain_get_name($name); - if (!array_key_exists($domkey, $this->dominfos)) { - $tmp = $this->domain_get_info_call($name, $name_override); - $this->dominfos[$domkey] = $tmp[$domname]; + $domname = libvirt_domain_get_name($dom); + if (!array_key_exists($domname, $this->dominfos)) { + $info = libvirt_domain_get_info($dom); + $this->dominfos[$domname] = $info; } - return $this->dominfos[$domkey]; + return $this->dominfos[$domname]; } function get_last_error() { @@ -940,8 +913,7 @@ $dom = $this->get_domain_object($domain); if (!$dom) return false; - - $tmp = $this->domain_get_info( $domain, $name ); + $tmp = $this->domain_get_info($dom); if (!$tmp) return $this->_set_last_error(); $ret = ( ($tmp['state'] == VIR_DOMAIN_RUNNING) || ($tmp['state'] == VIR_DOMAIN_BLOCKED) ); -- 2.4.9

It's harder to track which variables were free()-d if the free() call is hidden in the macro. Moreover, since we don't have a wrapper over free() that will set the pointer to NULL, we may end up double freeing something. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt-php.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index a532525..5bff720 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -1530,10 +1530,9 @@ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, args, __VA_ARGS__) == FAILU ZEND_FETCH_RESOURCE(snapshot, php_libvirt_snapshot*, &zsnapshot, -1, PHP_LIBVIRT_SNAPSHOT_RES_NAME, le_libvirt_snapshot);\ if ((snapshot==NULL) || (snapshot->snapshot==NULL)) RETURN_FALSE;\ -/* Macro to "recreate" string with emalloc and free the original one */ +/* Macro to "recreate" string with emalloc */ #define RECREATE_STRING_WITH_E(str_out, str_in) \ - str_out = estrndup(str_in, strlen(str_in)); \ -free(str_in); \ + str_out = estrdup(str_in); #define LONGLONG_INIT \ char tmpnumber[64]; @@ -2225,6 +2224,7 @@ PHP_FUNCTION(libvirt_connect_get_uri) if (uri == NULL) RETURN_FALSE; RECREATE_STRING_WITH_E(uri_out, uri); + free(uri); RETURN_STRING(uri_out, 0); } @@ -2249,7 +2249,7 @@ PHP_FUNCTION(libvirt_connect_get_hostname) if (hostname==NULL) RETURN_FALSE; RECREATE_STRING_WITH_E(hostname_out,hostname); - + free(hostname); RETURN_STRING(hostname_out,0); } @@ -2557,7 +2557,7 @@ PHP_FUNCTION(libvirt_connect_get_sysinfo) if (sysinfo==NULL) RETURN_FALSE; RECREATE_STRING_WITH_E(sysinfo_out, sysinfo); - + free(sysinfo); RETURN_STRING(sysinfo_out,0); } @@ -4491,6 +4491,9 @@ PHP_FUNCTION(libvirt_connect_get_capabilities) RECREATE_STRING_WITH_E (caps_out, tmp); } + free(caps); + free(tmp); + RETURN_STRING(caps_out,0); } @@ -4523,7 +4526,7 @@ PHP_FUNCTION(libvirt_connect_get_emulator) } RECREATE_STRING_WITH_E(emulator, tmp); - + free(tmp); RETURN_STRING(emulator, 0); } @@ -4993,6 +4996,9 @@ PHP_FUNCTION(libvirt_domain_get_xml_desc) RECREATE_STRING_WITH_E (xml_out, tmp); } + free(tmp); + free(xml); + RETURN_STRING(xml_out,0); } @@ -6726,7 +6732,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_get_xml) if (xml==NULL) RETURN_FALSE; RECREATE_STRING_WITH_E(xml_out,xml); - + free(xml); RETURN_STRING(xml_out,0); } @@ -7130,6 +7136,9 @@ PHP_FUNCTION(libvirt_storagevolume_get_xml_desc) RECREATE_STRING_WITH_E(xml_out, tmp); } + free(xml); + free(tmp); + RETURN_STRING(xml_out,0); } @@ -7474,6 +7483,9 @@ PHP_FUNCTION(libvirt_storagepool_get_xml_desc) RECREATE_STRING_WITH_E (xml_out, tmp); } + free(xml); + free(tmp); + RETURN_STRING (xml_out, 0); } @@ -8361,6 +8373,9 @@ PHP_FUNCTION(libvirt_nodedev_get_xml_desc) RECREATE_STRING_WITH_E (xml_out, tmp); } + free(xml); + free(tmp); + RETURN_STRING(xml_out, 0); } @@ -8808,6 +8823,9 @@ PHP_FUNCTION(libvirt_network_get_xml_desc) RECREATE_STRING_WITH_E (xml_out, tmp); } + free(xml); + free(tmp); + RETURN_STRING(xml_out, 0); } -- 2.4.9

This is purely just to fulfil my OCD, so that the code can be formatted better. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt-php.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index 5bff720..4d0785a 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -1535,7 +1535,7 @@ if ((snapshot==NULL) || (snapshot->snapshot==NULL)) RETURN_FALSE;\ str_out = estrdup(str_in); #define LONGLONG_INIT \ - char tmpnumber[64]; + char tmpnumber[64] #define LONGLONG_ASSOC(out,key,in) \ if (LIBVIRT_G(longlong_to_string_ini)) { \ @@ -6060,8 +6060,8 @@ PHP_FUNCTION(libvirt_domain_memory_stats) DPRINTF("%s: virDomainMemoryStats(%p...) returned %d\n", PHPFUNC, domain->domain, retval); if (retval == -1) RETURN_FALSE; - LONGLONG_INIT - array_init(return_value); + LONGLONG_INIT; + array_init(return_value); for (i=0;i<retval;i++) { LONGLONG_INDEX(return_value, stats[i].tag,stats[i].val) @@ -6121,8 +6121,8 @@ PHP_FUNCTION(libvirt_domain_block_stats) if (retval == -1) RETURN_FALSE; array_init(return_value); - LONGLONG_INIT - LONGLONG_ASSOC(return_value, "rd_req", stats.rd_req); + LONGLONG_INIT; + LONGLONG_ASSOC(return_value, "rd_req", stats.rd_req); LONGLONG_ASSOC(return_value, "rd_bytes", stats.rd_bytes); LONGLONG_ASSOC(return_value, "wr_req", stats.wr_req); LONGLONG_ASSOC(return_value, "wr_bytes", stats.wr_bytes); @@ -6328,8 +6328,8 @@ PHP_FUNCTION(libvirt_domain_get_block_info) } array_init(return_value); - LONGLONG_INIT - add_assoc_string_ex(return_value, "device", 7, dev, 1); + LONGLONG_INIT; + add_assoc_string_ex(return_value, "device", 7, dev, 1); if (isFile) add_assoc_string_ex(return_value, "file", 5, tmp, 1); @@ -6412,8 +6412,8 @@ PHP_FUNCTION(libvirt_domain_interface_stats) if (retval == -1) RETURN_FALSE; array_init(return_value); - LONGLONG_INIT - LONGLONG_ASSOC(return_value, "rx_bytes", stats.rx_bytes); + LONGLONG_INIT; + LONGLONG_ASSOC(return_value, "rx_bytes", stats.rx_bytes); LONGLONG_ASSOC(return_value, "rx_packets", stats.rx_packets); LONGLONG_ASSOC(return_value, "rx_errs", stats.rx_errs); LONGLONG_ASSOC(return_value, "rx_drop", stats.rx_drop); @@ -6608,8 +6608,8 @@ PHP_FUNCTION(libvirt_domain_get_job_info) if (retval == -1) RETURN_FALSE; array_init(return_value); - LONGLONG_INIT - add_assoc_long(return_value, "type", jobinfo.type); + LONGLONG_INIT; + add_assoc_long(return_value, "type", jobinfo.type); LONGLONG_ASSOC(return_value, "time_elapsed", jobinfo.timeElapsed); LONGLONG_ASSOC(return_value, "time_remaining", jobinfo.timeRemaining); LONGLONG_ASSOC(return_value, "data_total", jobinfo.dataTotal); @@ -6949,8 +6949,8 @@ PHP_FUNCTION(libvirt_storagepool_get_info) array_init(return_value); // @todo: fix the long long returns - LONGLONG_INIT - add_assoc_long(return_value, "state", (long)poolInfo.state); + LONGLONG_INIT; + add_assoc_long(return_value, "state", (long)poolInfo.state); LONGLONG_ASSOC(return_value, "capacity", poolInfo.capacity); LONGLONG_ASSOC(return_value, "allocation", poolInfo.allocation); LONGLONG_ASSOC(return_value, "available", poolInfo.available); @@ -7091,8 +7091,8 @@ PHP_FUNCTION(libvirt_storagevolume_get_info) if (retval != 0) RETURN_FALSE; array_init(return_value); - LONGLONG_INIT - add_assoc_long(return_value, "type", (long)volumeInfo.type); + LONGLONG_INIT; + add_assoc_long(return_value, "type", (long)volumeInfo.type); LONGLONG_ASSOC(return_value, "capacity", volumeInfo.capacity); LONGLONG_ASSOC(return_value, "allocation", volumeInfo.allocation); } -- 2.4.9

It's caller responsibility to free the returned value when no longer needed. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt-php.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index 4d0785a..36cb8b9 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -946,12 +946,15 @@ unsigned long long size_def_to_mbytes(char *arg) int is_local_connection(virConnectPtr conn) { #ifndef EXTWIN + int ret; char *hostname; char name[1024]; hostname=virConnectGetHostname(conn); gethostname(name, 1024); - return (strcmp(name, hostname) == 0); + ret = strcmp(name, hostname) == 0; + free(hostname); + return ret; #else // Libvirt daemon doesn't work on Windows systems so always return 0 (FALSE) return 0; @@ -2145,8 +2148,10 @@ PHP_FUNCTION(libvirt_connect_get_information) DPRINTF("%s: Got connection URI of %s...\n", PHPFUNC, tmp); array_init(return_value); add_assoc_string_ex(return_value, "uri", 4, tmp ? tmp : "unknown", 1); + free(tmp); tmp = virConnectGetHostname(conn->conn); add_assoc_string_ex(return_value, "hostname", 9, tmp ? tmp : "unknown", 1); + free(tmp); if ((virConnectGetVersion(conn->conn, &hvVer) == 0) && (type = virConnectGetType(conn->conn))) { @@ -2360,8 +2365,10 @@ PHP_FUNCTION(libvirt_image_remove) if (strcmp(name, hostname) != 0) { snprintf(msg, sizeof(msg), "%s works only on local systems!", PHPFUNC); set_error(msg TSRMLS_CC); + free(hostname); RETURN_FALSE; } + free(hostname); if (unlink(image) != 0) { snprintf(msg, sizeof(msg), "An error occured while unlinking %s: %d (%s)", image, errno, strerror(errno)); -- 2.4.9

It's caller responsibility to free the returned value when no longer needed. Moreover, some functions are rewritten so that they use the fancy APIs we have (e.g. virDomainAttachDeviceFlags instead of dumping domain XML, appending new disk there and defining again). Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt-php.c | 694 +++++++++++++++++++++++++----------------------------- 1 file changed, 321 insertions(+), 373 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index 36cb8b9..8a66022 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -2876,6 +2876,7 @@ long get_next_free_numeric_value(virDomainPtr domain, char *xpath) } efree(output); + free(xml); return max_slot + 1; } @@ -4121,20 +4122,20 @@ PHP_FUNCTION(libvirt_domain_get_screenshot) GET_DOMAIN_FROM_ARGS("rs|l",&zdomain, &hostname, &hostname_len, &scancode); - xml=virDomainGetXMLDesc(domain->domain, 0); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain, 0); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); - RETURN_FALSE; + goto error; } tmp = get_string_from_xpath(xml, "//domain/devices/graphics/@port", NULL, &retval); if ((tmp == NULL) || (retval < 0)) { set_error("Cannot get the VNC port" TSRMLS_CC); - RETURN_FALSE; + goto error; } if (mkstemp(file) == 0) - RETURN_FALSE; + goto error; /* Get the current hostname and override to localhost if local machine */ gethostname(name, 1024); @@ -4148,7 +4149,7 @@ PHP_FUNCTION(libvirt_domain_get_screenshot) if (vnc_get_bitmap(hostname, tmp, file) != 0) { set_error("Cannot use builtin approach to get VNC window contents" TSRMLS_CC); - RETURN_FALSE; + goto error; } } else { @@ -4158,7 +4159,7 @@ PHP_FUNCTION(libvirt_domain_get_screenshot) childpid = fork(); if (childpid == -1) - RETURN_FALSE; + goto error; if (childpid == 0) { char tmpp[64] = { 0 }; @@ -4171,13 +4172,13 @@ PHP_FUNCTION(libvirt_domain_get_screenshot) do { w = waitpid(childpid, &retval, 0); if (w == -1) - RETURN_FALSE; + goto error; } while (!WIFEXITED(retval) && !WIFSIGNALED(retval)); } if (WEXITSTATUS(retval) != 0) { set_error("Cannot spawn utility to get screenshot" TSRMLS_CC); - RETURN_FALSE; + goto error; } } @@ -4189,7 +4190,7 @@ PHP_FUNCTION(libvirt_domain_get_screenshot) if (read(fd, buf, fsize) < 0) { close(fd); unlink(file); - RETURN_FALSE; + goto error; } close(fd); @@ -4202,6 +4203,19 @@ PHP_FUNCTION(libvirt_domain_get_screenshot) Z_STRLEN_P(return_value) = fsize; Z_STRVAL_P(return_value) = buf; Z_TYPE_P(return_value) = IS_STRING; + + efree(buf); + free(tmp); + free(xml); + free(path); + return; + + error: + efree(buf); + free(tmp); + free(xml); + free(path); + RETURN_FALSE; #else set_error("Function is not supported on Windows systems" TSRMLS_CC); RETURN_FALSE; @@ -4232,16 +4246,16 @@ PHP_FUNCTION(libvirt_domain_get_screen_dimensions) GET_DOMAIN_FROM_ARGS("rs",&zdomain, &hostname, &hostname_len); - xml=virDomainGetXMLDesc(domain->domain, 0); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain, 0); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); - RETURN_FALSE; + goto error; } tmp = get_string_from_xpath(xml, "//domain/devices/graphics/@port", NULL, &retval); if ((tmp == NULL) || (retval < 0)) { set_error("Cannot get the VNC port" TSRMLS_CC); - RETURN_FALSE; + goto error; } DPRINTF("%s: hostname = %s, port = %s\n", PHPFUNC, hostname, tmp); @@ -4255,12 +4269,21 @@ PHP_FUNCTION(libvirt_domain_get_screen_dimensions) snprintf(error, sizeof(error), "Cannot get screen dimensions, error code = %d (%s)", ret, strerror(-ret)); set_error(error TSRMLS_CC); - RETURN_FALSE; + goto error; } array_init(return_value); add_assoc_long(return_value, "width", (long)width); add_assoc_long(return_value, "height", (long)height); + + free(tmp); + free(xml); + return; + + error: + free(tmp); + free(xml); + RETURN_FALSE; #else set_error("Function is not supported on Windows systems" TSRMLS_CC); RETURN_FALSE; @@ -4294,16 +4317,16 @@ PHP_FUNCTION(libvirt_domain_send_keys) DPRINTF("%s: Sending %d VNC keys to %s...\n", PHPFUNC, (int)strlen((const char *)keys), hostname); - xml=virDomainGetXMLDesc(domain->domain, 0); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain, 0); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); - RETURN_FALSE; + goto error; } tmp = get_string_from_xpath(xml, "//domain/devices/graphics/@port", NULL, &retval); if ((tmp == NULL) || (retval < 0)) { set_error("Cannot get the VNC port" TSRMLS_CC); - RETURN_FALSE; + goto error; } DPRINTF("%s: About to send string '%s' (%d keys) to %s:%s\n", PHPFUNC, keys, (int)strlen((const char *)keys), hostname, tmp); @@ -4311,15 +4334,21 @@ PHP_FUNCTION(libvirt_domain_send_keys) ret = vnc_send_keys(hostname, tmp, keys); DPRINTF("%s: Sequence sending result is %d\n", PHPFUNC, ret); - if (ret == 0) { - RETURN_TRUE - } - else { + if (!ret) { char tmpp[64] = { 0 }; snprintf(tmpp, sizeof(tmpp), "Cannot send keys, error code %d", ret); set_error(tmpp TSRMLS_CC); - RETURN_FALSE; + goto error; } + + free(tmp); + free(xml); + RETURN_TRUE; + + error: + free(tmp); + free(xml); + RETURN_FALSE; #else set_error("Function is not supported on Windows systems" TSRMLS_CC); RETURN_FALSE; @@ -4356,25 +4385,21 @@ PHP_FUNCTION(libvirt_domain_send_pointer_event) GET_DOMAIN_FROM_ARGS("rslll|b",&zdomain, &hostname, &hostname_len, &pos_x, &pos_y, &clicked, &release); - xml=virDomainGetXMLDesc(domain->domain, 0); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain, 0); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); - RETURN_FALSE; + goto error; } tmp = get_string_from_xpath(xml, "//domain/devices/graphics/@port", NULL, &retval); if ((tmp == NULL) || (retval < 0)) { set_error("Cannot get the VNC port" TSRMLS_CC); - RETURN_FALSE; + goto error; } DPRINTF("%s: x = %d, y = %d, clicked = %d, release = %d, hostname = %s...\n", PHPFUNC, (int) pos_x, (int) pos_y, (int) clicked, release, hostname); ret = vnc_send_pointer_event(hostname, tmp, pos_x, pos_y, clicked, release); - if (ret == 0) { - DPRINTF("%s: Pointer event result is %d\n", PHPFUNC, ret); - RETURN_TRUE - } - else { + if (!ret) { char error[1024] = { 0 }; if (ret == -9) snprintf(error, sizeof(error), "Cannot connect to VNC server. Please make sure domain is running and VNC graphics are set"); @@ -4382,8 +4407,17 @@ PHP_FUNCTION(libvirt_domain_send_pointer_event) snprintf(error, sizeof(error), "Cannot send pointer event, error code = %d (%s)", ret, strerror(-ret)); set_error(error TSRMLS_CC); - RETURN_FALSE; + goto error; } + + free(tmp); + free(xml); + RETURN_TRUE; + + error: + free(tmp); + free(xml); + RETURN_FALSE; #else set_error("Function is not supported on Windows systems" TSRMLS_CC); RETURN_FALSE; @@ -4890,7 +4924,7 @@ PHP_FUNCTION(libvirt_domain_new) } xml = virDomainGetXMLDesc(domain, 0); - if (xml == NULL) { + if (!xml) { DPRINTF("%s: Cannot get the XML description\n", PHPFUNC); set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; @@ -4990,8 +5024,8 @@ PHP_FUNCTION(libvirt_domain_get_xml_desc) DPRINTF("%s: Getting the XML for domain %p (xPath = %s)\n", PHPFUNC, domain->domain, xpath); - xml=virDomainGetXMLDesc(domain->domain,flags); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain,flags); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } @@ -5027,8 +5061,8 @@ PHP_FUNCTION(libvirt_domain_get_disk_devices) DPRINTF("%s: Getting disk device list for domain %p\n", PHPFUNC, domain->domain); - xml=virDomainGetXMLDesc(domain->domain, 0); - if (xml == NULL) { + xml = virDomainGetXMLDesc(domain->domain, 0); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } @@ -5062,8 +5096,8 @@ PHP_FUNCTION(libvirt_domain_get_interface_devices) DPRINTF("%s: Getting interface device list for domain %p\n", PHPFUNC, domain->domain); - xml=virDomainGetXMLDesc(domain->domain, 0); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain, 0); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } @@ -5071,6 +5105,7 @@ PHP_FUNCTION(libvirt_domain_get_interface_devices) array_init(return_value); free( get_string_from_xpath(xml, "//domain/devices/interface/target/@dev", &return_value, &retval) ); + free(xml); if (retval < 0) add_assoc_long(return_value, "error_code", (long)retval); @@ -5122,7 +5157,7 @@ PHP_FUNCTION(libvirt_domain_change_memory) char *xml; char *new_xml = NULL; int new_len; - char newXml[4096] = { 0 }; + char *newXml = NULL; long xflags = 0; long allocMem = 0; long allocMax = 0; @@ -5144,8 +5179,8 @@ PHP_FUNCTION(libvirt_domain_change_memory) if (allocMem > allocMax) allocMem = allocMax; - xml=virDomainGetXMLDesc(domain->domain,xflags); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain,xflags); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } @@ -5166,24 +5201,14 @@ PHP_FUNCTION(libvirt_domain_change_memory) conn = domain->conn; - virDomainUndefine(domain->domain); - - retval = virDomainFree(domain->domain); - if (retval != 0) { - DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error)); - } - else { - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0 TSRMLS_CC); - DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain); - } - dom=virDomainDefineXML(conn->conn, new_xml); if (dom==NULL) { - DPRINTF("%s: Function failed, restoring original XML\n", PHPFUNC); - dom=virDomainDefineXML(conn->conn, xml); - if (dom == NULL) - RETURN_FALSE; + free(xml); + efree(new_xml); + RETURN_FALSE; } + free(xml); + efree(new_xml); res_domain = (php_libvirt_domain *)emalloc(sizeof(php_libvirt_domain)); res_domain->domain = dom; @@ -5228,8 +5253,8 @@ PHP_FUNCTION(libvirt_domain_change_boot_devices) GET_DOMAIN_FROM_ARGS("rss|l",&zdomain,&first, &first_len, &second, &second_len, &xflags); - xml=virDomainGetXMLDesc(domain->domain,xflags); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain,xflags); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } @@ -5256,24 +5281,15 @@ PHP_FUNCTION(libvirt_domain_change_boot_devices) conn = domain->conn; - virDomainUndefine(domain->domain); - - retval = virDomainFree(domain->domain); - if (retval != 0) { - DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error)); - } - else { - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0 TSRMLS_CC); - DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain); - } - dom=virDomainDefineXML(conn->conn, new_xml); if (dom==NULL) { DPRINTF("%s: Function failed, restoring original XML\n", PHPFUNC); - dom=virDomainDefineXML(conn->conn, xml); - if (dom == NULL) - RETURN_FALSE; + free(xml); + efree(newXml); + RETURN_FALSE; } + free(xml); + efree(newXml); res_domain = (php_libvirt_domain *)emalloc(sizeof(php_libvirt_domain)); res_domain->domain = dom; @@ -5300,8 +5316,6 @@ PHP_FUNCTION(libvirt_domain_disk_add) { php_libvirt_domain *domain=NULL; zval *zdomain; - char *tmp1 = NULL; - char *tmp2 = NULL; char *xml; char *img = NULL; int img_len; @@ -5313,95 +5327,74 @@ PHP_FUNCTION(libvirt_domain_disk_add) int typ_len; char *new_xml = NULL; int new_len; - char newXml[4096] = { 0 }; + char *newXml = NULL; long xflags = 0; int retval = -1; - int pos = -1; - php_libvirt_domain *res_domain = NULL; - php_libvirt_connection *conn = NULL; - virDomainPtr dom=NULL; + char *xpath = NULL; + char *tmp = NULL; GET_DOMAIN_FROM_ARGS("rssss|l",&zdomain,&img,&img_len,&dev,&dev_len,&typ,&typ_len,&driver,&driver_len,&xflags); DPRINTF("%s: Domain %p, device = %s, image = %s, type = %s, driver = %s\n", PHPFUNC, domain->domain, dev, img, typ, driver); - xml=virDomainGetXMLDesc(domain->domain,xflags); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain,xflags); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); - RETURN_FALSE; + goto error; } - snprintf(newXml, sizeof(newXml), "//domain/devices/disk/source[@file=\"%s\"]/./@file", img); - tmp1 = get_string_from_xpath(xml, newXml, NULL, &retval); - if (tmp1 != NULL) { - free(tmp1); - snprintf(newXml, sizeof(newXml), "Domain already has image <i>%s</i> connected", img); - set_error(newXml TSRMLS_CC); - RETURN_FALSE; + if (asprintf(&xpath, "//domain/devices/disk/source[@file=\"%s\"]/./@file", img) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); + if (tmp != NULL) { + free(tmp); + asprintf(&tmp, "Domain already has image <i>%s</i> connected", img); + set_error(tmp TSRMLS_CC); + goto error; } - snprintf(newXml, sizeof(newXml), "//domain/devices/disk/target[@dev='%s']/./@dev", dev); - tmp1 = get_string_from_xpath(xml, newXml, NULL, &retval); - if (tmp1 != NULL) { - free(tmp1); - snprintf(newXml, sizeof(newXml), "Domain already has device <i>%s</i> connected", dev); - set_error(newXml TSRMLS_CC); - RETURN_FALSE; + free(xpath); + if (asprintf(&xpath, "//domain/devices/disk/target[@dev='%s']/./@dev", dev) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, newXml, NULL, &retval); + if (tmp != NULL) { + free(tmp); + asprintf(&tmp, "Domain already has device <i>%s</i> connected", dev); + set_error(tmp TSRMLS_CC); + goto error; } - if (access(img, R_OK) != 0) { - snprintf(newXml, sizeof(newXml), "Image file <i>%s</i> doesn't exist", img); - set_error(newXml TSRMLS_CC); - RETURN_FALSE; - } - - snprintf(newXml, sizeof(newXml), + if (asnprintf(&newXml, " <disk type='file' device='disk'>\n" " <driver name='qemu' type='%s'/>\n" " <source file='%s'/>\n" " <target dev='%s' bus='%s'/>\n" - " </disk>", driver, img, dev, typ); - tmp1 = strstr(xml, "</emulator>") + strlen("</emulator>"); - pos = strlen(xml) - strlen(tmp1); - - tmp2 = (char *)emalloc( ( pos + 1 )* sizeof(char) ); - memset(tmp2, 0, pos + 1); - memcpy(tmp2, xml, pos); - - new_len = strlen(tmp1) + strlen(tmp2) + strlen(newXml) + 2; - new_xml = (char *)emalloc( new_len * sizeof(char) ); - snprintf(new_xml, new_len, "%s\n%s%s", tmp2, newXml, tmp1); - - conn = domain->conn; - - virDomainUndefine(domain->domain); - virDomainFree(domain->domain); - - retval = virDomainFree(domain->domain); - if (retval != 0) { - DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error)); - } - else { - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0 TSRMLS_CC); - DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain); + " </disk>", driver, img, dev, typ) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; } - dom=virDomainDefineXML(conn->conn, new_xml); - if (dom==NULL) { - DPRINTF("%s: Function failed, restoring original XML\n", PHPFUNC); - dom=virDomainDefineXML(conn->conn, xml); - if (dom == NULL) - RETURN_FALSE; + if (virDomainAttachDeviceFlags(domain->domain, + newXml, VIR_DOMAIN_AFFECT_CONFIG) < 0) { + set_error("Unable to attach disk" TSRMLS_CC); + goto error; } - res_domain = (php_libvirt_domain *)emalloc(sizeof(php_libvirt_domain)); - res_domain->domain = dom; - res_domain->conn = conn; + free(tmp); + free(xpath); + free(xml); + RETURN_TRUE; - DPRINTF("%s: returning %p\n", PHPFUNC, res_domain->domain); - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, res_domain->domain, 1 TSRMLS_CC); - ZEND_REGISTER_RESOURCE(return_value, res_domain, le_libvirt_domain); + error: + free(tmp); + free(xpath); + free(xml); + RETURN_FALSE; } /* @@ -5417,14 +5410,12 @@ PHP_FUNCTION(libvirt_domain_disk_remove) { php_libvirt_domain *domain=NULL; zval *zdomain; - char *tmp1 = NULL; - char *tmp2 = NULL; char *xml; char *dev = NULL; int dev_len; char *new_xml = NULL; int new_len; - char newXml[4096] = { 0 }; + char *newXml = NULL; long xflags = 0; int retval = -1; int pos = -1; @@ -5432,81 +5423,54 @@ PHP_FUNCTION(libvirt_domain_disk_remove) php_libvirt_domain *res_domain=NULL; php_libvirt_connection *conn = NULL; virDomainPtr dom = NULL; + char *xpath = NULL; + char *tmp = NULL; GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&dev,&dev_len,&xflags); DPRINTF("%s: Trying to remove %s from domain %p\n", PHPFUNC, dev, domain->domain); - xml=virDomainGetXMLDesc(domain->domain,xflags); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain,xflags); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } - snprintf(newXml, sizeof(newXml), "//domain/devices/disk/target[@dev='%s']/./@dev", dev); - tmp1 = get_string_from_xpath(xml, newXml, NULL, &retval); - if (tmp1 == NULL) { - snprintf(newXml, sizeof(newXml), "Device <i>%s</i> is not connected to the guest", dev); - set_error(newXml TSRMLS_CC); - RETURN_FALSE; + if (asprintf(&xpath, "//domain/devices/disk/target[@dev='%s']/./@dev", dev) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); + if (!tmp) { + asnprintf(&tmp, "Device <i>%s</i> is not connected to the guest", dev); + set_error(tmp TSRMLS_CC); + goto error; } - free(tmp1); - - snprintf(newXml, sizeof(newXml), "<target dev='%s'", dev); - tmp1 = strstr(xml, newXml) + strlen(newXml); - pos = strlen(xml) - strlen(tmp1); - - tmp2 = (char *)emalloc( ( pos + 1 )* sizeof(char) ); - memset(tmp2, 0, pos + 1); - memcpy(tmp2, xml, pos); - - for (i = strlen(tmp2) - 5; i > 0; i--) - if ((tmp2[i] == '<') && (tmp2[i+1] == 'd') - && (tmp2[i+2] == 'i') && (tmp2[i+3] == 's') - && (tmp2[i+4] == 'k')) { - tmp2[i-5] = 0; - break; - } - - for (i = 0; i < strlen(tmp1) - 7; i++) - if ((tmp1[i] == '<') && (tmp1[i+1] == '/') - && (tmp1[i+2] == 'd') && (tmp1[i+3] == 'i') - && (tmp1[i+4] == 's') && (tmp1[i+5] == 'k') - && (tmp1[i+6] == '>')) { - idx = i + 6; - break; - } - - new_len = strlen(tmp2) + (strlen(tmp1) - idx); - new_xml = (char *)emalloc( new_len * sizeof(char) ); - memset(new_xml, 0, new_len); - strcpy(new_xml, tmp2); - for (i = idx; i < strlen(tmp1) - 1; i++) - new_xml[ strlen(tmp2) + i - idx ] = tmp1[i]; - - conn = domain->conn; - virDomainUndefine(domain->domain); - - retval = virDomainFree(domain->domain); - if (retval != 0) { - DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error)); - } - else { - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0 TSRMLS_CC); - DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain); + if (asnprintf(&newXml, + " <disk type='file' device='disk'>\n" + " <target dev='%s'/>\n" + " </disk>", dev) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; } - dom=virDomainDefineXML(conn->conn,new_xml); - if (dom==NULL) RETURN_FALSE; + if (virDomainDetachDeviceFlags(domain->domain, + newXml, VIR_DOMAIN_AFFECT_CONFIG) < 0) { + set_error("Unable to attach disk" TSRMLS_CC); + goto error; + } - res_domain = (php_libvirt_domain *)emalloc(sizeof(php_libvirt_domain)); - res_domain->domain = dom; - res_domain->conn = conn; + free(tmp); + free(xpath); + free(xml); + RETURN_TRUE; - DPRINTF("%s: returning %p\n", PHPFUNC, res_domain->domain); - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, res_domain->domain, 1 TSRMLS_CC); - ZEND_REGISTER_RESOURCE(return_value, res_domain, le_libvirt_domain); + error: + free(tmp); + free(xpath); + free(xml); + RETURN_FALSE; } /* @@ -5524,8 +5488,6 @@ PHP_FUNCTION(libvirt_domain_nic_add) { php_libvirt_domain *domain=NULL; zval *zdomain; - char *tmp1 = NULL; - char *tmp2 = NULL; char *xml; char *mac = NULL; int mac_len; @@ -5535,14 +5497,12 @@ PHP_FUNCTION(libvirt_domain_nic_add) int model_len; char *new_xml = NULL; int new_len; - char newXml[4096] = { 0 }; + char *newXml = NULL; long xflags = 0; int retval = -1; int pos = -1; - php_libvirt_domain *res_domain = NULL; - php_libvirt_connection *conn = NULL; - virDomainPtr dom=NULL; - long slot = -1; + char *xpath = NULL; + char *tmp = NULL; DPRINTF("%s: Entering\n", PHPFUNC); @@ -5552,83 +5512,61 @@ PHP_FUNCTION(libvirt_domain_nic_add) DPRINTF("%s: domain = %p, mac = %s, net = %s, model = %s\n", PHPFUNC, domain->domain, mac, net, model); - xml=virDomainGetXMLDesc(domain->domain,xflags); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain,xflags); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } - snprintf(newXml, sizeof(newXml), "//domain/devices/interface[@type='network']/mac[@address='%s']/./@mac", mac); - tmp1 = get_string_from_xpath(xml, newXml, NULL, &retval); - if (tmp1 != NULL) { - free(tmp1); - snprintf(newXml, sizeof(newXml), "Domain already has NIC device with MAC address <i>%s</i> connected", mac); - set_error(newXml TSRMLS_CC); - RETURN_FALSE; + if (asprintf(&xpath, "//domain/devices/interface[@type='network']/mac[@address='%s']/./@mac", mac) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); + if (tmp) { + free(tmp); + asprintf(&tmp, "Domain already has NIC device with MAC address <i>%s</i> connected", mac); + set_error(tmp TSRMLS_CC); + goto error; } - slot = get_next_free_numeric_value(domain->domain, "//@function"); - if (slot < 0) { - free(tmp1); - snprintf(newXml, sizeof(newXml), "Cannot find a free function slot for domain"); - set_error(newXml TSRMLS_CC); - RETURN_FALSE; + if (model) { + if (asprintf(&newXml, + " <interface type='network'>\n" + " <mac address='%s' />\n" + " <source network='%s' />\n" + " <model type='%s' />\n" + " </interface>", mac, net, model) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + } else { + if (asprintf(&newXml, + " <interface type='network'>\n" + " <mac address='%s' />\n" + " <source network='%s' />\n" + " </interface>", mac, net) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } } - if (model == NULL) - snprintf(newXml, sizeof(newXml), - " <interface type='network'>\n" - " <mac address='%s' />\n" - " <source network='%s' />\n" - " <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x%02x' />\n" - " </interface>", mac, net, slot+1); - else - snprintf(newXml, sizeof(newXml), - " <interface type='network'>\n" - " <mac address='%s' />\n" - " <source network='%s' />\n" - " <model type='%s' />\n" - " <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x%02x' />\n" - " </interface>", mac, net, model, slot+1); - - tmp1 = strstr(xml, "</controller>") + strlen("</controller>"); - pos = strlen(xml) - strlen(tmp1); - - tmp2 = (char *)emalloc( ( pos + 1 )* sizeof(char) ); - memset(tmp2, 0, pos + 1); - memcpy(tmp2, xml, pos); - - new_len = strlen(tmp1) + strlen(tmp2) + strlen(newXml) + 2; - new_xml = (char *)emalloc( new_len * sizeof(char) ); - snprintf(new_xml, new_len, "%s\n%s%s", tmp2, newXml, tmp1); - - conn = domain->conn; - - virDomainUndefine(domain->domain); - - retval = virDomainFree(domain->domain); - if (retval != 0) { - DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error)); - } - else { - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0 TSRMLS_CC); - DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain); + if (virDomainAttachDeviceFlags(domain->domain, + newXml, VIR_DOMAIN_AFFECT_CONFIG) < 0) { + set_error("Unable to attach interface" TSRMLS_CC); + goto error; } - dom=virDomainDefineXML(conn->conn, new_xml); - if (dom==NULL) { - DPRINTF("%s: Function failed, restoring original XML, new XML data: %s\n", PHPFUNC, new_xml); - virDomainDefineXML(conn->conn, xml); - RETURN_FALSE; - } + free(tmp); + free(xpath); + free(xml); + RETURN_TRUE; - res_domain = (php_libvirt_domain *)emalloc(sizeof(php_libvirt_domain)); - res_domain->domain = dom; - res_domain->conn = conn; - - DPRINTF("%s: returning %p\n", PHPFUNC, res_domain->domain); - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, res_domain->domain, 1 TSRMLS_CC); - ZEND_REGISTER_RESOURCE(return_value, res_domain, le_libvirt_domain); + error: + free(tmp); + free(xpath); + free(xml); + RETURN_FALSE; } /* @@ -5651,92 +5589,58 @@ PHP_FUNCTION(libvirt_domain_nic_remove) int mac_len; char *new_xml = NULL; int new_len; - char newXml[4096] = { 0 }; + char *newXml = NULL; long xflags = 0; int retval = -1; int pos = -1; - int i, idx = 0; - php_libvirt_domain *res_domain=NULL; - php_libvirt_connection *conn = NULL; - virDomainPtr dom = NULL; + char *xpath = NULL; + char *tmp = NULL; GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&mac,&mac_len,&xflags); DPRINTF("%s: Trying to remove NIC device with MAC address %s from domain %p\n", PHPFUNC, mac, domain->domain); - xml=virDomainGetXMLDesc(domain->domain,xflags); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain,xflags); + if (!xml) { set_error_if_unset("Cannot get the XML description" TSRMLS_CC); RETURN_FALSE; } - - snprintf(newXml, sizeof(newXml), "//domain/devices/interface[@type='network']/mac[@address='%s']/./@address", mac); - tmp1 = get_string_from_xpath(xml, newXml, NULL, &retval); - if (tmp1 == NULL) { - snprintf(newXml, sizeof(newXml), "Network card with IP address <i>%s</i> is not connected to the guest", mac); - set_error(newXml TSRMLS_CC); - RETURN_FALSE; + if (asprintf(&xpath, "//domain/devices/interface[@type='network']/mac[@address='%s']/./@mac", mac) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); + if (!tmp) { + free(tmp); + asprintf(&tmp, "Domain has no such interface with mac %s", mac); + set_error(tmp TSRMLS_CC); + goto error; } - free(tmp1); - - snprintf(newXml, sizeof(newXml), "<mac address='%s'", mac); - if (strstr(xml, newXml) == NULL) - snprintf(newXml, sizeof(newXml), "<mac address=\"%s\"", mac); - - tmp1 = strstr(xml, newXml) + strlen(newXml); - pos = strlen(xml) - strlen(tmp1); - - tmp2 = (char *)emalloc( ( pos + 1 )* sizeof(char) ); - memset(tmp2, 0, pos + 1); - memcpy(tmp2, xml, pos); - - for (i = strlen(tmp2) - 5; i > 0; i--) - if ((tmp2[i] == '<') && (tmp2[i+1] == 'i') - && (tmp2[i+2] == 'n') && (tmp2[i+3] == 't') - && (tmp2[i+4] == 'e')) { - tmp2[i-5] = 0; - break; - } - - for (i = 0; i < strlen(tmp1) - 7; i++) - if ((tmp1[i] == '<') && (tmp1[i+1] == '/') - && (tmp1[i+2] == 'i') && (tmp1[i+3] == 'n') - && (tmp1[i+4] == 't') && (tmp1[i+5] == 'e') - && (tmp1[i+6] == 'r')) { - idx = i + 6; - break; - } - - new_len = strlen(tmp2) + (strlen(tmp1) - idx); - new_xml = (char *)emalloc( new_len * sizeof(char) ); - memset(new_xml, 0, new_len); - strcpy(new_xml, tmp2); - for (i = idx; i < strlen(tmp1) - 1; i++) - new_xml[ strlen(tmp2) + i - idx ] = tmp1[i]; - - conn = domain->conn; - virDomainUndefine(domain->domain); - - retval = virDomainFree(domain->domain); - if (retval != 0) { - DPRINTF("%s: Cannot free domain %p, error code = %d (%s)\n", PHPFUNC, domain->domain, retval, LIBVIRT_G(last_error)); - } - else { - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, domain->domain, 0 TSRMLS_CC); - DPRINTF("%s: Domain %p freed\n", PHPFUNC, domain->domain); + if (asprintf(&newXml, + " <interface type='network'>\n" + " <mac address='%s' />\n" + " </interface>", mac) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; } - dom=virDomainDefineXML(conn->conn,new_xml); - if (dom==NULL) RETURN_FALSE; + if (virDomainDetachDeviceFlags(domain->domain, + newXml, VIR_DOMAIN_AFFECT_CONFIG) < 0) { + set_error("Unable to detach interface" TSRMLS_CC); + goto error; + } - res_domain = (php_libvirt_domain *)emalloc(sizeof(php_libvirt_domain)); - res_domain->domain = dom; - res_domain->conn = conn; + free(tmp); + free(xpath); + free(xml); + RETURN_TRUE; - DPRINTF("%s: returning %p\n", PHPFUNC, res_domain->domain); - resource_change_counter(INT_RESOURCE_DOMAIN, conn->conn, res_domain->domain, 1 TSRMLS_CC); - ZEND_REGISTER_RESOURCE(return_value, res_domain, le_libvirt_domain); + error: + free(tmp); + free(xpath); + free(xml); + RETURN_FALSE; } /* @@ -6237,40 +6141,60 @@ PHP_FUNCTION(libvirt_domain_get_network_info) char *xml; char *tmp = NULL; int mac_len; - char fnpath[1024] = { 0 }; + char *xpath = NULL; GET_DOMAIN_FROM_ARGS("rs",&zdomain,&mac,&mac_len); /* Get XML for the domain */ - xml=virDomainGetXMLDesc(domain->domain, VIR_DOMAIN_XML_INACTIVE); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain, VIR_DOMAIN_XML_INACTIVE); + if (!xml) { set_error("Cannot get domain XML" TSRMLS_CC); RETURN_FALSE; } DPRINTF("%s: Getting network information for NIC with MAC address '%s'\n", PHPFUNC, mac); - snprintf(fnpath, sizeof(fnpath), "//domain/devices/interface[@type='network']/mac[@address='%s']/../source/@network", mac); - tmp = get_string_from_xpath(xml, fnpath, NULL, &retval); + if (asprintf(&xpath, "//domain/devices/interface[@type='network']/mac[@address='%s']/../source/@network", mac) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); if (tmp == NULL) { set_error("Invalid XPath node for source network" TSRMLS_CC); - RETURN_FALSE; + goto error; } if (retval < 0) { set_error("Cannot get XPath expression result for network source" TSRMLS_CC); - RETURN_FALSE; + goto error; } array_init(return_value); add_assoc_string_ex(return_value, "mac", 4, mac, 1); add_assoc_string_ex(return_value, "network", 8, tmp, 1); - snprintf(fnpath, sizeof(fnpath), "//domain/devices/interface[@type='network']/mac[@address='%s']/../model/@type", mac); - tmp = get_string_from_xpath(xml, fnpath, NULL, &retval); + free(tmp); + free(xpath); + + if (asprintf(&xpath, "//domain/devices/interface[@type='network']/mac[@address='%s']/../model/@type", mac) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "nic_type", 9, tmp, 1); else add_assoc_string_ex(return_value, "nic_type", 9, "default", 1); + + free(xml); + free(xpath); + free(tmp); + RETURN_TRUE; + + error: + free(xml); + free(xpath); + free(tmp); + RETURN_FALSE; } /* @@ -6290,48 +6214,55 @@ PHP_FUNCTION(libvirt_domain_get_block_info) char *xml; char *tmp = NULL; int dev_len, isFile; - char fnpath[1024] = { 0 }; + char *xpath = NULL; struct _virDomainBlockInfo info; GET_DOMAIN_FROM_ARGS("rs",&zdomain,&dev,&dev_len); /* Get XML for the domain */ - xml=virDomainGetXMLDesc(domain->domain, VIR_DOMAIN_XML_INACTIVE); - if (xml==NULL) { + xml = virDomainGetXMLDesc(domain->domain, VIR_DOMAIN_XML_INACTIVE); + if (!xml) { set_error("Cannot get domain XML" TSRMLS_CC); RETURN_FALSE; } isFile = 0; - snprintf(fnpath, sizeof(fnpath), "//domain/devices/disk/target[@dev='%s']/../source/@dev", dev); - tmp = get_string_from_xpath(xml, fnpath, NULL, &retval); + if (asprintf(&xpath, "//domain/devices/disk/target[@dev='%s']/../source/@dev", dev) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); if (retval < 0) { set_error("Cannot get XPath expression result for device storage" TSRMLS_CC); - RETURN_FALSE; + goto error; } if (retval == 0) { - snprintf(fnpath, sizeof(fnpath), "//domain/devices/disk/target[@dev='%s']/../source/@file", dev); - tmp = get_string_from_xpath(xml, fnpath, NULL, &retval); + free(xpath); + if (asprintf(&xpath, "//domain/devices/disk/target[@dev='%s']/../source/@file", dev) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + free(tmp); + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); if (retval < 0) { set_error("Cannot get XPath expression result for file storage" TSRMLS_CC); - RETURN_FALSE; + goto error; } isFile = 1; } if (retval == 0) { set_error("No relevant node found" TSRMLS_CC); - RETURN_FALSE; + goto error; } - retval=virDomainGetBlockInfo(domain->domain, tmp, &info,0); - + retval = virDomainGetBlockInfo(domain->domain, tmp, &info,0); if (retval == -1) { set_error("Cannot get domain block information" TSRMLS_CC); - RETURN_FALSE; + goto error; } array_init(return_value); @@ -6343,14 +6274,30 @@ PHP_FUNCTION(libvirt_domain_get_block_info) else add_assoc_string_ex(return_value, "partition", 10, tmp, 1); - snprintf(fnpath, sizeof(fnpath), "//domain/devices/disk/target[@dev='%s']/../driver/@type", dev); - tmp = get_string_from_xpath(xml, fnpath, NULL, &retval); + free(xpath); + if (asprintf(&xpath, "//domain/devices/disk/target[@dev='%s']/../driver/@type", dev) < 0) { + set_error("Out of memory" TSRMLS_CC); + goto error; + } + free(tmp); + tmp = get_string_from_xpath(xml, xpath, NULL, &retval); if (tmp != NULL) add_assoc_string_ex(return_value, "type", 5, tmp, 1); LONGLONG_ASSOC(return_value, "capacity", info.capacity); LONGLONG_ASSOC(return_value, "allocation", info.allocation); LONGLONG_ASSOC(return_value, "physical", info.physical); + + free(xpath); + free(tmp); + free(xml); + return; + + error: + free(xpath); + free(tmp); + free(xml); + RETURN_FALSE; } /* @@ -6373,8 +6320,9 @@ PHP_FUNCTION(libvirt_domain_xml_xpath) GET_DOMAIN_FROM_ARGS("rs|l",&zdomain, &zpath, &path_len, &flags); - xml=virDomainGetXMLDesc(domain->domain, flags); - if (xml==NULL) RETURN_FALSE; + xml = virDomainGetXMLDesc(domain->domain, flags); + if (!xml) + RETURN_FALSE; array_init(return_value); -- 2.4.9

It's caller responsibility to free the returned value when no longer needed. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt-php.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index 8a66022..a772a6f 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -8315,8 +8315,8 @@ PHP_FUNCTION(libvirt_nodedev_get_xml_desc) xpath = NULL; } - xml=virNodeDeviceGetXMLDesc(nodedev->device, 0); - if ( xml == NULL ) { + xml = virNodeDeviceGetXMLDesc(nodedev->device, 0); + if (!xml) { set_error("Cannot get the device XML information" TSRMLS_CC); RETURN_FALSE; } @@ -8352,8 +8352,8 @@ PHP_FUNCTION(libvirt_nodedev_get_information) GET_NODEDEV_FROM_ARGS("r",&znodedev); - xml=virNodeDeviceGetXMLDesc(nodedev->device, 0); - if ( xml == NULL ) { + xml = virNodeDeviceGetXMLDesc(nodedev->device, 0); + if (!xml) { set_error("Cannot get the device XML information" TSRMLS_CC); RETURN_FALSE; } @@ -8364,17 +8364,18 @@ PHP_FUNCTION(libvirt_nodedev_get_information) tmp = get_string_from_xpath(xml, "//device/name", NULL, &retval); if (tmp == NULL) { set_error("Invalid XPath node for device name" TSRMLS_CC); - RETURN_FALSE; + goto error; } if (retval < 0) { set_error("Cannot get XPath expression result for device name" TSRMLS_CC); - RETURN_FALSE; + goto error; } add_assoc_string_ex(return_value, "name", 5, tmp, 1); /* Get parent name */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/parent", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "parent", 7, tmp, 1); @@ -8387,80 +8388,106 @@ PHP_FUNCTION(libvirt_nodedev_get_information) /* System capability is having hardware and firmware sub-blocks */ if (strcmp(cap, "system") == 0) { /* Get hardware vendor */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/hardware/vendor", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "hardware_vendor", 16, tmp, 1); /* Get hardware version */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/hardware/version", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "hardware_version", 17, tmp, 1); /* Get hardware serial */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/hardware/serial", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "hardware_serial", 16, tmp, 1); /* Get hardware UUID */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/hardware/uuid", NULL, &retval); if (tmp != NULL) add_assoc_string_ex(return_value, "hardware_uuid", 15, tmp, 1); /* Get firmware vendor */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/firmware/vendor", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "firmware_vendor", 16, tmp, 1); /* Get firmware version */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/firmware/version", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "firmware_version", 17, tmp, 1); /* Get firmware release date */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/firmware/release_date", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "firmware_release_date", 22, tmp, 1); } /* Get product_id */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/product/@id", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "product_id", 11, tmp, 1); /* Get product_name */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/product", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "product_name", 13, tmp, 1); /* Get vendor_id */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/vendor/@id", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "vendor_id", 10, tmp, 1); /* Get vendor_name */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/vendor", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "vendor_name", 12, tmp, 1); /* Get driver name */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/driver/name", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "driver_name", 12, tmp, 1); /* Get driver name */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/interface", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "interface_name", 15, tmp, 1); /* Get driver name */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/address", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "address", 8, tmp, 1); /* Get driver name */ + free(tmp); tmp = get_string_from_xpath(xml, "//device/capability/capability/@type", NULL, &retval); if ((tmp != NULL) && (retval > 0)) add_assoc_string_ex(return_value, "capabilities", 11, tmp, 1); + + free(cap); + free(tmp); + free(xml); + return; + + error: + free(cap); + free(tmp); + free(xml); + RETURN_FALSE; } /* Network functions */ -- 2.4.9
participants (1)
-
Michal Privoznik