|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [WIP PATCH 09/16] WIP: tools/xl: Implement generalized output formatting for `xl list`
Implement a generalized output formatting function for the `xl list`
subcommands. Notably `xl list` and `xl vm-list` could make use of
alternative output list formats.
Signed-off-by: Elliott Mitchell <ehem+xen@xxxxxxx>
---
I'm a bit unsure of #include <xen-tools/libs.h>. When looking for an
implementation of ARRAY_SIZE(), that was the header I found. I can
readily write it myself, but rather than inlining, I looked for a copy in
a header and found that.
---
tools/xl/xl_list.c | 285 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 285 insertions(+)
diff --git a/tools/xl/xl_list.c b/tools/xl/xl_list.c
index e30536fd9a..1c04f2126b 100644
--- a/tools/xl/xl_list.c
+++ b/tools/xl/xl_list.c
@@ -14,10 +14,14 @@
#define _GNU_SOURCE
+#include <ctype.h>
#include <inttypes.h>
#include <stdlib.h>
+#include <stddef.h>
#include <unistd.h>
+#include <xen-tools/libs.h>
+
#include <libxl.h>
#include <libxl_utils.h>
@@ -25,6 +29,287 @@
#include "xl_utils.h"
+struct format_entry;
+
+typedef void (format_function_t)(const struct format_entry *,
+ const void *, const char *, size_t);
+
+typedef struct format_entry {
+ char *const header;
+ char formatc[3];
+ format_function_t *formatf;
+ ptrdiff_t offset;
+ union {
+ int i;
+ unsigned long lu;
+ float f;
+ void *v;
+ char *(*xlfunc)(libxl_ctx *, uint32_t);
+ } extra;
+} format_table_t['z' - 'A' + 1];
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+static void format_normal(const struct format_entry *entry,
+ const void *info, const char *format,
+ size_t len)
+{
+ char *buf = alloca(len + 3);
+ memcpy(buf, format, len);
+ if (info) {
+ const char *str;
+ int i;
+ unsigned long lu;
+ float f;
+ strcpy(buf + len, entry->formatc);
+ switch (entry->formatc[0]) {
+ case 's':
+ str = ((char **)info)[entry->offset];
+ if (!str) str = "-";
+ printf(buf, str);
+ break;
+ case 'f':
+ f = ((float *)info)[entry->offset];
+ if (entry->extra.f != 0) f /= entry->extra.f;
+ printf(buf, f);
+ break;
+ case 'l':
+ lu = ((unsigned long *)info)[entry->offset];
+ if (entry->extra.lu) lu /= entry->extra.lu;
+ printf(buf, lu);
+ break;
+ case 'd':
+ default:
+ i = ((int *)info)[entry->offset];
+ if (entry->extra.i) i /= entry->extra.i;
+ printf(buf, i);
+ break;
+ }
+ } else {
+ if (entry->formatc[0] == 'f') {
+ char *tmp;
+ buf[len] = '\0';
+ if ((tmp = rindex(buf, '.')))
+ len = tmp - buf - 1;
+ }
+ strcpy(buf + len, "s");
+ printf(buf, entry->header);
+ }
+}
+
+static void format_allocstr(const struct format_entry *entry,
+ const void *info, const char *format,
+ size_t len)
+{
+ char *fmt = alloca(len + 2);
+ char *outbuf;
+ memcpy(fmt, format, len);
+ strcpy(fmt + len, "s");
+
+ if (info) {
+ outbuf = entry->extra.xlfunc(ctx, ((uint32_t *)info)[entry->offset]);
+ printf(fmt, outbuf);
+ free(outbuf);
+ } else printf(fmt, entry->header);
+}
+
+static void format_uuid(const struct format_entry *entry,
+ const void *info, const char *format,
+ size_t len)
+{
+ if (info) printf(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(*(libxl_uuid *)((char
*)info + entry->offset)));
+ else fputs(entry->header, stdout);
+}
+
+static void format_time(const struct format_entry *entry,
+ const void *_info, const char *format,
+ size_t len)
+{
+ const libxl_dominfo *info = _info;
+ char *fmt = alloca(len + 2);
+ memcpy(fmt, format, len);
+
+ if (info) {
+ strcpy(fmt + len, "f");
+ printf(fmt, ((float)info->cpu_time / 1e9));
+ } else {
+ char *tmp;
+ if (!(tmp = index(fmt, '.'))) tmp = fmt + len;
+ strcpy(tmp, "s");
+ printf(fmt, entry->header);
+ }
+}
+
+static void format_state(const struct format_entry *entry,
+ const void *_info, const char *format,
+ size_t len)
+{
+ const libxl_dominfo *info = _info;
+ if (info) {
+ const char shutdown_reason_letters[] = "-rscwS";
+ libxl_shutdown_reason shutdown_reason;
+ static const char letters[] = "rbps";
+ int i;
+ const bool *flags;
+
+ flags = &info->running;
+ for (i = 0; i < strlen(letters); ++i)
+ putchar(flags[i] ? letters[i] : '-');
+
+ shutdown_reason = info->shutdown ? info->shutdown_reason : 0;
+ putchar((shutdown_reason >= 0 &&
+ shutdown_reason < sizeof(shutdown_reason_letters)-1
+ ? shutdown_reason_letters[shutdown_reason] : '?'));
+
+ putchar(info->dying ? 'd' : '-');
+ } else printf("%6s", entry->header);
+}
+
+static void format_reason(const struct format_entry *entry,
+ const void *_info, const char *format,
+ size_t len)
+{
+ const libxl_dominfo *info = _info;
+ const char *output = entry->header;
+ if (info) {
+ if (info->shutdown) {
+ printf("%8x", info->shutdown_reason);
+ return;
+ }
+ output = "-";
+ }
+ printf("%8s", output);
+}
+
+static void format_memory(const struct format_entry *entry,
+ const void *_info, const char *format,
+ size_t len)
+{
+ const libxl_dominfo *info = _info;
+ char *fmt = alloca(len + 3);
+ memcpy(fmt, format, len);
+ if (info) {
+ strcpy(fmt + len, entry->formatc);
+ printf(fmt, (info->current_memkb + info->outstanding_memkb) >> 10);
+ } else {
+ strcpy(fmt + len, "s");
+ printf(fmt, "Mem");
+ }
+}
+
+static void format_node(const struct format_entry *entry,
+ const void *_info, const char *format,
+ size_t len)
+{
+ const libxl_dominfo *info = _info;
+ static bool need_init = true;
+ static libxl_bitmap nodemap;
+ static libxl_physinfo physinfo;
+
+ if (need_init) {
+ libxl_bitmap_init(&nodemap);
+ libxl_physinfo_init(&physinfo);
+ need_init = false;
+
+ if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
+ fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
+ exit(EXIT_FAILURE);
+ }
+ if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+ fprintf(stderr, "libxl_physinfo failed.\n");
+ libxl_bitmap_dispose(&nodemap);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (info) {
+ libxl_domain_get_nodeaffinity(ctx, info->domid, &nodemap);
+
+ putchar(' ');
+ print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
+ } else fputs(entry->header, stdout);
+
+#if 0
+ /* unfortunately these get leaked on exit */
+ libxl_bitmap_dispose(&nodemap);
+ libxl_physinfo_dispose(&physinfo);
+#endif
+}
+
+#pragma GCC diagnostic pop
+
+static bool isfmtchar(int c)
+{
+ const bool opts[] = {
+ ['0'] = true,
+ ['1'] = true,
+ ['2'] = true,
+ ['3'] = true,
+ ['4'] = true,
+ ['5'] = true,
+ ['6'] = true,
+ ['7'] = true,
+ ['8'] = true,
+ ['9'] = true,
+ ['.'] = true,
+ ['#'] = true,
+ ['-'] = true,
+ ['+'] = true,
+ [' '] = true,
+ ['\''] = true,
+ };
+ if ((unsigned int)c < ARRAY_SIZE(opts) && opts[c]) return true;
+ else return false;
+}
+
+static void format(const format_table_t fmttab, const char *fmt,
+ const void *info)
+{
+ while (fmt[0]) {
+ if (fmt[0] == '\\') {
+ switch (fmt[1]) {
+ case 0:
+ /* Uhm... */
+ return;
+ case '0':
+ putchar(0);
+ break;
+ case 'n':
+ fputs("\n", stdout);
+ break;
+ case 't':
+ putchar('\t');
+ break;
+ default:
+ putchar(fmt[1]);
+ }
+ fmt+=2;
+ } else if (fmt[0] == '%') {
+ size_t len=1;
+ unsigned char entryn;
+
+ while (isfmtchar(fmt[len])) ++len;
+
+ entryn = fmt[len] - 'A';
+ if (entryn < sizeof(format_table_t) / sizeof(fmttab[0]) &&
+ fmttab[entryn].formatf)
+ fmttab[entryn].formatf(fmttab + entryn, info, fmt, len);
+ else {
+ fprintf(stderr, "Invalid conversion character \'%c\'\n",
+ entryn);
+ exit(EXIT_FAILURE);
+ }
+
+ fmt += len + 1;
+ } else {
+ putchar(*fmt);
+ ++fmt;
+ }
+ }
+}
+
+
static void list_vm(void)
{
libxl_vminfo *info;
--
--
(\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/)
\BS ( | ehem+sigmsg@xxxxxxx PGP 87145445 | ) /
\_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/
8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |