static int testRemove(const void *args) { const struct testSplitData *data = args; char **list = NULL; size_t ntokens; size_t i; int ret = -1; if (!(list = virStringSplitCount(data->string, data->delim, data->max_tokens, &ntokens))) { VIR_DEBUG("Got no tokens at all"); return -1; } for (i = 0; data->tokens[i]; i++) { virStringListRemove(&list, data->tokens[i]); if (virStringListHasString((const char **) list, data->tokens[i])) { virFilePrintf(stderr, "Not removed %s", data->tokens[i]); goto cleanup; } } if (list && list[0]) { virFilePrintf(stderr, "Not removed all tokens: %s", list[0]); goto cleanup; } ret = 0; cleanup: virStringListFree(list); return ret; }
/* Parse config values of the form barrier:limit into barrier and limit */ static int openvzParseBarrierLimit(const char* value, unsigned long long *barrier, unsigned long long *limit) { char **tmp = NULL; size_t ntmp = 0; int ret = -1; if (!(tmp = virStringSplitCount(value, ":", 0, &ntmp))) goto error; if (ntmp != 2) goto error; if (barrier && virStrToLong_ull(tmp[0], NULL, 10, barrier) < 0) goto error; if (limit && virStrToLong_ull(tmp[1], NULL, 10, limit) < 0) goto error; ret = 0; error: virStringFreeListCount(tmp, ntmp); return ret; }
static int testSplit(const void *args) { const struct testSplitData *data = args; char **got; size_t ntokens; size_t exptokens = 0; char **tmp1; const char **tmp2; int ret = -1; if (!(got = virStringSplitCount(data->string, data->delim, data->max_tokens, &ntokens))) { VIR_DEBUG("Got no tokens at all"); return -1; } tmp1 = got; tmp2 = data->tokens; while (*tmp1 && *tmp2) { if (STRNEQ(*tmp1, *tmp2)) { virFilePrintf(stderr, "Mismatch '%s' vs '%s'\n", *tmp1, *tmp2); goto cleanup; } tmp1++; tmp2++; exptokens++; } if (*tmp1) { virFilePrintf(stderr, "Too many pieces returned\n"); goto cleanup; } if (*tmp2) { virFilePrintf(stderr, "Too few pieces returned\n"); goto cleanup; } if (ntokens != exptokens) { virFilePrintf(stderr, "Returned token count (%zu) doesn't match " "expected count (%zu)", ntokens, exptokens); goto cleanup; } ret = 0; cleanup: virStringListFree(got); return ret; }
static int virStorageBackendZFSParseVol(virStoragePoolObjPtr pool, virStorageVolDefPtr vol, const char *volume_string) { int ret = -1; char **tokens; size_t count; char **name_tokens = NULL; char *vol_name; bool is_new_vol = false; virStorageVolDefPtr volume = NULL; if (!(tokens = virStringSplitCount(volume_string, "\t", 0, &count))) return -1; if (count != 2) goto cleanup; if (!(name_tokens = virStringSplit(tokens[0], "/", 2))) goto cleanup; vol_name = name_tokens[1]; if (vol == NULL) volume = virStorageVolDefFindByName(pool, vol_name); else volume = vol; if (volume == NULL) { if (VIR_ALLOC(volume) < 0) goto cleanup; is_new_vol = true; volume->type = VIR_STORAGE_VOL_BLOCK; if (VIR_STRDUP(volume->name, vol_name) < 0) goto cleanup; } if (!volume->key && VIR_STRDUP(volume->key, tokens[0]) < 0) goto cleanup; if (volume->target.path == NULL) { if (virAsprintf(&volume->target.path, "%s/%s", pool->def->target.path, volume->name) < 0) goto cleanup; } if (virStrToLong_ull(tokens[1], NULL, 10, &volume->target.capacity) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volsize reported")); goto cleanup; } if (is_new_vol && VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, volume) < 0) goto cleanup; ret = 0; cleanup: virStringFreeList(tokens); virStringFreeList(name_tokens); if (is_new_vol) virStorageVolDefFree(volume); return ret; }
static int virStorageBackendZFSRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool ATTRIBUTE_UNUSED) { virCommandPtr cmd = NULL; char *zpool_props = NULL; char **lines = NULL; char **tokens = NULL; size_t i; /** * $ zpool get -Hp health,size,free,allocated test * test health ONLINE - * test size 199715979264 - * test free 198899976704 - * test allocated 816002560 - * $ * * Here we just provide a list of properties we want to see */ cmd = virCommandNewArgList(ZPOOL, "get", "-Hp", "health,size,free,allocated", pool->def->source.name, NULL); virCommandSetOutputBuffer(cmd, &zpool_props); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (!(lines = virStringSplit(zpool_props, "\n", 0))) goto cleanup; for (i = 0; lines[i]; i++) { size_t count; char *prop_name; if (STREQ(lines[i], "")) continue; virStringFreeList(tokens); if (!(tokens = virStringSplitCount(lines[i], "\t", 0, &count))) goto cleanup; if (count != 4) continue; prop_name = tokens[1]; if (STREQ(prop_name, "free") || STREQ(prop_name, "size") || STREQ(prop_name, "allocated")) { unsigned long long value; if (virStrToLong_ull(tokens[2], NULL, 10, &value) < 0) goto cleanup; if (STREQ(prop_name, "free")) pool->def->available = value; else if (STREQ(prop_name, "size")) pool->def->capacity = value; else if (STREQ(prop_name, "allocated")) pool->def->allocation = value; } } /* Obtain a list of volumes */ if (virStorageBackendZFSFindVols(pool, NULL) < 0) goto cleanup; cleanup: virCommandFree(cmd); virStringFreeList(lines); virStringFreeList(tokens); VIR_FREE(zpool_props); return 0; }
static int lxctoolsReadFSConfig(lxctoolsConffilePtr conffile, virDomainDefPtr def) { virDomainFSDefPtr fs = NULL; char* item_str = NULL; size_t tokencnt; char** splitlist = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.rootfs.path")) == NULL || item_str[0] == '\0') { VIR_WARN("Could not find key lxc.rootfs.path. Trying legacy key lxc.rootfs."); if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.rootfs")) == NULL) { VIR_ERROR("Could not find key lxc.rootfs"); goto error; } } if (item_str[0] == '\0') { VIR_ERROR("Domain has no rootfs config-item."); goto error; } if (VIR_ALLOC(fs) < 0) { VIR_ERROR("Could not allocate for virDomainFSDefPtr fs."); goto error; } fs->type = VIR_DOMAIN_FS_TYPE_MOUNT; if (VIR_ALLOC(fs->src) < 0) { VIR_ERROR("Could not allocate for virStorageSourcePtr fs->src."); goto error; } splitlist = virStringSplitCount(item_str, ":", 3, &tokencnt); // Simple path if (tokencnt == 1) { fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH; if (virAsprintf(&fs->src->path, "dir:%s", splitlist[0]) < 0) { VIR_ERROR("Could not print string in fs->src->path."); goto error; } // dir } else if (tokencnt == 2 && strcmp(splitlist[0], "dir") == 0) { fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH; if (virAsprintf(&fs->src->path, "%s:%s", splitlist[0], splitlist[1]) < 0) { VIR_ERROR("Could not print string in fs->src->path."); goto error; } // overlay or overlayfs } else if (tokencnt == 3 && (strcmp(splitlist[0], "overlay") == 0 || strcmp(splitlist[0], "overlayfs") == 0)) { // We could add a new FS type like VIR_DOMAIN_FS_DRIVER_TYPE_OVERLAY, but this requires minor changes in the // libvirt interface and the qemu driver. // Also, we could either save "lowerdir:upperdir" in fs->src or create additional members to hold each seperately // splitlist[0] -> overlayfs/overlay // splitlist[1] -> lowerdir path // splitlist[2] -> upperdir path // For now, this implements overlayfs using VIR_DOMAIN_FS_DRIVER_TYPE_PATH and saving "overlayfs:lowerdir:upperdir" // in fs->src, which does not require lxctools external changes, but is a little bit ugly. fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH; if (virAsprintf(&fs->src->path, "%s:%s:%s", splitlist[0], splitlist[1], splitlist[2]) < 0) { VIR_ERROR("Could not print string in fs->src->path."); goto error; } } else { VIR_ERROR("Domain rootfs type is currently not supported"); goto error; } if (VIR_STRDUP(fs->dst, "/") != 1) { VIR_ERROR("Could not duplicate string."); goto error; } if (virDomainFSInsert(def, fs) < 0) { VIR_ERROR("Could not insert filesystem desc into domain."); goto error; } fs = NULL; VIR_FREE(item_str); virStringListFree(splitlist); splitlist = NULL; if ((splitlist = lxctoolsConffileGetItemlist(conffile, "lxc.mount.entry", &tokencnt)) == NULL) { goto error; } if (splitlist[0] != NULL) { size_t param_cnt; char** params; while (tokencnt-- > 0) { params = virStringSplitCount(splitlist[tokencnt], " ", 6, ¶m_cnt); if (param_cnt != 6) { VIR_ERROR("The following entry has to few parameters: '%s'", splitlist[tokencnt]); goto error; } if (VIR_ALLOC(fs) < 0) { VIR_ERROR("Could not allocate for virDomainFSDefPtr fs."); goto error; } if (strcmp(params[2], "none") == 0 && strstr(params[3],"bind") != NULL) { fs->type = VIR_DOMAIN_FS_TYPE_MOUNT; fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PATH; if (VIR_ALLOC(fs->src) < 0) { VIR_ERROR("Could not allocate for virStorageSourcePtr fs->src."); goto error; } if (VIR_STRDUP(fs->src->path, params[0]) < 0) { VIR_ERROR("Could not copy src string."); goto error; } if (virAsprintf(&fs->dst, "/%s", params[1]) < 0) { VIR_ERROR("Could not copy dst string."); goto error; } if (strstr(params[3], "ro") != NULL) { fs->readonly = true; } if (virDomainFSInsert(def, fs) < 0) { VIR_ERROR("Could not insert filesystem desc into domain."); goto error; } fs = NULL; } VIR_FREE(fs); virStringListFree(params); } virStringListFree(splitlist); splitlist = NULL; } return 0; error: virStringListFree(splitlist); splitlist = NULL; VIR_FREE(item_str); if (fs) VIR_FREE(fs->src); VIR_FREE(fs); return -1; }