On Fri, Nov 13, 2015 at 10:28:02AM +0100, Christian Loehle wrote: > On 11/11/2015 10:17 AM, Daniel P. Berrange wrote: > >> + virCommandSetOutputBuffer(cmd, &output); > >> + size_t count = -1; // Don't count table header line > >> + size_t i = 0; > >> + if (virCommandRun(cmd, NULL) < 0) > >> + goto error; > >> + while (output[i] != '\0') { > >> + if (output[i] == '\n') count++; > >> + i++; > >> + } > >> + if (VIR_ALLOC_N(*parsedOutput, count)) { > >> + virReportError(VIR_ERR_INTERNAL_ERROR, > >> + _("Failed to allocate jailhouse_cell array of size %zu"), count); > > > > Again no need to report error. You need to check > > > > VIR_ALLOC_N(...) < 0 > > > > too - this error check is inverted right now > > I removed the report, but I don't quite understand why this check > would be inverted. > VIR_ALLOC_N returns 0 on success, in which case it won't enter the > if block and -1 on failure(OOM) in which case the if block will be > entered. Care to elaborate? Ok, saying it was inverted is not accurate, but it is at risk of incorrect behaviour because it treats positive integers as failure and by convention in libvirt positive integers always indicate success. It just happens that we VIR_ALLOC_N doesn't /currently/ return a positive integer, but it could in future.... > >> + i = 0; > >> + size_t j; > >> + while (output[i++] != '\n'); // Skip table header line > >> + for (j = 0; j < count; j++) { > >> + size_t k; > >> + for (k = 0; k <= IDLENGTH; k++) // char after number needs to be NUL for virStrToLong > >> + if (output[i+k] == ' ') { > >> + output[i+k] = '\0'; > >> + break; > >> + } > >> + char c = output[i+IDLENGTH]; > >> + output[i+IDLENGTH] = '\0'; // in case ID is 8 chars long, so beginning of name won't get parsed > >> + if (virStrToLong_i(output+i, NULL, 0, &(*parsedOutput)[j].id)) > >> + virReportError(VIR_ERR_INTERNAL_ERROR, > >> + _("Failed to parse id to long: %s"), output+i); > >> + output[i+IDLENGTH] = c; > >> + i += IDLENGTH; > >> + if (virStrncpy((*parsedOutput)[j].name, output+i, NAMELENGTH, NAMELENGTH+1) == NULL) > >> + // should never happen > >> + goto error; > >> + (*parsedOutput)[j].name[NAMELENGTH] = '\0'; > >> + for (k = 0; k < NAMELENGTH; k++) > >> + if ((*parsedOutput)[j].name[k] == ' ') > >> + break; > >> + (*parsedOutput)[j].name[k] = '\0'; > >> + i += NAMELENGTH; > >> + if (STREQLEN(output+i, STATERUNNINGSTRING, STATELENGTH)) (*parsedOutput)[j].state = STATERUNNING; > >> + else if (STREQLEN(output+i, STATESHUTDOWNSTRING, STATELENGTH)) (*parsedOutput)[j].state = STATESHUTDOWN; > >> + else if (STREQLEN(output+i, STATEFAILEDSTRING, STATELENGTH)) (*parsedOutput)[j].state = STATEFAILED; > >> + else if (STREQLEN(output+i, STATERUNNINGLOCKEDSTRING, STATELENGTH)) (*parsedOutput)[j].state = STATERUNNINGLOCKED; > >> + i += STATELENGTH; > >> + (*parsedOutput)[j].assignedCPUsLength = parseCPUs(output+i, &((*parsedOutput)[j].assignedCPUs)); > >> + i += CPULENGTH; > >> + (*parsedOutput)[j].failedCPUsLength = parseCPUs(output+i, &((*parsedOutput)[j].failedCPUs)); > >> + i += CPULENGTH; > >> + i++; // skip \n > >> + } > > > > It would be nice to include an example of the 'cell list' output to understand > > what this code is trying to parse. Then i migth be able to suggest a way > > to do this more simply. > > ID Name State Assigned CPUs Failed CPUs > 0 QEMU-VM running 0-3 So you could use virStringSplit once to break the output into lines and then use either virStringSplit a second time or a regex match to break each line into fields, splitting on space character. An alternative approach might be to use virCommandRunRegex which takes care of splitting output into lines, and uses a regex to split each line into fields. It just invokes a callback that gives you a list of the pieces for each line. I think either approach would probably be clearer that this code you have currently. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list