static int gather_capability(LibHalContext *ctx, const char *udi, const char *cap_name, virNodeDevCapsDefPtr *caps_p) { caps_tbl_entry *entry; entry = bsearch(&cap_name, caps_tbl, ARRAY_CARDINALITY(caps_tbl), sizeof(caps_tbl[0]), cmpstringp); if (entry) { virNodeDevCapsDefPtr caps; if (VIR_ALLOC(caps) < 0) return ENOMEM; caps->type = entry->type; if (entry->gather_fn) { int rv = (*entry->gather_fn)(ctx, udi, &caps->data); if (rv != 0) { virNodeDevCapsDefFree(caps); return rv; } } caps->next = *caps_p; *caps_p = caps; } return 0; }
static int gather_capabilities(LibHalContext *ctx, const char *udi, virNodeDevCapsDefPtr *caps_p) { char *bus_name = NULL; virNodeDevCapsDefPtr caps = NULL; char **hal_cap_names = NULL; int rv; size_t i; if (STREQ(udi, "/org/freedesktop/Hal/devices/computer")) { rv = gather_capability(ctx, udi, "system", &caps); if (rv != 0) goto failure; } if (get_str_prop(ctx, udi, "info.subsystem", &bus_name) == 0 || get_str_prop(ctx, udi, "linux.subsystem", &bus_name) == 0) { rv = gather_capability(ctx, udi, bus_name, &caps); if (rv != 0) goto failure; } hal_cap_names = libhal_device_get_property_strlist(ctx, udi, "info.capabilities", NULL); if (hal_cap_names) { for (i = 0; hal_cap_names[i]; i++) { if (! (bus_name && STREQ(hal_cap_names[i], bus_name))) { rv = gather_capability(ctx, udi, hal_cap_names[i], &caps); if (rv != 0) goto failure; } } for (i = 0; hal_cap_names[i]; i++) VIR_FREE(hal_cap_names[i]); VIR_FREE(hal_cap_names); } VIR_FREE(bus_name); *caps_p = caps; return 0; failure: VIR_FREE(bus_name); if (hal_cap_names) { for (i = 0; hal_cap_names[i]; i++) VIR_FREE(hal_cap_names[i]); VIR_FREE(hal_cap_names); } while (caps) { virNodeDevCapsDefPtr next = caps->next; virNodeDevCapsDefFree(caps); caps = next; } return rv; }
void virNodeDeviceDefFree(virNodeDeviceDefPtr def) { virNodeDevCapsDefPtr caps; if (!def) return; VIR_FREE(def->name); VIR_FREE(def->parent); VIR_FREE(def->driver); VIR_FREE(def->sysfs_path); VIR_FREE(def->parent_sysfs_path); caps = def->caps; while (caps) { virNodeDevCapsDefPtr next = caps->next; virNodeDevCapsDefFree(caps); caps = next; } VIR_FREE(def); }
static virNodeDevCapsDefPtr virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDefPtr def, xmlNodePtr node, int create) { virNodeDevCapsDefPtr caps; char *tmp; int val, ret; if (VIR_ALLOC(caps) < 0) { virReportOOMError(); return NULL; } tmp = virXMLPropString(node, "type"); if (!tmp) { virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing capability type")); goto error; } if ((val = virNodeDevCapTypeFromString(tmp)) < 0) { virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, _("unknown capability type '%s'"), tmp); VIR_FREE(tmp); goto error; } caps->type = val; VIR_FREE(tmp); switch (caps->type) { case VIR_NODE_DEV_CAP_SYSTEM: ret = virNodeDevCapSystemParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_PCI_DEV: ret = virNodeDevCapPciDevParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_USB_DEV: ret = virNodeDevCapUsbDevParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_USB_INTERFACE: ret = virNodeDevCapUsbInterfaceParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_NET: ret = virNodeDevCapNetParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_SCSI_HOST: ret = virNodeDevCapScsiHostParseXML(ctxt, def, node, &caps->data, create); break; case VIR_NODE_DEV_CAP_SCSI_TARGET: ret = virNodeDevCapScsiTargetParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_SCSI: ret = virNodeDevCapScsiParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_STORAGE: ret = virNodeDevCapStorageParseXML(ctxt, def, node, &caps->data); break; default: virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, _("unknown capability type '%d' for '%s'"), caps->type, def->name); ret = -1; break; } if (ret < 0) goto error; return caps; error: virNodeDevCapsDefFree(caps); return NULL; }