[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v4 2/7] plat/xen: Add API for Xenstore messages
Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx> Costin Lupu <costin.lupu@xxxxxxxxx> writes: > 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 | 2 + > plat/xen/include/xenbus/xs.h | 282 ++++++++++++++++++ > plat/xen/xenbus/exportsyms.uk | 21 ++ > plat/xen/xenbus/xs.c | 674 > ++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 979 insertions(+) > create mode 100644 plat/xen/include/xenbus/xs.h > create mode 100644 plat/xen/xenbus/exportsyms.uk > create mode 100644 plat/xen/xenbus/xs.c > > diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk > index 2703a54..5578194 100644 > --- a/plat/xen/Makefile.uk > +++ b/plat/xen/Makefile.uk > @@ -74,10 +74,12 @@ LIBXENPLAT_SRCS-y += > $(LIBXENPLAT_BASE)/events.c > LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/gnttab.c > > ifeq ($(CONFIG_XEN_XENBUS),y) > +LIBXENBUS_EXPORTS = $(LIBXENPLAT_BASE)/xenbus/exportsyms.uk > LIBXENBUS_ASFLAGS-y += $(LIBXENPLAT_ASFLAGS-y) > LIBXENBUS_ASINCLUDES-y += $(LIBXENPLAT_ASINCLUDES-y) > 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..afa1ce2 > --- /dev/null > +++ b/plat/xen/include/xenbus/xs.h > @@ -0,0 +1,282 @@ > +/* 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_perm(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_perm(xenbus_transaction_t xbt, const char *path, > + domid_t domid, enum xs_perm perm); > + > +/* > + * Deletes permissions for domid. > + * > + * @param xbt Xenbus transaction id > + * @param path Xenstore path > + * @param domid Domain ID > + * @return 0 on success, a negative errno value on error. > + */ > +int xs_del_perm(xenbus_transaction_t xbt, const char *path, > + domid_t domid); > + > +/* > + * 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 xbt Xenbus transaction id > + * @param path Xenstore path > + * @param value Returned int value > + * @return 0 on success, a negative errno value on error. > + */ > +int xs_read_integer(xenbus_transaction_t xbt, 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 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 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/exportsyms.uk b/plat/xen/xenbus/exportsyms.uk > new file mode 100644 > index 0000000..5d9729e > --- /dev/null > +++ b/plat/xen/xenbus/exportsyms.uk > @@ -0,0 +1,21 @@ > +# Xenstore API > +xs_read > +xs_write > +xs_ls > +xs_rm > +xs_char_to_perm > +xs_perm_to_char > +xs_str_to_perm > +xs_perm_to_str > +xs_get_acl > +xs_set_acl > +xs_get_perm > +xs_set_perm > +xs_del_perm > +xs_transaction_start > +xs_transaction_end > +xs_debug_msg > +xs_read_integer > +xs_scanf > +xs_printf > +xs_get_self_id > diff --git a/plat/xen/xenbus/xs.c b/plat/xen/xenbus/xs.c > new file mode 100644 > index 0000000..fad7d9d > --- /dev/null > +++ b/plat/xen/xenbus/xs.c > @@ -0,0 +1,674 @@ > +/* 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 macros for initializing xs requests from strings */ > +#define XS_IOVEC_STR_NULL(str) \ > + ((struct xs_iovec) { str, strlen(str) + 1 }) > +#define XS_IOVEC_STR(str) \ > + ((struct xs_iovec) { str, strlen(str) }) > + > + > +/* 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_NULL(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_NULL(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 to 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_NULL((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_NULL((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) > +{ > + if (c == NULL || perm >= ARRAY_SIZE(xs_perm_tbl)) > + return -EINVAL; > + > + *c = xs_perm_tbl[perm]; > + > + return 0; > +} > + > +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_NULL((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_NULL((char *) path); > + > + s = xs_perm_to_str(acl->ownerid, acl->others_perm); > + if (s == NULL) { > + err = -EINVAL; > + goto out; > + } > + > + req[1] = XS_IOVEC_STR_NULL(s); > + > + 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] = XS_IOVEC_STR_NULL(s); > + } > + > + 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_perm(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; > +} > + > +static int acl_find_entry_index(struct xs_acl *acl, domid_t domid) > +{ > + struct xs_acl_entry *acle; > + int i; > + > + 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 > + */ > + return -EINVAL; > + > + for (i = 0; i < acl->entries_num; i++) { > + acle = &acl->entries[i]; > + if (acle->domid == domid) > + break; > + } > + > + if (i == acl->entries_num) > + /* no entry found for domid */ > + return -ENOENT; > + > + return i; > +} > + > +int xs_set_perm(xenbus_transaction_t xbt, const char *path, > + domid_t domid, enum xs_perm perm) > +{ > + struct xs_acl *acl; > + struct xs_acl_entry *acle; > + int err, idx; > + > + UK_ASSERT(xbt != XBT_NIL); > + > + /* 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; > + } > + > + idx = acl_find_entry_index(acl, domid); > + if (idx == -ENOENT) { > + /* new entry */ > + acle = &acl->entries[acl->entries_num]; > + acle->domid = domid; > + acle->perm = perm; > + acl->entries_num++; > + > + } else if (idx < 0) { > + /* some other error */ > + err = idx; > + goto out_acl; > + > + } else { > + /* update entry */ > + acle = &acl->entries[idx]; > + acle->perm = perm; > + } > + > + err = xs_set_acl(xbt, path, acl); > + > +out_acl: > + free(acl); > +out: > + return err; > +} > + > +int xs_del_perm(xenbus_transaction_t xbt, const char *path, > + domid_t domid) > +{ > + struct xs_acl *acl; > + int idx, err = 0; > + > + UK_ASSERT(xbt != XBT_NIL); > + > + acl = __xs_get_acl(xbt, path, 0); > + if (PTRISERR(acl)) { > + err = PTR2ERR(acl); > + goto out; > + } > + > + idx = acl_find_entry_index(acl, domid); > + if (idx < 0) { > + err = idx; > + goto out_acl; > + } > + > + /* remove entry */ > + acl->entries_num--; > + memmove(&acl->entries[idx], &acl->entries[idx + 1], > + (acl->entries_num - idx) * 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_NULL(""); > + 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_NULL("print"); > + req[1] = XS_IOVEC_STR((char *) msg); > + req[2] = XS_IOVEC_STR_NULL(""); > + > + 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(xenbus_transaction_t xbt, const char *path, int *value) > +{ > + char *value_str; > + > + if (path == NULL || value == NULL) > + return -EINVAL; > + > + value_str = xs_read(xbt, 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, ...) > +{ > + char *val; > + va_list args; > + int err = 0; > + > + if (fmt == NULL) > + return -EINVAL; > + > + val = xs_read(xbt, dir, node); > + 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, ...) > +{ > +#define VAL_SIZE 256 > + char val[VAL_SIZE]; > + va_list args; > + int err = 0, _err; > + > + if (fmt == NULL) > + return -EINVAL; > + > + va_start(args, fmt); > + _err = vsnprintf(val, VAL_SIZE, fmt, args); > + va_end(args); > + > + /* send to Xenstore if vsnprintf was successful */ > + if (_err > 0) > + err = xs_write(xbt, dir, node, 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 > -- Yuri Volchkov Software Specialist NEC Europe Ltd Kurfürsten-Anlage 36 D-69115 Heidelberg _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |