static int qemu_rbd_set_conf(rados_t cluster, const char *conf, bool only_read_conf_file, Error **errp) { char *p, *buf; char name[RBD_MAX_CONF_NAME_SIZE]; char value[RBD_MAX_CONF_VAL_SIZE]; int ret = 0; buf = g_strdup(conf); p = buf; while (p) { ret = qemu_rbd_next_tok(name, sizeof(name), p, '=', "conf option name", &p, errp); if (ret < 0) { break; } qemu_rbd_unescape(name); if (!p) { error_setg(errp, "conf option %s has no value", name); ret = -EINVAL; break; } ret = qemu_rbd_next_tok(value, sizeof(value), p, ':', "conf option value", &p, errp); if (ret < 0) { break; } qemu_rbd_unescape(value); if (strcmp(name, "conf") == 0) { /* read the conf file alone, so it doesn't override more specific settings for a particular device */ if (only_read_conf_file) { ret = rados_conf_read_file(cluster, value); if (ret < 0) { error_setg_errno(errp, -ret, "error reading conf file %s", value); break; } } } else if (strcmp(name, "id") == 0) { /* ignore, this is parsed by qemu_rbd_parse_clientname() */ } else if (!only_read_conf_file) { ret = rados_conf_set(cluster, name, value); if (ret < 0) { error_setg_errno(errp, -ret, "invalid conf option %s", name); ret = -EINVAL; break; } } } g_free(buf); return ret; }
static int qemu_rbd_parsename(const char *filename, char *pool, int pool_len, char *snap, int snap_len, char *name, int name_len, char *conf, int conf_len, Error **errp) { const char *start; char *p, *buf; int ret; if (!strstart(filename, "rbd:", &start)) { error_setg(errp, "File name must start with 'rbd:'"); return -EINVAL; } buf = g_strdup(start); p = buf; *snap = '\0'; *conf = '\0'; ret = qemu_rbd_next_tok(pool, pool_len, p, '/', "pool name", &p, errp); if (ret < 0 || !p) { ret = -EINVAL; goto done; } qemu_rbd_unescape(pool); if (strchr(p, '@')) { ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p, errp); if (ret < 0) { goto done; } ret = qemu_rbd_next_tok(snap, snap_len, p, ':', "snap name", &p, errp); qemu_rbd_unescape(snap); } else { ret = qemu_rbd_next_tok(name, name_len, p, ':', "object name", &p, errp); } qemu_rbd_unescape(name); if (ret < 0 || !p) { goto done; } ret = qemu_rbd_next_tok(conf, conf_len, p, '\0', "configuration", &p, errp); done: g_free(buf); return ret; }
static int qemu_rbd_set_conf(rados_t cluster, const char *conf) { char *p, *buf; char name[RBD_MAX_CONF_NAME_SIZE]; char value[RBD_MAX_CONF_VAL_SIZE]; int ret = 0; buf = g_strdup(conf); p = buf; while (p) { ret = qemu_rbd_next_tok(name, sizeof(name), p, '=', "conf option name", &p); if (ret < 0) { break; } qemu_rbd_unescape(name); if (!p) { error_report("conf option %s has no value", name); ret = -EINVAL; break; } ret = qemu_rbd_next_tok(value, sizeof(value), p, ':', "conf option value", &p); if (ret < 0) { break; } qemu_rbd_unescape(value); if (strcmp(name, "conf") == 0) { ret = rados_conf_read_file(cluster, value); if (ret < 0) { error_report("error reading conf file %s", value); break; } } else if (strcmp(name, "id") == 0) { /* ignore, this is parsed by qemu_rbd_parse_clientname() */ } else { ret = rados_conf_set(cluster, name, value); if (ret < 0) { error_report("invalid conf option %s", name); ret = -EINVAL; break; } } } g_free(buf); return ret; }
static void qemu_rbd_parse_filename(const char *filename, QDict *options, Error **errp) { const char *start; char *p, *buf; QList *keypairs = NULL; char *found_str; if (!strstart(filename, "rbd:", &start)) { error_setg(errp, "File name must start with 'rbd:'"); return; } buf = g_strdup(start); p = buf; found_str = qemu_rbd_next_tok(p, '/', &p); if (!p) { error_setg(errp, "Pool name is required"); goto done; } qemu_rbd_unescape(found_str); qdict_put_str(options, "pool", found_str); if (strchr(p, '@')) { found_str = qemu_rbd_next_tok(p, '@', &p); qemu_rbd_unescape(found_str); qdict_put_str(options, "image", found_str); found_str = qemu_rbd_next_tok(p, ':', &p); qemu_rbd_unescape(found_str); qdict_put_str(options, "snapshot", found_str); } else { found_str = qemu_rbd_next_tok(p, ':', &p); qemu_rbd_unescape(found_str); qdict_put_str(options, "image", found_str); } if (!p) { goto done; } /* The following are essentially all key/value pairs, and we treat * 'id' and 'conf' a bit special. Key/value pairs may be in any order. */ while (p) { char *name, *value; name = qemu_rbd_next_tok(p, '=', &p); if (!p) { error_setg(errp, "conf option %s has no value", name); break; } qemu_rbd_unescape(name); value = qemu_rbd_next_tok(p, ':', &p); qemu_rbd_unescape(value); if (!strcmp(name, "conf")) { qdict_put_str(options, "conf", value); } else if (!strcmp(name, "id")) { qdict_put_str(options, "user", value); } else { /* * We pass these internally to qemu_rbd_set_keypairs(), so * we can get away with the simpler list of [ "key1", * "value1", "key2", "value2" ] rather than a raw dict * { "key1": "value1", "key2": "value2" } where we can't * guarantee order, or even a more correct but complex * [ { "key1": "value1" }, { "key2": "value2" } ] */ if (!keypairs) { keypairs = qlist_new(); } qlist_append_str(keypairs, name); qlist_append_str(keypairs, value); } } if (keypairs) { qdict_put(options, "=keyvalue-pairs", qobject_to_json(QOBJECT(keypairs))); } done: g_free(buf); QDECREF(keypairs); return; }
static void qemu_rbd_parse_filename(const char *filename, QDict *options, Error **errp) { const char *start; char *p, *buf, *keypairs; char *found_str; size_t max_keypair_size; if (!strstart(filename, "rbd:", &start)) { error_setg(errp, "File name must start with 'rbd:'"); return; } max_keypair_size = strlen(start) + 1; buf = g_strdup(start); keypairs = g_malloc0(max_keypair_size); p = buf; found_str = qemu_rbd_next_tok(p, '/', &p); if (!p) { error_setg(errp, "Pool name is required"); goto done; } qemu_rbd_unescape(found_str); qdict_put(options, "pool", qstring_from_str(found_str)); if (strchr(p, '@')) { found_str = qemu_rbd_next_tok(p, '@', &p); qemu_rbd_unescape(found_str); qdict_put(options, "image", qstring_from_str(found_str)); found_str = qemu_rbd_next_tok(p, ':', &p); qemu_rbd_unescape(found_str); qdict_put(options, "snapshot", qstring_from_str(found_str)); } else { found_str = qemu_rbd_next_tok(p, ':', &p); qemu_rbd_unescape(found_str); qdict_put(options, "image", qstring_from_str(found_str)); } if (!p) { goto done; } /* The following are essentially all key/value pairs, and we treat * 'id' and 'conf' a bit special. Key/value pairs may be in any order. */ while (p) { char *name, *value; name = qemu_rbd_next_tok(p, '=', &p); if (!p) { error_setg(errp, "conf option %s has no value", name); break; } qemu_rbd_unescape(name); value = qemu_rbd_next_tok(p, ':', &p); qemu_rbd_unescape(value); if (!strcmp(name, "conf")) { qdict_put(options, "conf", qstring_from_str(value)); } else if (!strcmp(name, "id")) { qdict_put(options, "user" , qstring_from_str(value)); } else { /* FIXME: This is pretty ugly, and not the right way to do this. * These should be contained in a structure, and then * passed explicitly as individual key/value pairs to * rados. Consider this legacy code that needs to be * updated. */ char *tmp = g_malloc0(max_keypair_size); /* only use a delimiter if it is not the first keypair found */ /* These are sets of unknown key/value pairs we'll pass along * to ceph */ if (keypairs[0]) { snprintf(tmp, max_keypair_size, ":%s=%s", name, value); pstrcat(keypairs, max_keypair_size, tmp); } else { snprintf(keypairs, max_keypair_size, "%s=%s", name, value); } g_free(tmp); } } if (keypairs[0]) { qdict_put(options, "=keyvalue-pairs", qstring_from_str(keypairs)); } done: g_free(buf); g_free(keypairs); return; }