[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v2 05/10] plat/xen: Add API for Xenstore messages
Add the API needed for sending Xenstore messages. These functions are used by any client communicating with the Xenstore daemon. Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx> --- plat/xen/Makefile.uk | 1 + plat/xen/include/xenbus/xs.h | 270 ++++++++++++++++++ plat/xen/xenbus/xs.c | 650 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 921 insertions(+) create mode 100644 plat/xen/include/xenbus/xs.h create mode 100644 plat/xen/xenbus/xs.c diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk index 2703a54..63cc42b 100644 --- a/plat/xen/Makefile.uk +++ b/plat/xen/Makefile.uk @@ -80,4 +80,5 @@ LIBXENBUS_CFLAGS-y += $(LIBXENPLAT_CFLAGS-y) LIBXENBUS_CINCLUDES-y += $(LIBXENPLAT_CINCLUDES-y) LIBXENBUS_SRCS-y += $(LIBXENPLAT_BASE)/xenbus/xenbus.c LIBXENBUS_SRCS-y += $(LIBXENPLAT_BASE)/xenbus/xs_comms.c +LIBXENBUS_SRCS-y += $(LIBXENPLAT_BASE)/xenbus/xs.c endif diff --git a/plat/xen/include/xenbus/xs.h b/plat/xen/include/xenbus/xs.h new file mode 100644 index 0000000..6ae761d --- /dev/null +++ b/plat/xen/include/xenbus/xs.h @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Costin Lupu <costin.lupu@xxxxxxxxx> + * + * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. + */ +/* Xenstore API */ +/* + * TODO The intention for this API is to be used by applications as well. + * Therefore, all data allocated by this API for external use must be free'd + * calling 'free' function (and not uk_xb_free). This is the reason why such + * data is allocated with 'malloc'/'calloc'. + */ + +#ifndef __XS_H__ +#define __XS_H__ + +#include <xenbus/xenbus.h> + + +/* + * Read the value associated with a path. + * + * @param xbt Xenbus transaction id + * @param path Xenstore path + * @param node Xenstore subdirectory + * @return On success, returns a malloc'd copy of the value. On error, returns + * a negative error number which should be checked using PTRISERR. + */ +char *xs_read(xenbus_transaction_t xbt, const char *path, const char *node); + +/* + * Associates a value with a path. + * + * @param xbt Xenbus transaction id + * @param path Xenstore path + * @param node Xenstore subdirectory (optional) + * @param value Xenstore value + * @return 0 on success, a negative errno value on error. + */ +int xs_write(xenbus_transaction_t xbt, const char *path, const char *node, + const char *value); + +/* + * List the contents of a directory. + * + * @param xbt Xenbus transaction id + * @param path Xenstore directory path + * @param node Xenstore subdirectory (optional) + * @return On success, returns a malloc'd array of pointers to strings. The + * array is NULL terminated. The caller should free only the array. On error, + * returns a negative error number which should be checked using PTRISERR. + * May block. + */ +char **xs_ls(xenbus_transaction_t xbt, const char *path); + +/* + * Removes the value associated with a path. + * + * @param xbt Xenbus transaction id + * @param path Xenstore path + * @return 0 on success, a negative errno value on error. + */ +int xs_rm(xenbus_transaction_t xbt, const char *path); + +/* + * Xenstore permissions + */ +enum xs_perm { + XS_PERM_NONE = 0x0, + XS_PERM_READ = 0x1, + XS_PERM_WRITE = 0x2, + XS_PERM_BOTH = XS_PERM_WRITE | XS_PERM_READ +}; + +/* + * Converts a character to corresponding permission value. + * + * @param c Permission character + * @param perm Permission value + * @return 0 on success, a negative errno value on error. + */ +int xs_char_to_perm(char c, enum xs_perm *perm); + +/* + * Converts a permission value to corresponding character. + * + * @param perm Permission value + * @param c Permission character + * @return 0 on success, a negative errno value on error. + */ +int xs_perm_to_char(enum xs_perm perm, char *c); + +/* + * Extracts domid and permission value out of a permission string. + * + * @param str Permission string + * @param domid Domain ID + * @param perm Permission value + * @return 0 on success, a negative errno value on error. + */ +int xs_str_to_perm(const char *str, domid_t *domid, enum xs_perm *perm); + +/* + * Returns a permission string from domid and permission value. + * + * @param domid Domain ID + * @param perm Permission value + * @return On success, returns a malloc'd string. On error, returns a negative + * error number which should be checked using PTRISERR. + */ +char *xs_perm_to_str(domid_t domid, enum xs_perm perm); + +/* + * Xenstore ACL + */ +struct xs_acl_entry { + domid_t domid; + enum xs_perm perm; +}; + +struct xs_acl { + domid_t ownerid; + enum xs_perm others_perm; + int entries_num; + struct xs_acl_entry entries[]; +}; + +/* + * Returns the ACL for input path. + * + * @param xbt Xenbus transaction id + * @param path Xenstore path + * @return On success, returns a malloc'd ACL. On error, returns a + * negative error number which should be checked using PTRISERR. + */ +struct xs_acl *xs_get_acl(xenbus_transaction_t xbt, const char *path); + +/* + * Sets ACL for input path. + * + * @param xbt Xenbus transaction id + * @param path Xenstore path + * @param acl New ACL + * @return 0 on success, a negative errno value on error. + */ +int xs_set_acl(xenbus_transaction_t xbt, const char *path, struct xs_acl *acl); + +/* + * Reads permissions for input path and domid. + * + * @param xbt Xenbus transaction id + * @param path Xenstore path + * @param domid Domain ID + * @param perm Permission value + * @return 0 on success, a negative errno value on error. + */ +int xs_get_perms(xenbus_transaction_t xbt, const char *path, + domid_t domid, enum xs_perm *perm); + +/* + * Sets permissions for input path and domid. + * + * @param xbt Xenbus transaction id + * @param path Xenstore path + * @param domid Domain ID + * @param perm Permission value + * @return 0 on success, a negative errno value on error. + */ +int xs_set_perms(xenbus_transaction_t xbt, const char *path, + domid_t domid, enum xs_perm perm); + +/* + * Start a xenbus transaction. Returns the transaction in xbt on + * success or an error number otherwise. + * + * @param xbt Address for returning the Xenbus transaction id + * @return 0 on success, a negative errno value on error. + */ +int xs_transaction_start(xenbus_transaction_t *xbt); + +/* + * End a xenbus transaction. Returns non-zero on failure. + * Parameter abort says whether the transaction should be aborted. + * Returns 1 in *retry iff the transaction should be retried. + * + * @param xbt Xenbus transaction id + * @param abort Non-zero if transaction should be aborted + * @return 0 on success, a negative errno value on error. + */ +int xs_transaction_end(xenbus_transaction_t xbt, int abort); + +/* + * Sends a debug message to the Xenstore daemon for writing it in the debug log + * + * @param msg The logged message + * @return 0 on success, a negative errno value on error. + */ +int xs_debug_msg(const char *msg); + +/* + * Read path and parse it as an integer. + * + * @param path Xenstore path + * @param value Returned int value + * @return 0 on success, a negative errno value on error. + */ +int xs_read_integer(const char *path, int *value); + +/* + * Contraction of sscanf and xs_read(node/path). + * + * @param xbt Xenbus transaction id + * @param dir Xenstore directory + * @param node Xenstore directory entry + * @param fmt Path format string + * @return Just like sscanf, on success returns the number of input items + * successfully matched and assigned. On error returns a negative errno value. + */ +int xs_scanf(xenbus_transaction_t xbt, const char *dir, const char *node, + const char *fmt, ...) __scanf(4, 5); + +/* + * Contraction of sprintf and xs_write(node/path). + * + * @param xbt Xenbus transaction id + * @param dir Xenstore directory + * @param node Xenstore directory entry + * @param fmt Path format string + * @return Just like sprintf, on success returns the number of the number of + * characters printed. On error returns a negative errno value. + */ +int xs_printf(xenbus_transaction_t xbt, const char *dir, const char *node, + const char *fmt, ...) __printf(4, 5); + +/* + * Utility function to figure out our domain id + * + * @return Our domain id + */ +domid_t xs_get_self_id(void); + +#endif /* __XS_H__ */ diff --git a/plat/xen/xenbus/xs.c b/plat/xen/xenbus/xs.c new file mode 100644 index 0000000..eb5131a --- /dev/null +++ b/plat/xen/xenbus/xs.c @@ -0,0 +1,650 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Steven Smith (sos22@xxxxxxxxx) + * Grzegorz Milos (gm281@xxxxxxxxx) + * John D. Ramsdell + * Costin Lupu <costin.lupu@xxxxxxxxx> + * + * Copyright (c) 2006, Cambridge University + * 2018, NEC Europe Ltd., NEC Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. + */ +/* + * Ported from Mini-OS xenbus.c + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdarg.h> +#include <uk/errptr.h> +#include <xen/io/xs_wire.h> +#include <xenbus/xs.h> +#include "xs_comms.h" + + +/* Helper macro for initializing xs requests from strings + * (w/ null terminator) + */ +#define XS_IOVEC_STR(str) \ + ((struct xs_iovec) { str, strlen(str) + 1 }) + + +/* Common function used for sending requests when replies aren't handled */ +static inline int xs_msg(enum xsd_sockmsg_type type, xenbus_transaction_t xbt, + struct xs_iovec *reqs, int reqs_num) +{ + return xs_msg_reply(type, xbt, reqs, reqs_num, NULL); +} + +char *xs_read(xenbus_transaction_t xbt, const char *path, const char *node) +{ + struct xs_iovec req, rep; + char *fullpath, *value; + int err; + + if (path == NULL) + return ERR2PTR(EINVAL); + + if (node != NULL) { + err = asprintf(&fullpath, "%s/%s", path, node); + if (err < 0) { + value = ERR2PTR(ENOMEM); + goto out; + } + } else + fullpath = (char *) path; + + req = XS_IOVEC_STR(fullpath); + err = xs_msg_reply(XS_READ, xbt, &req, 1, &rep); + if (err == 0) + value = rep.data; + else + value = ERR2PTR(-err); + + if (node != NULL) + free(fullpath); +out: + return value; +} + +int xs_write(xenbus_transaction_t xbt, const char *path, const char *node, + const char *value) +{ + struct xs_iovec req[2]; + char *fullpath; + int err; + + if (path == NULL || value == NULL) + return -EINVAL; + + if (node != NULL) { + err = asprintf(&fullpath, "%s/%s", path, node); + if (err < 0) { + err = -ENOMEM; + goto out; + } + } else + fullpath = (char *) path; + + req[0] = XS_IOVEC_STR(fullpath); + req[1] = XS_IOVEC_STR((char *) value); + + err = xs_msg(XS_WRITE, xbt, req, ARRAY_SIZE(req)); + + if (node != NULL) + free(fullpath); +out: + return err; +} + +/* Returns an array of strings out of the serialized reply */ +static char **reply_to_string_array(struct xs_iovec *rep, int *size) +{ + int strings_num, offs, i; + char *rep_strings, *strings, **res = NULL; + + rep_strings = rep->data; + + /* count the strings */ + for (offs = strings_num = 0; offs < (int) rep->len; offs++) + strings_num += (rep_strings[offs] == 0); + + /* one alloc for both string addresses and contents */ + res = malloc((strings_num + 1) * sizeof(char *) + rep->len); + if (!res) + return ERR2PTR(ENOMEM); + + /* copy the strings at the end of the array */ + strings = (char *) &res[strings_num + 1]; + memcpy(strings, rep_strings, rep->len); + + /* fill the string array */ + for (offs = i = 0; i < strings_num; i++) { + char *string = strings + offs; + int string_len = strlen(string); + + res[i] = string; + + offs += string_len + 1; + } + res[i] = NULL; + + if (size) + *size = strings_num; + + return res; +} + +char **xs_ls(xenbus_transaction_t xbt, const char *path) +{ + struct xs_iovec req, rep; + char **res = NULL; + int err; + + if (path == NULL) + return ERR2PTR(EINVAL); + + req = XS_IOVEC_STR((char *) path); + err = xs_msg_reply(XS_DIRECTORY, xbt, &req, 1, &rep); + if (err) + return ERR2PTR(-err); + + res = reply_to_string_array(&rep, NULL); + free(rep.data); + + return res; +} + +int xs_rm(xenbus_transaction_t xbt, const char *path) +{ + struct xs_iovec req; + + if (path == NULL) + return -EINVAL; + + req = XS_IOVEC_STR((char *) path); + + return xs_msg(XS_RM, xbt, &req, 1); +} + +/* + * Permissions + */ + +static const char xs_perm_tbl[] = { + [XS_PERM_NONE] = 'n', + [XS_PERM_READ] = 'r', + [XS_PERM_WRITE] = 'w', + [XS_PERM_BOTH] = 'b', +}; + +int xs_char_to_perm(char c, enum xs_perm *perm) +{ + int err = -EINVAL; + + if (perm == NULL) + goto out; + + for (int i = 0; i < (int) ARRAY_SIZE(xs_perm_tbl); i++) { + if (c == xs_perm_tbl[i]) { + *perm = i; + err = 0; + break; + } + } + +out: + return err; +} + +int xs_perm_to_char(enum xs_perm perm, char *c) +{ + int err = -EINVAL; + + if (c == NULL) + goto out; + + if (perm < ARRAY_SIZE(xs_perm_tbl)) { + *c = xs_perm_tbl[perm]; + err = 0; + } + +out: + return err; +} + +int xs_str_to_perm(const char *str, domid_t *domid, enum xs_perm *perm) +{ + int err = 0; + + if (str == NULL || domid == NULL || perm == NULL) { + err = -EINVAL; + goto out; + } + + err = xs_char_to_perm(str[0], perm); + if (err) + goto out; + + *domid = (domid_t) strtoul(&str[1], NULL, 10); + +out: + return err; +} + +#define PERM_MAX_SIZE 32 +char *xs_perm_to_str(domid_t domid, enum xs_perm perm) +{ + int err = 0; + char permc, value[PERM_MAX_SIZE]; + + err = xs_perm_to_char(perm, &permc); + if (err) + return NULL; + + snprintf(value, PERM_MAX_SIZE, "%c%hu", permc, domid); + + return strdup(value); +} + +/* + * Returns the ACL for input path. An extra number of empty entries may be + * requested if caller intends to extend the list. + */ +static struct xs_acl *__xs_get_acl(xenbus_transaction_t xbt, const char *path, + int extra) +{ + struct xs_acl *acl = NULL; + struct xs_iovec req, rep; + char **values; + int values_num, err; + + if (path == NULL) { + err = EINVAL; + goto out; + } + + req = XS_IOVEC_STR((char *) path); + err = xs_msg_reply(XS_GET_PERMS, xbt, &req, 1, &rep); + if (err) + goto out; + + values = reply_to_string_array(&rep, &values_num); + free(rep.data); + if (PTRISERR(values)) { + err = PTR2ERR(values); + goto out; + } + + acl = malloc(sizeof(struct xs_acl) + + (values_num + extra) * sizeof(struct xs_acl_entry)); + if (acl == NULL) { + err = ENOMEM; + goto out_values; + } + + /* set owner id and permissions for others */ + err = xs_str_to_perm(values[0], + &acl->ownerid, &acl->others_perm); + if (err) + goto out_values; + + /* set ACL entries */ + acl->entries_num = values_num - 1; + for (int i = 0; i < acl->entries_num; i++) { + err = xs_str_to_perm(values[i + 1], + &acl->entries[i].domid, &acl->entries[i].perm); + if (err) + goto out_values; + } + +out_values: + free(values); +out: + if (err) { + if (acl) + free(acl); + acl = ERR2PTR(-err); + } + return acl; +} + +struct xs_acl *xs_get_acl(xenbus_transaction_t xbt, const char *path) +{ + return __xs_get_acl(xbt, path, 0); +} + +int xs_set_acl(xenbus_transaction_t xbt, const char *path, struct xs_acl *acl) +{ + struct xs_iovec req[2 + acl->entries_num]; + char *s; + int i, err; + + if (path == NULL || acl == NULL) { + err = -EINVAL; + goto out; + } + + req[0] = XS_IOVEC_STR((char *) path); + + s = xs_perm_to_str(acl->ownerid, acl->others_perm); + if (s == NULL) { + err = -EINVAL; + goto out; + } + + req[1].data = s; + req[1].len = strlen(s) + 1; + + for (i = 0; i < acl->entries_num; i++) { + struct xs_acl_entry *acle = &acl->entries[i]; + + s = xs_perm_to_str(acle->domid, acle->perm); + if (s == NULL) { + err = -EINVAL; + goto out_req; + } + + req[i + 2].data = s; + req[i + 2].len = strlen(s) + 1; + } + + err = xs_msg(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req)); + +out_req: + for (i--; i > 0; i--) + free(req[i].data); +out: + return err; +} + +int xs_get_perms(xenbus_transaction_t xbt, const char *path, + domid_t domid, enum xs_perm *perm) +{ + struct xs_acl *acl; + int err = 0; + + if (perm == NULL) { + err = -EINVAL; + goto out; + } + + acl = xs_get_acl(xbt, path); + if (PTRISERR(acl)) { + err = PTR2ERR(acl); + goto out; + } + + if (acl->ownerid == domid) { + *perm = XS_PERM_BOTH; + goto out_acl; + } + + for (int i = 0; i < acl->entries_num; i++) { + struct xs_acl_entry *acle = &acl->entries[i]; + + if (acle->domid == domid) { + *perm = acle->perm; + goto out_acl; + } + } + + *perm = acl->others_perm; + +out_acl: + free(acl); +out: + return err; +} + +int xs_set_perms(xenbus_transaction_t xbt, const char *path, + domid_t domid, enum xs_perm perm) +{ + struct xs_acl *acl; + struct xs_acl_entry *acle; + int i, err = 0; + + /* one extra entry in case a new one will be added */ + acl = __xs_get_acl(xbt, path, 1); + if (PTRISERR(acl)) { + err = PTR2ERR(acl); + goto out; + } + + if (acl->ownerid == domid) { + /* + * let's say the function isn't called correctly considering + * that the owner domain has all the rights, all the time + */ + err = -EINVAL; + goto out_acl; + } + + for (i = 0, acle = &acl->entries[i]; i < acl->entries_num; i++) { + if (acle->domid == domid) + break; + } + + if (perm != XS_PERM_NONE) { + if (i == acl->entries_num) { + /* new entry */ + acle->domid = domid; + acl->entries_num++; + } + + acle->perm = perm; + + } else { + if (i == acl->entries_num) { + /* no entry */ + err = -ENOENT; + goto out_acl; + } + /* remove entry */ + acl->entries_num--; + memmove(&acl->entries[i], &acl->entries[i + 1], + (acl->entries_num - i) * sizeof(struct xs_acl_entry)); + } + + err = xs_set_acl(xbt, path, acl); + +out_acl: + free(acl); +out: + return err; +} + +/* + * Transactions + */ + +int xs_transaction_start(xenbus_transaction_t *xbt) +{ + /* + * xenstored becomes angry if you send a length 0 message, + * so just shove a nul terminator on the end + */ + struct xs_iovec req, rep; + int err; + + if (xbt == NULL) + return -EINVAL; + + req = XS_IOVEC_STR(""); + err = xs_msg_reply(XS_TRANSACTION_START, 0, &req, 1, &rep); + if (err) + return err; + + *xbt = strtoul(rep.data, NULL, 10); + free(rep.data); + + return err; +} + +int xs_transaction_end(xenbus_transaction_t xbt, int abort) +{ + struct xs_iovec req; + + req.data = abort ? "F" : "T"; + req.len = 2; + + return xs_msg(XS_TRANSACTION_END, xbt, &req, 1); +} + +/* + * Misc + */ + +/* Send a debug message to xenbus. Can block. */ +int xs_debug_msg(const char *msg) +{ + struct xs_iovec req[3], rep; + int err; + + if (msg == NULL) + return -EINVAL; + + req[0] = XS_IOVEC_STR("print"); + req[1] = XS_IOVEC_STR((char *) msg); + req[2] = XS_IOVEC_STR(""); + + err = xs_msg_reply(XS_DEBUG, XBT_NIL, req, ARRAY_SIZE(req), &rep); + if (err) + goto out; + + uk_printd(DLVL_EXTRA, + "Got a debug reply %s\n", (char *) rep.data); + free(rep.data); + +out: + return err; +} + +int xs_read_integer(const char *path, int *value) +{ + char *value_str; + + if (path == NULL || value == NULL) + return -EINVAL; + + value_str = xs_read(XBT_NIL, path, NULL); + if (PTRISERR(value_str)) + return PTR2ERR(value_str); + + *value = atoi(value_str); + + free(value_str); + + return 0; +} + +int xs_scanf(xenbus_transaction_t xbt, const char *dir, const char *node, + const char *fmt, ...) +{ +#define FULLPATH_SIZE 256 + char fullpath[FULLPATH_SIZE]; + char *val; + va_list args; + int err = 0; + + if (dir == NULL || node == NULL || fmt == NULL) + return -EINVAL; + + if (strlen(dir) + strlen(node) + 1 >= FULLPATH_SIZE) + return -ENOMEM; + + sprintf(fullpath, "%s/%s", dir, node); + + val = xs_read(xbt, fullpath, NULL); + if (PTRISERR(val)) { + err = PTR2ERR(val); + goto out; + } + + va_start(args, fmt); + err = vsscanf(val, fmt, args); + va_end(args); + + free(val); + +out: + return err; +} + +int xs_printf(xenbus_transaction_t xbt, const char *dir, const char *node, + const char *fmt, ...) +{ + char fullpath[FULLPATH_SIZE]; + char val[FULLPATH_SIZE]; + va_list args; + int err, _err; + + if (dir == NULL || node == NULL || fmt == NULL) + return -EINVAL; + + if (strlen(dir) + strlen(node) + 1 >= FULLPATH_SIZE) + return -ENOMEM; + + sprintf(fullpath, "%s/%s", dir, node); + + va_start(args, fmt); + _err = vsprintf(val, fmt, args); + va_end(args); + + /* send to Xenstore iff vsprintf was successful */ + if (_err > 0) + err = xs_write(xbt, fullpath, NULL, val); + + /* + * if message sent to Xenstore was successful, + * return the number of characters + */ + if (err == 0) + err = _err; + + return err; +} + +domid_t xs_get_self_id(void) +{ + char *domid_str; + domid_t domid; + + domid_str = xs_read(XBT_NIL, "domid", NULL); + if (PTRISERR(domid_str)) + UK_CRASH("Error reading domain id."); + + domid = (domid_t) strtoul(domid_str, NULL, 10); + + free(domid_str); + + return domid; +} -- 2.11.0 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |