--- /dev/null
+/* Display
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include "kafs.h"
+#include "vlservice.h"
+#include "afs_xg.h"
+#include "display.h"
+
+/**
+ * kafs_sprint_address - Convert/resolve an address into text
+ * @ctx: The cell and authentication context
+ * @addr: The address to convert
+ * @buf: The buffer to write into
+ * @buf_len: The size of the buffer
+ *
+ * Convert an address into a textual representation, possibly resolving it to a
+ * hostname via the DNS or other name resolution service. The conversion is
+ * written into the buffer and truncated to the length given.
+ */
+void kafs_sprint_address(struct kafs_context *ctx,
+ struct sockaddr_rxrpc *addr,
+ char *buf, size_t buf_len)
+{
+ unsigned short port;
+ char service[64];
+ size_t len = 0;
+ int hint, ni;
+
+ hint = NI_DGRAM | NI_NUMERICSERV;
+
+ if (!ctx->no_resolve) {
+ hint |= NI_NAMEREQD;
+ ni = getnameinfo((struct sockaddr *)&addr[0].transport,
+ addr[0].transport_len,
+ buf, buf_len, service, sizeof(service), hint);
+ if (ni == EAI_MEMORY) {
+ kafs_nomem(ctx);
+ return;
+ }
+ if (ni == 0) {
+ len = strlen(buf);
+ if (len < buf_len - 2)
+ snprintf(buf + len, buf_len - len, ":%s", service);
+ return;
+ }
+ }
+
+ hint &= ~NI_NAMEREQD;
+ hint |= NI_NUMERICHOST;
+ ni = getnameinfo((struct sockaddr *)&addr[0].transport,
+ addr[0].transport_len,
+ buf, buf_len, service, sizeof(service), hint);
+ if (ni == EAI_MEMORY) {
+ kafs_nomem(ctx);
+ return;
+ }
+
+ len = strlen(buf);
+ if (strchr(buf, ':')) {
+ memmove(buf + 1, buf, len);
+ buf[0] = '[';
+ buf[len + 1] = ']';
+ buf[len + 2] = 0;
+ len += 2;
+ }
+
+ if (ni == 0) {
+ if (len < buf_len - 2)
+ snprintf(buf + len, buf_len - len, ":%s", service);
+ return;
+ }
+
+ buf[0] = 0;
+ switch (addr[0].transport.sin.sin_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &addr[0].transport.sin.sin_addr, buf, buf_len);
+ port = ntohs(addr[0].transport.sin.sin_port);
+ break;
+ case AF_INET6:
+ buf[0] = '[';
+ inet_ntop(AF_INET6, &addr[0].transport.sin6.sin6_addr, buf + 1, buf_len - 1);
+ len = strlen(buf);
+ buf[len] = ']';
+ buf[len + 1] = 0;
+ port = ntohs(addr[0].transport.sin6.sin6_port);
+ break;
+ default:
+ snprintf(buf, buf_len, "<af-%u>", addr[0].transport.sin.sin_family);
+ return;
+ }
+
+ if (port == FS_PORT)
+ return;
+
+ len = strlen(buf);
+ if (len < buf_len - 3)
+ snprintf(buf + len, buf_len - len, "+%u", port);
+}
+
+/*
+ * kafs_sprint_address - Convert a numeric ID into a partition name string.
+ * @ctx: The cell and authentication context
+ * @partition: The partition specified to convert
+ * @buf: The buffer to write into
+ * @buf_len: The size of the buffer
+ *
+ * Render the numeric partition ID to the standard string representation and
+ * write it into the buffer.
+ */
+void kafs_sprint_partition(struct kafs_context *ctx,
+ struct kafs_partition *partition,
+ char *buf, size_t buf_len)
+{
+ unsigned int n = partition->id;
+
+ if (n < 26) {
+ snprintf(buf, buf_len, "/vicep%c", n + 97);
+ } else if (n <= 255) {
+ n -= 26;
+ snprintf(buf, buf_len, "/vicep%c%c", n / 26 + 97, n % 26 + 97);
+ } else {
+ snprintf(buf, buf_len, "/vicep?%u", n);
+ }
+}
--- /dev/null
+/* Volume information display.
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include "kafs.h"
+#include "vlservice.h"
+#include "afs_xg.h"
+#include "display.h"
+
+
+/*
+ * Convert a volume site into a textual representation, possibly resolving it
+ * to a DNS hostname.
+ */
+void kafs_sprint_site(struct kafs_context *ctx,
+ struct kafs_vldb_site *site,
+ char *buf, size_t buf_len)
+{
+ struct kafs_fileserver *server = site->server;
+ struct sockaddr_rxrpc *addrs = server ? server->vs_addrs : NULL;
+ unsigned int nr_addrs = server ? server->vs_nr_addrs : 0;
+
+ if (buf_len < 64)
+ abort();
+
+ if (!addrs || nr_addrs == 0) {
+ if (site->has_uuid && buf_len > 40) {
+ uuid_unparse(site->uuid, buf);
+ return;
+ }
+ snprintf(buf, buf_len, "<no-addrs>");
+ return;
+ }
+
+ return kafs_sprint_address(ctx, &addrs[0], buf, buf_len);
+}
+
+/*
+ * Display the VLDB site list, looking something like:
+ *
+ * number of sites -> 2
+ * server fserver.abc.com partition /vicepa RW Site
+ * server fserver.abc.com partition /vicepa RO Site
+ */
+void kafs_display_vldb_site_list(struct kafs_context *ctx,
+ struct kafs_vldb_entry *vldb,
+ const char *indent)
+{
+ const char *ptype;
+ unsigned int i;
+ char abuf[1024], pbuf[64];
+
+ printf("%snumber of sites -> %u\n", indent, vldb->nr_sites);
+ for (i = 0; i < vldb->nr_sites; i++) {
+ struct kafs_vldb_site *site = &vldb->sites[i];
+ unsigned int flags = site->flags;
+
+ kafs_sprint_site(ctx, site, abuf, sizeof(abuf));
+ kafs_sprint_partition(ctx, &site->partition, pbuf, sizeof(pbuf));
+
+ if (flags & VLSF_ROVOL)
+ ptype = "RO";
+ else if (flags & VLSF_RWVOL)
+ ptype = "RW";
+ else
+ ptype = "Back";
+
+ printf("%s server %s partition %s %s Site\n",
+ indent, abuf, pbuf, ptype);
+ }
+
+ if (vldb->flags & (VLOP_MOVE |
+ VLOP_RELEASE |
+ VLOP_BACKUP |
+ VLOP_DELETE |
+ VLOP_DUMP)
+ ) {
+ printf("%sVolume is currently LOCKED", indent);
+ if (vldb->flags & VLOP_MOVE)
+ printf("%sVolume is locked for a move operation", indent);
+ if (vldb->flags & VLOP_RELEASE)
+ printf("%sVolume is locked for a release operation", indent);
+ if (vldb->flags & VLOP_BACKUP)
+ printf("%sVolume is locked for a backup operation", indent);
+ if (vldb->flags & VLOP_DELETE)
+ printf("%sVolume is locked for a delete/misc operation", indent);
+ if (vldb->flags & VLOP_DUMP)
+ printf("%sVolume is locked for a dump/restore operation", indent);
+ }
+}