]> www.infradead.org Git - users/dhowells/kafs-utils.git/commitdiff
Common display/formatting routines
authorDavid Howells <dhowells@redhat.com>
Thu, 9 Jul 2020 10:27:04 +0000 (11:27 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 5 May 2023 10:53:26 +0000 (11:53 +0100)
Add some common display and output formatting routines.

Signed-off-by: David Howells <dhowells@redhat.com>
kafs/Makefile
kafs/display.C [new file with mode: 0644]
kafs/display.H
kafs/display_vol.C [new file with mode: 0644]

index 28b9147abc575aa26ed78c15372d396276e332e7..c673349e3a4bd4eeae85c018f3cd7cd6b630768f 100644 (file)
@@ -7,7 +7,9 @@ CORE_SRCS := \
        kafs.C \
        arg_completion.C \
        arg_parse.C \
+       display.C \
        display_error.C \
+       display_vol.C \
        misc.C \
        vl_fileservers.C \
        vl_probe.C \
diff --git a/kafs/display.C b/kafs/display.C
new file mode 100644 (file)
index 0000000..379b616
--- /dev/null
@@ -0,0 +1,169 @@
+/* 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 <iostream>
+#include <fmt/chrono.h>
+#include <netdb.h>
+//#include <arpa/inet.h>
+#include "kafs.H"
+#include "vlservice.H"
+#include "afs_xg.H"
+#include "display.H"
+
+using rxrpc::ref;
+
+std::string kafs::sprint_time(const Time &time)
+{
+       return fmt::format("{:%a %b %d %H:%M:%S %Y}", fmt::localtime(time.seconds()));
+}
+
+/**
+ * kafs::sprint_time_or_never - Print a time in standard format
+ * @time: The time to display.
+ *
+ * Print a time in a standard format for AFS tools to a string.  If @time is 0,
+ * then "Never" will be printed instead.
+ */
+std::string kafs::sprint_time_or_never(const Time &time)
+{
+       if (time.seconds() == 0)
+               return "Never";
+       else
+               return kafs::sprint_time(time);
+}
+
+/**
+ * kafs::print_time - Print a time in standard format
+ * @time: The time to display.
+ *
+ * Print a time in a standard format for AFS tools to stdout.
+ */
+void kafs::print_time(const Time &time)
+{
+       time_t t = time.seconds();
+       struct tm tm;
+       char buf[128];
+
+       localtime_r(&t, &tm);
+       strftime(buf, 128, "%a %b %d %H:%M:%S %Y", &tm);
+       std::cout << buf;
+}
+
+/**
+ * kafs::print_time_or_never - Print a time in standard format
+ * @time: The time to display.
+ *
+ * Print a time in a standard format for AFS tools to stdout.  If @time is 0,
+ * then "Never" will be printed instead.
+ */
+void kafs::print_time_or_never(const Time &time)
+{
+       if (time.seconds() == 0)
+               std::cout << "Never";
+       else
+               kafs::print_time(time);
+}
+
+/**
+ * kafs::sprint_address - Convert/resolve an address into text
+ * @ctx: The cell and authentication context
+ * @addr: The address to convert
+ *
+ * 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.
+ */
+std::string kafs::sprint_address(Context *ctx,
+                                const struct sockaddr_rxrpc &addr)
+{
+       unsigned short port;
+       char buf[1024], service[64], *b;
+       size_t len;
+       int hint, ni;
+
+       hint = NI_DGRAM | NI_NUMERICSERV;
+
+       if (!ctx->no_resolve) {
+               hint |= NI_NAMEREQD;
+               ni = getnameinfo((struct sockaddr *)&addr.transport,
+                                addr.transport_len,
+                                buf, sizeof(buf), service, sizeof(service), hint);
+               if (ni == EAI_MEMORY)
+                       throw rxrpc::nomem();
+               if (ni == 0)
+                       return fmt::format("{}:{}", buf, service);
+       }
+
+       hint &= ~NI_NAMEREQD;
+       hint |= NI_NUMERICHOST;
+       b = buf + 1;
+       ni = getnameinfo((struct sockaddr *)&addr.transport,
+                        addr.transport_len,
+                        b, sizeof(buf) - 2, service, sizeof(service), hint);
+       if (ni == EAI_MEMORY)
+               throw rxrpc::nomem();
+
+       if (strchr(b, ':')) {
+               len = strlen(b);
+               b[-1] = '[';
+               b[len] = ']';
+               b[len + 1] = 0;
+               b--;
+       }
+
+       if (ni == 0)
+               return fmt::format("{}:{}", b, service);
+
+       buf[0] = 0;
+       switch (addr.transport.sin.sin_family) {
+       case AF_INET:
+               inet_ntop(AF_INET, &addr.transport.sin.sin_addr, buf, sizeof(buf));
+               port = ntohs(addr.transport.sin.sin_port);
+               break;
+       case AF_INET6:
+               buf[0] = '[';
+               inet_ntop(AF_INET6, &addr.transport.sin6.sin6_addr, buf + 1, sizeof(buf) - 2);
+               len = strlen(buf);
+               buf[len] = ']';
+               buf[len + 1] = 0;
+               port = ntohs(addr.transport.sin6.sin6_port);
+               break;
+       default:
+               return fmt::format("<af-{}>", addr.transport.sin.sin_family);
+       }
+
+       if (port == afs::FS_PORT)
+               return std::string(buf);
+
+       return fmt::format("{}+{:d}", b, 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
+ *
+ * Render the numeric partition ID to the standard string representation and
+ * write it into the buffer.
+ */
+std::string kafs::sprint_partition(const Partition_spec &partition)
+{
+       unsigned int n = partition.id;
+
+       if (n < 26) {
+               return fmt::format("/vicep{:c}", (char)(n + 97));
+       } else if (n <= 255) {
+               n -= 26;
+               return fmt::format("/vicep{:c}{:c}", (char)(n / 26 + 97), (char)(n % 26 + 97));
+       } else {
+               return fmt::format("/vicep?{:d}", n);
+       }
+}
index 26c0fdf636e08ba0be9d476b27b688dc89716b55..e76b9af4a84aa0eed94cc87b6eec091a95750109 100644 (file)
 
 namespace kafs {
 
+struct Vldb_entry;
+struct Vldb_site;
+
+/*
+ * display.C
+ */
+extern std::string sprint_time(const Time &);
+extern std::string sprint_time_or_never(const Time &);
+extern void print_time(const Time &);
+extern void print_time_or_never(const Time &);
+extern std::string sprint_address(Context *, const struct sockaddr_rxrpc &);
+extern std::string sprint_partition(const Partition_spec &);
+
 /*
  * display_error.C
  */
 extern bool kafs_display_error(Context *);
 
+/*
+ * display_vol.C
+ */
+extern std::string sprint_site(Context *, Vldb_site &);
+extern void display_vldb_site_list(Context *, Vldb_entry *, const char *);
+
 } /* end namespace kafs */
 
 #endif /* DISPLAY_H */
diff --git a/kafs/display_vol.C b/kafs/display_vol.C
new file mode 100644 (file)
index 0000000..d38c059
--- /dev/null
@@ -0,0 +1,96 @@
+/* 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 <iostream>
+#include <fmt/format.h>
+#include "kafs.H"
+#include "vlservice.H"
+#include "afs_xg.H"
+#include "display.H"
+
+using rxrpc::ref;
+
+/*
+ * Convert a volume site into a textual representation, possibly resolving it
+ * to a DNS hostname.
+ */
+std::string kafs::sprint_site(Context *ctx, Vldb_site &vldb_site)
+{
+       FS_site *site = vldb_site.fs_site;
+
+       if (!site)
+               return "<no-server>";
+
+       std::vector<sockaddr_rxrpc> &addrs = site->vs_addrs;
+
+       if (!addrs.size()) {
+               if (vldb_site.has_uuid) {
+                       char buf[48];
+                       uuid_unparse(vldb_site.uuid.uuid, buf);
+                       return std::string(buf);
+               }
+               return "<no-addrs>";
+       }
+
+       return sprint_address(ctx, addrs[0]);
+}
+
+/*
+ * 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(Context *ctx,
+                                 Vldb_entry *vldb,
+                                 const char *indent)
+{
+       const char *ptype;
+       unsigned int i;
+
+       std::cout << indent << "number of sites -> " << vldb->sites.size() << "\n";
+       for (i = 0; i < vldb->sites.size(); i++) {
+               Vldb_site &site = vldb->sites[i];
+               unsigned int flags = site.flags;
+
+               if (flags & afs::VLSF_ROVOL)
+                       ptype = "RO";
+               else if (flags & afs::VLSF_RWVOL)
+                       ptype = "RW";
+               else
+                       ptype = "Back";
+
+               std::cout << indent
+                         << "   server " << sprint_site(ctx, site)
+                         << " partition " << sprint_partition(site.partition)
+                         << " " << ptype << " Site\n";
+       }
+
+       if (vldb->flags & (afs::VLOP_MOVE |
+                          afs::VLOP_RELEASE |
+                          afs::VLOP_BACKUP |
+                          afs::VLOP_DELETE |
+                          afs::VLOP_DUMP)
+           ) {
+               std::cout << indent << "Volume is currently LOCKED\n";
+               if (vldb->flags & afs::VLOP_MOVE)
+                       std::cout << indent << "Volume is locked for a move operation\n";
+               if (vldb->flags & afs::VLOP_RELEASE)
+                       std::cout << indent << "Volume is locked for a release operation\n";
+               if (vldb->flags & afs::VLOP_BACKUP)
+                       std::cout << indent << "Volume is locked for a backup operation\n";
+               if (vldb->flags & afs::VLOP_DELETE)
+                       std::cout << indent << "Volume is locked for a delete/misc operation\n";
+               if (vldb->flags & afs::VLOP_DUMP)
+                       std::cout << indent << "Volume is locked for a dump/restore operation\n";
+       }
+}