[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.