[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH v3 05/10] plat/xen: Add API for Xenstore messages


  • To: minios-devel@xxxxxxxxxxxxx
  • From: Costin Lupu <costin.lupu@xxxxxxxxx>
  • Date: Mon, 10 Sep 2018 12:05:57 +0300
  • Cc: simon.kuenzer@xxxxxxxxx, yuri.volchkov@xxxxxxxxx
  • Delivery-date: Mon, 10 Sep 2018 09:06:22 +0000
  • Ironport-phdr: 9a23:yRLOJBECDynkJqZDxmr5qJ1GYnF86YWxBRYc798ds5kLTJ7zocSwAkXT6L1XgUPTWs2DsrQY07WQ6/iocFdDyK7JiGoFfp1IWk1NouQttCtkPvS4D1bmJuXhdS0wEZcKflZk+3amLRodQ56mNBXdrXKo8DEdBAj0OxZrKeTpAI7SiNm82/yv95HJbAhEmDiwbaluIBmqsA7cqtQYjYx+J6gr1xDHuGFIe+NYxWNpIVKcgRPx7dqu8ZBg7ipdpesv+9ZPXqvmcas4S6dYDCk9PGAu+MLrrxjDQhCR6XYaT24bjwBHAwnB7BH9Q5fxri73vfdz1SWGIcH7S60/VDK/5KlpVRDokj8KOT4n/m/KhMJ+j6VVrxCvpxFk34LYfJuYOOZkc6/BYd8XQ3dKUMZLVyxGB4Oxd5UCD+0aPeZEron9oUYFox2jBQm0GePk1zhFiWPx3a0hz+QhEAfG0BYkH9ITqHTUsc74O7sJUeyv1KnI0C7MY+lM2Tf68YXFdA0qr/KUXb9obMbcxlQjGxnGg1iQs4DpIS2Z2+YXv2WV9+ZsSO2ih3M9pwxyojWj3Nkgh4fHi44P11zJ+jt1zYAoLtOiUkF7e8SrEJ5IuiGfMIt5X90tTnlzuCY/1r0GoZm7fDUWyJg/xx7QdfiHc4+Q7xL9UeaeOzZ4hHZ/dL2jnBa+61CgyvDnWcWuylZKqTJJktjKtn8Tyxze8tWLR/Rg8ku72juC1xrf5v9aLU02j6bWJYYtwrsqmZoStUTDEDX2mELzjKKOakok/fOo6/jmYrXgvJOcM5J0ihnjMqk1hsO/Gv40MhATX2eA4+i8zrrj8VXjQLpWlv02jrXZsJfCKMQep665BQ5V0oE46xqmEjipzsoYkmcDLF9efBKHjpPpO03VIPziAvawnVKsnC1sx/DcMb3rGo/NIWTbkLf9YbZ97FZRyBEyzdBa4JJUDKsNIPHuWkDvstzZDwE2MxavzubhFtpyyoceVniUDaODLqzSrEeC5vgzLOmUeI8VpDH9JuAl5v7zl385mEURfbeu3ZsTdH+4HvdmI0KHYXf3hNcOD3sFvg4kQ+PxklGNTyNTND6OWPc55zc6D5njAYrdS4SFhL2awDz9DpBQIGdcBQOiC3DtIq6DQOsNbmq2P9d82mgPUqO9Soln0Qy2qSfx0Px/M+CS4CpO5sGr78R8++CGzUJ6zjdzFcnIi2w=
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>

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;
+
+       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;
+
+       return err;
+}
+
+domid_t xs_get_self_id(void)
+{
+       char *domid_str;
+       domid_t domid;
+
+       domid_str = xs_read(XBT_NIL, "domid", NULL);
+       if (PTRISERR(domid_str))
+               UK_CRASH("Error reading domain id.");
+
+       domid = (domid_t) strtoul(domid_str, NULL, 10);
+
+       free(domid_str);
+
+       return domid;
+}
-- 
2.11.0


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

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