|
[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
Unfortunately had to stop even one commit before. So only 1-3 are
pushed. Patch 4 is broken and does not compile. Please fix this.
Yuri Volchkov <yuri.volchkov@xxxxxxxxx> writes:
> 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
--
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 |