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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list