static int virSysinfoParseSystem(const char *base, virSysinfoDefPtr ret) { char *eol = NULL; const char *cur; if ((cur = strstr(base, "platform")) == NULL) return 0; base = cur; /* Account for format 'platform : XXXX'*/ cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(ret->system_family, cur, eol - cur) < 0) return -1; if ((cur = strstr(base, "model")) != NULL) { cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(ret->system_serial, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "machine")) != NULL) { cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(ret->system_version, cur, eol - cur) < 0) return -1; } return 0; }
/** * virConfParseString: * @ctxt: the parsing context * * Parse one string * * Returns a pointer to the string or NULL in case of error */ static char * virConfParseString(virConfParserCtxtPtr ctxt) { const char *base; char *ret = NULL; if (CUR == '\'') { NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (CUR != '\'') && (!IS_EOL(CUR))) NEXT; if (CUR != '\'') { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; NEXT; } else if ((ctxt->cur + 6 < ctxt->end) && (STRPREFIX(ctxt->cur, "\"\"\""))) { /* String starts with python-style triple quotes """ */ ctxt->cur += 3; base = ctxt->cur; /* Find the ending triple quotes */ while ((ctxt->cur + 2 < ctxt->end) && !(STRPREFIX(ctxt->cur, "\"\"\""))) { if (CUR == '\n') ctxt->line++; NEXT; } if (!STRPREFIX(ctxt->cur, "\"\"\"")) { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; ctxt->cur += 3; } else if (CUR == '"') { NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (CUR != '"') && (!IS_EOL(CUR))) NEXT; if (CUR != '"') { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; NEXT; } return ret; }
static int virSysinfoParseBIOS(const char *base, virSysinfoBIOSDefPtr *bios) { int ret = -1; const char *cur, *eol = NULL; virSysinfoBIOSDefPtr def; if ((cur = strstr(base, "BIOS Information")) == NULL) return 0; if (VIR_ALLOC(def) < 0) return ret; base = cur; if ((cur = strstr(base, "Vendor: ")) != NULL) { cur += 8; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(def->vendor, cur, eol - cur) < 0) goto cleanup; } if ((cur = strstr(base, "Version: ")) != NULL) { cur += 9; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(def->version, cur, eol - cur) < 0) goto cleanup; } if ((cur = strstr(base, "Release Date: ")) != NULL) { cur += 14; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(def->date, cur, eol - cur) < 0) goto cleanup; } if ((cur = strstr(base, "BIOS Revision: ")) != NULL) { cur += 15; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(def->release, cur, eol - cur) < 0) goto cleanup; } if (!def->vendor && !def->version && !def->date && !def->release) { virSysinfoBIOSDefFree(def); def = NULL; } *bios = def; def = NULL; ret = 0; cleanup: virSysinfoBIOSDefFree(def); return ret; }
static int virSysinfoParseSystem(const char *base, virSysinfoSystemDefPtr *sysdef) { int ret = -1; char *eol = NULL; const char *cur; virSysinfoSystemDefPtr def; if ((cur = strstr(base, "platform")) == NULL) return 0; if (VIR_ALLOC(def) < 0) return ret; base = cur; /* Account for format 'platform : XXXX'*/ cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(def->family, cur, eol - cur) < 0) goto cleanup; if ((cur = strstr(base, "model")) != NULL) { cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(def->serial, cur, eol - cur) < 0) goto cleanup; } if ((cur = strstr(base, "machine")) != NULL) { cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(def->version, cur, eol - cur) < 0) goto cleanup; } if (!def->manufacturer && !def->product && !def->version && !def->serial && !def->uuid && !def->sku && !def->family) { virSysinfoSystemDefFree(def); def = NULL; } *sysdef = def; def = NULL; ret = 0; cleanup: virSysinfoSystemDefFree(def); return ret; }
static int virSysinfoParseProcessor(const char *base, virSysinfoDefPtr ret) { const char *cur; char *eol, *tmp_base; virSysinfoProcessorDefPtr processor; char *processor_type = NULL; if (!(tmp_base = strstr(base, "Processor"))) return 0; base = tmp_base; eol = strchr(base, '\n'); cur = strchr(base, ':') + 1; virSkipSpaces(&cur); if (eol && VIR_STRNDUP(processor_type, cur, eol - cur) < 0) goto error; base = cur; while ((tmp_base = strstr(base, "processor")) != NULL) { base = tmp_base; eol = strchr(base, '\n'); cur = strchr(base, ':') + 1; if (VIR_EXPAND_N(ret->processor, ret->nprocessor, 1) < 0) goto error; processor = &ret->processor[ret->nprocessor - 1]; virSkipSpaces(&cur); if (eol && VIR_STRNDUP(processor->processor_socket_destination, cur, eol - cur) < 0) goto error; if (processor_type && VIR_STRDUP(processor->processor_type, processor_type) < 0) goto error; base = cur; } VIR_FREE(processor_type); return 0; error: VIR_FREE(processor_type); return -1; }
static int vmwareParsePath(const char *path, char **directory, char **filename) { char *separator; separator = strrchr(path, '/'); if (separator != NULL) { separator++; if (*separator == '\0') { virReportError(VIR_ERR_INTERNAL_ERROR, _("path '%s' doesn't reference a file"), path); return -1; } if (VIR_STRNDUP(*directory, path, separator - path - 1) < 0) goto error; if (VIR_STRDUP(*filename, separator) < 0) { VIR_FREE(*directory); goto error; } } else { if (VIR_STRDUP(*filename, path) < 0) goto error; } return 0; error: return -1; }
static int virJSONParserHandleNumber(void *ctx, const char *s, yajl_size_t l) { virJSONParserPtr parser = ctx; char *str; virJSONValuePtr value; if (VIR_STRNDUP(str, s, l) < 0) return -1; value = virJSONValueNewNumber(str); VIR_FREE(str); VIR_DEBUG("parser=%p str=%s", parser, str); if (!value) return 0; if (virJSONParserInsertValue(parser, value) < 0) { virJSONValueFree(value); return 0; } return 1; }
/** * virConfParseName: * @ctxt: the parsing context * * Parse one name * * Returns a copy of the new string, NULL in case of error */ static char * virConfParseName(virConfParserCtxtPtr ctxt) { const char *base; char *ret; SKIP_BLANKS; base = ctxt->cur; /* TODO: probably need encoding support and UTF-8 parsing ! */ if (!c_isalpha(CUR) && !((ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) && (CUR == '.'))) { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a name")); return NULL; } while ((ctxt->cur < ctxt->end) && (c_isalnum(CUR) || (CUR == '_') || ((ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) && ((CUR == ':') || (CUR == '.') || (CUR == '-'))) || ((ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) && (CUR == '.')))) NEXT; if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; return ret; }
int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, const char *name, ssize_t nameLen, virDomainCapsCPUUsable usable, char **blockers) { char *nameCopy = NULL; char **blockersCopy = NULL; if (VIR_STRNDUP(nameCopy, name, nameLen) < 0) goto error; if (virStringListCopy(&blockersCopy, (const char **)blockers) < 0) goto error; if (virDomainCapsCPUModelsAddSteal(cpuModels, &nameCopy, usable, &blockersCopy) < 0) goto error; return 0; error: VIR_FREE(nameCopy); virStringListFree(blockersCopy); return -1; }
static int virSysinfoParseProcessor(const char *base, virSysinfoDefPtr ret) { const char *cur; char *eol, *tmp_base; virSysinfoProcessorDefPtr processor; while ((tmp_base = strstr(base, "processor")) != NULL) { base = tmp_base; eol = strchr(base, '\n'); cur = strchr(base, ':') + 1; if (VIR_EXPAND_N(ret->processor, ret->nprocessor, 1) < 0) { return -1; } processor = &ret->processor[ret->nprocessor - 1]; virSkipSpaces(&cur); if (eol && VIR_STRNDUP(processor->processor_socket_destination, cur, eol - cur) < 0) return -1; if ((cur = strstr(base, "cpu")) != NULL) { cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(processor->processor_type, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "revision")) != NULL) { cur = strchr(cur, ':') + 1; eol = strchr(cur, '\n'); virSkipSpaces(&cur); if (eol && VIR_STRNDUP(processor->processor_version, cur, eol - cur) < 0) return -1; } base = cur; } return 0; }
static int bhyveParsePCISlot(const char *slotdef, unsigned *pcislot, unsigned *bus, unsigned *function) { /* slot[:function] | bus:slot:function */ const char *curr = NULL; const char *next = NULL; unsigned values[3]; size_t i; curr = slotdef; for (i = 0; i < 3; i++) { char *val = NULL; next = strchr(curr, ':'); if (VIR_STRNDUP(val, curr, next? next - curr : -1) < 0) goto error; if (virStrToLong_ui(val, NULL, 10, &values[i]) < 0) goto error; VIR_FREE(val); if (!next) break; curr = next +1; } *bus = 0; *pcislot = 0; *function = 0; switch (i + 1) { case 2: /* pcislot[:function] */ *function = values[1]; case 1: *pcislot = values[0]; break; case 3: /* bus:pcislot:function */ *bus = values[0]; *pcislot = values[1]; *function = values[2]; break; } return 0; error: return -1; }
static int virSysinfoParseSystem(const char *base, virSysinfoDefPtr ret) { const char *cur, *eol = NULL; if ((cur = strstr(base, "System Information")) == NULL) return 0; base = cur; if ((cur = strstr(base, "Manufacturer: ")) != NULL) { cur += 14; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->system_manufacturer, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Product Name: ")) != NULL) { cur += 14; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->system_product, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Version: ")) != NULL) { cur += 9; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->system_version, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Serial Number: ")) != NULL) { cur += 15; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->system_serial, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "UUID: ")) != NULL) { cur += 6; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->system_uuid, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "SKU Number: ")) != NULL) { cur += 12; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->system_sku, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Family: ")) != NULL) { cur += 8; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->system_family, cur, eol - cur) < 0) return -1; } return 0; }
/** * sexpr_string: * @str: the input string, assumed to be UTF-8 * @len: the length in bytes of the input * * Parse the input S-Expression and return a pointer to the result * * Returns the S-Expression pointer or NULL in case of error */ struct sexpr * sexpr_string(const char *str, ssize_t len) { struct sexpr *ret = sexpr_new(); if (ret == NULL) return ret; ret->kind = SEXPR_VALUE; if (VIR_STRNDUP(ret->u.value, str, len) < 0) VIR_FREE(ret); return ret; }
static int virSysinfoParseBIOS(const char *base, virSysinfoDefPtr ret) { const char *cur, *eol = NULL; if ((cur = strstr(base, "BIOS Information")) == NULL) return 0; base = cur; if ((cur = strstr(base, "Vendor: ")) != NULL) { cur += 8; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->bios_vendor, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Version: ")) != NULL) { cur += 9; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->bios_version, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Release Date: ")) != NULL) { cur += 14; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->bios_date, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "BIOS Revision: ")) != NULL) { cur += 15; eol = strchr(cur, '\n'); if (eol && VIR_STRNDUP(ret->bios_release, cur, eol - cur) < 0) return -1; } return 0; }
/** * virConfParseStatement: * @ctxt: the parsing context * * Parse one statement in the conf file * * Returns 0 in case of success and -1 in case of error */ static int virConfParseStatement(virConfParserCtxtPtr ctxt) { const char *base; char *name; virConfValuePtr value; char *comm = NULL; SKIP_BLANKS_AND_EOL; if (CUR == '#') { return virConfParseComment(ctxt); } name = virConfParseName(ctxt); if (name == NULL) return -1; SKIP_BLANKS; if (CUR != '=') { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting an assignment")); VIR_FREE(name); return -1; } NEXT; SKIP_BLANKS; value = virConfParseValue(ctxt); if (value == NULL) { VIR_FREE(name); return -1; } SKIP_BLANKS; if (CUR == '#') { NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (!IS_EOL(CUR))) NEXT; if (VIR_STRNDUP(comm, base, ctxt->cur - base) < 0) { VIR_FREE(name); virConfFreeValue(value); return -1; } } if (virConfAddEntry(ctxt->conf, name, value, comm) == NULL) { VIR_FREE(name); virConfFreeValue(value); VIR_FREE(comm); return -1; } return 0; }
virJSONValuePtr virJSONValueNewStringLen(const char *data, size_t length) { virJSONValuePtr val; if (!data) return virJSONValueNewNull(); if (VIR_ALLOC(val) < 0) return NULL; val->type = VIR_JSON_TYPE_STRING; if (VIR_STRNDUP(val->data.string, data, length) < 0) { VIR_FREE(val); return NULL; } return val; }
static int virJSONParserHandleMapKey(void *ctx, const unsigned char *stringVal, yajl_size_t stringLen) { virJSONParserPtr parser = ctx; virJSONParserStatePtr state; VIR_DEBUG("parser=%p key=%p", parser, (const char *)stringVal); if (!parser->nstate) return 0; state = &parser->state[parser->nstate-1]; if (state->key) return 0; if (VIR_STRNDUP(state->key, (const char *)stringVal, stringLen) < 0) return 0; return 1; }
/** * virConfParseComment: * @ctxt: the parsing context * * Parse one standalone comment in the configuration file * * Returns 0 in case of success and -1 in case of error */ static int virConfParseComment(virConfParserCtxtPtr ctxt) { const char *base; char *comm; if (CUR != '#') return -1; NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (!IS_EOL(CUR))) NEXT; if (VIR_STRNDUP(comm, base, ctxt->cur - base) < 0) return -1; if (virConfAddEntry(ctxt->conf, NULL, NULL, comm) == NULL) { VIR_FREE(comm); return -1; } return 0; }
static char * virSysinfoParseDelimited(const char *base, const char *name, char **value, char delim1, char delim2) { const char *start; char *end; if (delim1 != delim2 && (start = strstr(base, name)) && (start = strchr(start, delim1))) { start += 1; end = strchrnul(start, delim2); virSkipSpaces(&start); if (VIR_STRNDUP(*value, start, end - start) < 0) return NULL; virTrimSpaces(*value, NULL); return end; } return NULL; }
int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, const char *name, ssize_t nameLen, virDomainCapsCPUUsable usable) { char *copy = NULL; if (VIR_STRNDUP(copy, name, nameLen) < 0) goto error; if (virDomainCapsCPUModelsAddSteal(cpuModels, ©, usable) < 0) goto error; return 0; error: VIR_FREE(copy); return -1; }
static int virSysinfoParseMemory(const char *base, virSysinfoDefPtr ret) { const char *cur, *tmp_base; char *eol; virSysinfoMemoryDefPtr memory; while ((tmp_base = strstr(base, "Memory Device")) != NULL) { base = tmp_base; eol = NULL; if (VIR_EXPAND_N(ret->memory, ret->nmemory, 1) < 0) return -1; memory = &ret->memory[ret->nmemory - 1]; if ((cur = strstr(base, "Size: ")) != NULL) { cur += 6; eol = strchr(cur, '\n'); if (STREQLEN(cur, "No Module Installed", eol - cur)) goto next; virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_size, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Form Factor: ")) != NULL) { cur += 13; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_form_factor, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Locator: ")) != NULL) { cur += 9; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_locator, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Bank Locator: ")) != NULL) { cur += 14; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_bank_locator, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Type: ")) != NULL) { cur += 6; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_type, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Type Detail: ")) != NULL) { cur += 13; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_type_detail, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Speed: ")) != NULL) { cur += 7; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_speed, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Manufacturer: ")) != NULL) { cur += 14; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_manufacturer, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Serial Number: ")) != NULL) { cur += 15; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_serial_number, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Part Number: ")) != NULL) { cur += 13; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(memory->memory_part_number, cur, eol - cur) < 0) return -1; } next: base += strlen("Memory Device"); } return 0; }
static int virSysinfoParseProcessor(const char *base, virSysinfoDefPtr ret) { const char *cur, *tmp_base; char *eol; virSysinfoProcessorDefPtr processor; while ((tmp_base = strstr(base, "Processor Information")) != NULL) { base = tmp_base; eol = NULL; if (VIR_EXPAND_N(ret->processor, ret->nprocessor, 1) < 0) return -1; processor = &ret->processor[ret->nprocessor - 1]; if ((cur = strstr(base, "Socket Designation: ")) != NULL) { cur += 20; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_socket_destination, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Type: ")) != NULL) { cur += 6; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_type, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Family: ")) != NULL) { cur += 8; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_family, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Manufacturer: ")) != NULL) { cur += 14; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_manufacturer, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Signature: ")) != NULL) { cur += 11; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_signature, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Version: ")) != NULL) { cur += 9; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_version, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "External Clock: ")) != NULL) { cur += 16; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_external_clock, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Max Speed: ")) != NULL) { cur += 11; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_max_speed, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Status: ")) != NULL) { cur += 8; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_status, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Serial Number: ")) != NULL) { cur += 15; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_serial_number, cur, eol - cur) < 0) return -1; } if ((cur = strstr(base, "Part Number: ")) != NULL) { cur += 13; eol = strchr(cur, '\n'); virSkipSpacesBackwards(cur, &eol); if (eol && VIR_STRNDUP(processor->processor_part_number, cur, eol - cur) < 0) return -1; } base += strlen("Processor Information"); } return 0; }
static int bhyveParseBhyvePCIArg(virDomainDefPtr def, virDomainXMLOptionPtr xmlopt, unsigned caps, unsigned *nvirtiodisk, unsigned *nahcidisk, const char *arg) { /* -s slot,emulation[,conf] */ const char *separator = NULL; char *slotdef = NULL; char *emulation = NULL; char *conf = NULL; unsigned pcislot, bus, function; separator = strchr(arg, ','); if (!separator) goto error; else separator++; /* Skip comma */ if (VIR_STRNDUP(slotdef, arg, separator - arg - 1) < 0) goto error; conf = strchr(separator+1, ','); if (conf) conf++; /* Skip initial comma */ if (VIR_STRNDUP(emulation, separator, conf? conf - separator - 1 : -1) < 0) goto error; if (bhyveParsePCISlot(slotdef, &pcislot, &bus, &function) < 0) goto error; if (STREQ(emulation, "ahci-cd")) bhyveParsePCIDisk(def, caps, pcislot, bus, function, VIR_DOMAIN_DISK_BUS_SATA, VIR_DOMAIN_DISK_DEVICE_CDROM, nvirtiodisk, nahcidisk, conf); else if (STREQ(emulation, "ahci-hd")) bhyveParsePCIDisk(def, caps, pcislot, bus, function, VIR_DOMAIN_DISK_BUS_SATA, VIR_DOMAIN_DISK_DEVICE_DISK, nvirtiodisk, nahcidisk, conf); else if (STREQ(emulation, "virtio-blk")) bhyveParsePCIDisk(def, caps, pcislot, bus, function, VIR_DOMAIN_DISK_BUS_VIRTIO, VIR_DOMAIN_DISK_DEVICE_DISK, nvirtiodisk, nahcidisk, conf); else if (STREQ(emulation, "virtio-net")) bhyveParsePCINet(def, xmlopt, caps, pcislot, bus, function, conf); VIR_FREE(emulation); VIR_FREE(slotdef); return 0; error: VIR_FREE(emulation); VIR_FREE(slotdef); return -1; }
static int virStorageBackendIQNFound(const char *initiatoriqn, char **ifacename) { int ret = IQN_MISSING, fd = -1; char ebuf[64]; FILE *fp = NULL; char *line = NULL, *newline = NULL, *iqn = NULL, *token = NULL; virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "iface", NULL); if (VIR_ALLOC_N(line, LINE_SIZE) != 0) { ret = IQN_ERROR; virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not allocate memory for output of '%s'"), ISCSIADM); goto out; } memset(line, 0, LINE_SIZE); virCommandSetOutputFD(cmd, &fd); if (virCommandRunAsync(cmd, NULL) < 0) { ret = IQN_ERROR; goto out; } if ((fp = VIR_FDOPEN(fd, "r")) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to open stream for file descriptor " "when reading output from '%s': '%s'"), ISCSIADM, virStrerror(errno, ebuf, sizeof(ebuf))); ret = IQN_ERROR; goto out; } while (fgets(line, LINE_SIZE, fp) != NULL) { newline = strrchr(line, '\n'); if (newline == NULL) { ret = IQN_ERROR; virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected line > %d characters " "when parsing output of '%s'"), LINE_SIZE, ISCSIADM); goto out; } *newline = '\0'; iqn = strrchr(line, ','); if (iqn == NULL) continue; iqn++; if (STREQ(iqn, initiatoriqn)) { token = strchr(line, ' '); if (!token) { ret = IQN_ERROR; virReportError(VIR_ERR_INTERNAL_ERROR, _("Missing space when parsing output " "of '%s'"), ISCSIADM); goto out; } if (VIR_STRNDUP(*ifacename, line, token - line) < 0) { ret = IQN_ERROR; goto out; } VIR_DEBUG("Found interface '%s' with IQN '%s'", *ifacename, iqn); ret = IQN_FOUND; break; } } if (virCommandWait(cmd, NULL) < 0) ret = IQN_ERROR; out: if (ret == IQN_MISSING) VIR_DEBUG("Could not find interface with IQN '%s'", iqn); VIR_FREE(line); VIR_FORCE_FCLOSE(fp); VIR_FORCE_CLOSE(fd); virCommandFree(cmd); return ret; }
/** * virStringSearch: * @str: string to search * @regexp: POSIX Extended regular expression pattern used for matching * @max_matches: maximum number of substrings to return * @result: pointer to an array to be filled with NULL terminated list of matches * * Performs a POSIX extended regex search against a string and return all matching substrings. * The @result value should be freed with virStringListFree() when no longer * required. * * @code * char *source = "6853a496-1c10-472e-867a-8244937bd6f0 * 773ab075-4cd7-4fc2-8b6e-21c84e9cb391 * bbb3c75c-d60f-43b0-b802-fd56b84a4222 * 60c04aa1-0375-4654-8d9f-e149d9885273 * 4548d465-9891-4c34-a184-3b1c34a26aa8"; * char **matches = NULL; * virStringSearch(source, * "([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})", * 3, * &matches); * * // matches[0] == "6853a496-1c10-472e-867a-8244937bd6f0"; * // matches[1] == "773ab075-4cd7-4fc2-8b6e-21c84e9cb391"; * // matches[2] == "bbb3c75c-d60f-43b0-b802-fd56b84a4222" * // matches[3] == NULL; * * virStringListFree(matches); * @endcode * * Returns: -1 on error, or number of matches */ ssize_t virStringSearch(const char *str, const char *regexp, size_t max_matches, char ***matches) { regex_t re; regmatch_t rem; size_t nmatches = 0; ssize_t ret = -1; int rv = -1; *matches = NULL; VIR_DEBUG("search '%s' for '%s'", str, regexp); if ((rv = regcomp(&re, regexp, REG_EXTENDED)) != 0) { char error[100]; regerror(rv, &re, error, sizeof(error)); virReportError(VIR_ERR_INTERNAL_ERROR, _("Error while compiling regular expression '%s': %s"), regexp, error); return -1; } if (re.re_nsub != 1) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Regular expression '%s' must have exactly 1 match group, not %zu"), regexp, re.re_nsub); goto cleanup; } /* '*matches' must always be NULL terminated in every iteration * of the loop, so start by allocating 1 element */ if (VIR_EXPAND_N(*matches, nmatches, 1) < 0) goto cleanup; while ((nmatches - 1) < max_matches) { char *match; if (regexec(&re, str, 1, &rem, 0) != 0) break; if (VIR_EXPAND_N(*matches, nmatches, 1) < 0) goto cleanup; if (VIR_STRNDUP(match, str + rem.rm_so, rem.rm_eo - rem.rm_so) < 0) goto cleanup; VIR_DEBUG("Got '%s'", match); (*matches)[nmatches-2] = match; str = str + rem.rm_eo; } ret = nmatches - 1; /* don't count the trailing null */ cleanup: regfree(&re); if (ret < 0) { virStringListFree(*matches); *matches = NULL; } return ret; }
static int bhyveParsePCIDisk(virDomainDefPtr def, unsigned caps ATTRIBUTE_UNUSED, unsigned pcislot, unsigned pcibus, unsigned function, int bus, int device, unsigned *nvirtiodisk, unsigned *nahcidisk, char *config) { /* -s slot,virtio-blk|ahci-cd|ahci-hd,/path/to/file */ const char *separator = NULL; int idx = -1; virDomainDiskDefPtr disk = NULL; if (VIR_ALLOC(disk) < 0) goto cleanup; if (VIR_ALLOC(disk->src) < 0) goto error; disk->bus = bus; disk->device = device; disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; disk->info.addr.pci.slot = pcislot; disk->info.addr.pci.bus = pcibus; disk->info.addr.pci.function = function; if (STRPREFIX(config, "/dev/")) disk->src->type = VIR_STORAGE_TYPE_BLOCK; else disk->src->type = VIR_STORAGE_TYPE_FILE; if (!config) goto error; separator = strchr(config, ','); if (VIR_STRNDUP(disk->src->path, config, separator? separator - config : -1) < 0) goto error; if (bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { idx = *nvirtiodisk; *nvirtiodisk += 1; if (VIR_STRDUP(disk->dst, "vda") < 0) goto error; } else if (bus == VIR_DOMAIN_DISK_BUS_SATA) { idx = *nahcidisk; *nahcidisk += 1; if (VIR_STRDUP(disk->dst, "sda") < 0) goto error; } if (idx > 'z' - 'a') { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("too many disks")); goto error; } disk->dst[2] = 'a' + idx; if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) goto error; cleanup: return 0; error: virDomainDiskDefFree(disk); return -1; }
static int bhyveParsePCINet(virDomainDefPtr def, virDomainXMLOptionPtr xmlopt, unsigned caps ATTRIBUTE_UNUSED, unsigned pcislot, unsigned pcibus, unsigned function, const char *config) { /* -s slot,virtio-net,tapN[,mac=xx:xx:xx:xx:xx:xx] */ virDomainNetDefPtr net = NULL; const char *separator = NULL; const char *mac = NULL; if (VIR_ALLOC(net) < 0) goto cleanup; /* Let's just assume it is VIR_DOMAIN_NET_TYPE_ETHERNET, it could also be * a bridge, but this is the most generic option. */ net->type = VIR_DOMAIN_NET_TYPE_ETHERNET; net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; net->info.addr.pci.slot = pcislot; net->info.addr.pci.bus = pcibus; net->info.addr.pci.function = function; if (!config) goto error; if (!STRPREFIX(config, "tap")) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only tap devices supported")); goto error; } separator = strchr(config, ','); if (VIR_STRNDUP(net->ifname, config, separator? separator - config : -1) < 0) goto error; if (!separator) goto cleanup; if (!STRPREFIX(++separator, "mac=")) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only mac option can be specified for virt-net")); goto error; } mac = separator + 4; if (virMacAddrParse(mac, &net->mac) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to parse mac address '%s'"), mac); goto cleanup; } cleanup: if (!mac) virDomainNetGenerateMAC(xmlopt, &net->mac); if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0) goto error; return 0; error: virDomainNetDefFree(net); return -1; }
/** * _string2sexpr: * @buffer: a zero terminated buffer containing an S-Expression in UTF-8 * @end: pointer to an index in the buffer for the already parsed bytes * * Internal routine implementing the parse of S-Expression * Note that failure in this function is catastrophic. If it returns * NULL, you've leaked memory and you're currently OOM. It will always * parse an SEXPR given a buffer * * Returns a pointer to the resulting parsed S-Expression, or NULL in case of * hard error. */ static struct sexpr * _string2sexpr(const char *buffer, size_t * end) { const char *ptr = buffer + *end; struct sexpr *ret = sexpr_new(); if (ret == NULL) return NULL; ptr = trim(ptr); if (ptr[0] == '(') { ret->kind = SEXPR_NIL; ptr = trim(ptr + 1); while (*ptr && *ptr != ')') { struct sexpr *tmp; size_t tmp_len = 0; tmp = _string2sexpr(ptr, &tmp_len); if (tmp == NULL) goto error; if (append(ret, tmp) < 0) { sexpr_free(tmp); goto error; } ptr = trim(ptr + tmp_len); } if (*ptr == ')') { ptr++; } } else { const char *start; if (*ptr == '\'') { ptr++; start = ptr; while (*ptr && *ptr != '\'') { if (*ptr == '\\' && ptr[1]) ptr++; ptr++; } if (VIR_STRNDUP(ret->u.value, start, ptr - start) < 0) goto error; if (*ptr == '\'') ptr++; } else { start = ptr; while (*ptr && !c_isspace(*ptr) && *ptr != ')' && *ptr != '(') { ptr++; } if (VIR_STRNDUP(ret->u.value, start, ptr - start) < 0) goto error; } ret->kind = SEXPR_VALUE; if (ret->u.value == NULL) goto error; } *end = ptr - buffer; return ret; error: sexpr_free(ret); return NULL; }
static int virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool, char **const groups, void *data) { virStorageVolDefPtr vol = NULL; bool is_new_vol = false; unsigned long long offset, size, length; const char *regex_unit = "(\\S+)\\((\\S+)\\)"; char *regex = NULL; regex_t *reg = NULL; regmatch_t *vars = NULL; char *p = NULL; size_t i; int err, nextents, nvars, ret = -1; const char *attrs = groups[9]; /* Skip inactive volume */ if (attrs[4] != 'a') return 0; /* * Skip thin pools(t). These show up in normal lvs output * but do not have a corresponding /dev/$vg/$lv device that * is created by udev. This breaks assumptions in later code. */ if (attrs[0] == 't') return 0; /* See if we're only looking for a specific volume */ if (data != NULL) { vol = data; if (STRNEQ(vol->name, groups[0])) return 0; } /* Or filling in more data on an existing volume */ if (vol == NULL) vol = virStorageVolDefFindByName(pool, groups[0]); /* Or a completely new volume */ if (vol == NULL) { if (VIR_ALLOC(vol) < 0) return -1; is_new_vol = true; vol->type = VIR_STORAGE_VOL_BLOCK; if (VIR_STRDUP(vol->name, groups[0]) < 0) goto cleanup; if (VIR_REALLOC_N(pool->volumes.objs, pool->volumes.count + 1)) goto cleanup; } if (vol->target.path == NULL) { if (virAsprintf(&vol->target.path, "%s/%s", pool->def->target.path, vol->name) < 0) goto cleanup; } /* Skips the backingStore of lv created with "--virtualsize", * its original device "/dev/$vgname/$lvname_vorigin" is * just for lvm internal use, one should never use it. * * (lvs outputs "[$lvname_vorigin] for field "origin" if the * lv is created with "--virtualsize"). */ if (groups[1] && !STREQ(groups[1], "") && (groups[1][0] != '[')) { if (virAsprintf(&vol->backingStore.path, "%s/%s", pool->def->target.path, groups[1]) < 0) goto cleanup; vol->backingStore.format = VIR_STORAGE_POOL_LOGICAL_LVM2; } if (!vol->key && VIR_STRDUP(vol->key, groups[2]) < 0) goto cleanup; if (virStorageBackendUpdateVolInfo(vol, 1) < 0) goto cleanup; nextents = 1; if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) { if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent stripes value")); goto cleanup; } } /* Finally fill in extents information */ if (VIR_REALLOC_N(vol->source.extents, vol->source.nextent + nextents) < 0) goto cleanup; if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent length value")); goto cleanup; } if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent size value")); goto cleanup; } if (virStrToLong_ull(groups[8], NULL, 10, &vol->allocation) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume allocation value")); goto cleanup; } /* Now parse the "devices" field separately */ if (VIR_STRDUP(regex, regex_unit) < 0) goto cleanup; for (i = 1; i < nextents; i++) { if (VIR_REALLOC_N(regex, strlen(regex) + strlen(regex_unit) + 2) < 0) goto cleanup; /* "," is the separator of "devices" field */ strcat(regex, ","); strncat(regex, regex_unit, strlen(regex_unit)); } if (VIR_ALLOC(reg) < 0) goto cleanup; /* Each extent has a "path:offset" pair, and vars[0] will * be the whole matched string. */ nvars = (nextents * 2) + 1; if (VIR_ALLOC_N(vars, nvars) < 0) goto cleanup; err = regcomp(reg, regex, REG_EXTENDED); if (err != 0) { char error[100]; regerror(err, reg, error, sizeof(error)); virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to compile regex %s"), error); goto cleanup; } err = regexec(reg, groups[3], nvars, vars, 0); regfree(reg); if (err != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent devices value")); goto cleanup; } p = groups[3]; /* vars[0] is skipped */ for (i = 0; i < nextents; i++) { size_t j; int len; char *offset_str = NULL; j = (i * 2) + 1; len = vars[j].rm_eo - vars[j].rm_so; p[vars[j].rm_eo] = '\0'; if (VIR_STRNDUP(vol->source.extents[vol->source.nextent].path, p + vars[j].rm_so, len) < 0) goto cleanup; len = vars[j + 1].rm_eo - vars[j + 1].rm_so; if (VIR_STRNDUP(offset_str, p + vars[j + 1].rm_so, len) < 0) goto cleanup; if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent offset value")); VIR_FREE(offset_str); goto cleanup; } VIR_FREE(offset_str); vol->source.extents[vol->source.nextent].start = offset * size; vol->source.extents[vol->source.nextent].end = (offset * size) + length; vol->source.nextent++; } if (is_new_vol) pool->volumes.objs[pool->volumes.count++] = vol; ret = 0; cleanup: VIR_FREE(regex); VIR_FREE(reg); VIR_FREE(vars); if (is_new_vol && (ret == -1)) virStorageVolDefFree(vol); return ret; }
/** * virConfParseString: * @ctxt: the parsing context * * Parse one string * * Returns a pointer to the string or NULL in case of error */ static char * virConfParseString(virConfParserCtxtPtr ctxt) { const char *base; char *ret = NULL; if (CUR == '\'') { NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (CUR != '\'') && (!IS_EOL(CUR))) NEXT; if (CUR != '\'') { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; NEXT; } else if ((ctxt->cur + 6 < ctxt->end) && (STRPREFIX(ctxt->cur, "\"\"\""))) { /* String starts with python-style triple quotes """ */ ctxt->cur += 3; base = ctxt->cur; /* Find the ending triple quotes */ while ((ctxt->cur + 2 < ctxt->end) && !(STRPREFIX(ctxt->cur, "\"\"\""))) { if (CUR == '\n') ctxt->line++; NEXT; } if (!STRPREFIX(ctxt->cur, "\"\"\"")) { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; ctxt->cur += 3; } else if (CUR == '"') { NEXT; base = ctxt->cur; while ((ctxt->cur < ctxt->end) && (CUR != '"') && (!IS_EOL(CUR))) NEXT; if (CUR != '"') { virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("unterminated string")); return NULL; } if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; NEXT; } else if (ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) { base = ctxt->cur; /* LXC config format doesn't support comments after the value */ while ((ctxt->cur < ctxt->end) && (!IS_EOL(CUR))) NEXT; /* Reverse to exclude the trailing blanks from the value */ while ((ctxt->cur > base) && (c_isblank(CUR))) ctxt->cur--; if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0) return NULL; } return ret; }