[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v3 05/10] plat/xen: Add API for Xenstore messages
Earlier I said I will push patches 1-7, but actually I have to stop here :(. See inline. Yuri Volchkov <yuri.volchkov@xxxxxxxxx> writes: > Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx> > > I will add one minor modification here (see inline) > > 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 | 672 >> ++++++++++++++++++++++++++++++++++++++++++ >> 4 files changed, 977 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..b1774d8 >> --- /dev/null >> +++ b/plat/xen/xenbus/xs.c >> @@ -0,0 +1,672 @@ >> +/* 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; >> + > I will add this line here before pushing > 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, _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 If vsnprintf return a negative value the err will be returned uninitialized. Initializing it to zero also is not enough, because returning zero on a failure is not intended behavior. >> + >> + 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 -- 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 |