
On 06/20/2013 05:21 AM, Osier Yang wrote:
On 20/06/13 02:28, John Ferlan wrote:
On 06/07/2013 01:16 PM, Osier Yang wrote:
On 08/06/13 01:03, Osier Yang wrote:
return NULL; } - if (!(tokens = virStringSplit(parent, "_", 0))) - return NULL; + if (strchr(parent, '_')) { + if (!(tokens = virStringSplit(parent, "_", 0))) + return NULL; - len = virStringListLength(tokens); + length = virStringListLength(tokens); + + switch (length) { + case 4: + if (!(ret = virStringJoin((const char **)(&tokens[1]), ":"))) + goto cleanup; + break; - switch (len) { - case 4: - if (!(ret = virStringJoin((const char **)(&tokens[1]), ":"))) + case 2: + vendor = tokens[1]; + product = tokens[2]; + if (!(ret = virFindPCIDeviceByVPD(NULL, vendor, product))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find PCI device with vendor '%s' " + "product '%s'"), vendor, product); + goto cleanup; + } + + break; + default: + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'parent' of scsi_host adapter must be " + "either consistent with name of mode " + "device, or in domain:bus:slot:function " + "format"));
Duplicated error message - same issues as before, plus I think you need to consider determining which of the two places you got the error. That is if we see that message, then did we get an error because there wasn't a "_" or ":" in the name or (in this case) because the address was malformed since we expected only 2 or 4 numbers with a specific separator but found more or less. In this case, I would think you could just indicate the parent %s is malformed, requires only 2 or 4 separators.
I don't think so, indicate it requires 2 or 4 separators doesn't give the user what we expect clearly. That's why I use "duplicate" error messages, even if
+ if (!strchr(parent, '_') && + !strchr(parent, ':')) {
is false, we still have to let the user know what the format we expect for "parent" attribute.
goto cleanup; - break; + } + } else if (strchr(parent, ':')) { + char *padstr = NULL; + + if (!(tokens = virStringSplit(parent, ":", 0))) + return NULL; - case 2: - vendor = tokens[1]; - product = tokens[2]; - if (!(ret = virFindPCIDeviceByVPD(NULL, vendor, product))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find PCI device with vendor '%s' " - "product '%s'"), vendor, product); + length = virStringListLength(tokens); + + if (length != 4) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid PCI address for scsi_host " + "'parent' '%s'"), parent); goto cleanup; } - break; - default: - virReportError(VIR_ERR_XML_ERROR, "%s", - _("'parent' of scsi_host adapter must " - "be consistent with name of node device")); - goto cleanup; + for (i = 0; i < length; i++) { + if (strlen(tokens[i]) == 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid PCI address for scsi_host " + "'parent' '%s'"), parent); + goto cleanup; + } + } + + /* sysfs always exposes the PCI address like "0000:00:1f:2", + * this do the padding if the address prodived by user is
s/prodived/provided
+ * not padded (e.g. 0:0:2:0). + */ + if (strlen(tokens[0]) != 4) { + if (!(padstr = virStringPad(tokens[0], '0', 4, false))) + goto cleanup; + + virBufferAsprintf(&buf, "%s", padstr); + VIR_FREE(padstr); + } else { + virBufferAsprintf(&buf, "%s", tokens[0]); + } + + for (i = 1; i < 3; i++) { + if (strlen(tokens[i]) != 2) { + if (!(padstr = virStringPad(tokens[i], '0', 2, false))) + goto error; + virBufferAsprintf(&buf, "%s", padstr); I think the following syntax will avoid any sort of virStringPad() and whatever is going on above
virBufferAsprintf(&buf, "%04x:02x:02x:%s", atoi(tokens[0]), atoi(tokens[1]), atoi(tokens[2]), tokens[3]);
Assuming of course that each field is a base16 value and atoi() is "OK" to use here...
glibc says atoi is absolete, and since it's not required to do any error checking, strtol is recommended.
In libvirt, we have wrapper for strtol: virStrTo*.
But I don't see it's better than using virStringPad if converting the string into int using virStringTo*. We have to check the return value of virStringTo* anyway here, because the user could input crazy data, e.g.
1234566789101112:01:02:02
Osier
What if we separated the fields in the XML? It feels wrong to store data as a string separated by underscores, only to have to parse it again. Instead of <adapter type='scsi_host' parent='pci_0000_00_1f_2' unique_id='2'/> We could do: <adapter type='scsi_host' unique_id='2'> <parent> <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> </parent> </adapter> or: <parent> <vendor>0x8086</vendor> <device>0x1e03</device> </parent> Jan