From d97c00013dd5b13b618d08d9b6d6517176674a4e Mon Sep 17 00:00:00 2001
From: Jacob Smith <jake.smith@hdfgroup.org>
Date: Tue, 7 Apr 2020 10:16:48 -0500
Subject: Tidying of Mirror VFD.

* Rename server-stop utility to mirror_server_stop.
* Remove external dependency on bzero().
* Modify test/use_common to use only the public API.
* Rename internal bitswap macro to follow convention.
---
 MANIFEST                                    |   2 +-
 src/H5FDmirror.c                            |  20 ++-
 src/H5private.h                             |   3 -
 test/mirror_vfd.c                           |  73 ++++++----
 test/test_mirror.sh.in                      |   2 +-
 test/use_common.c                           |   6 +-
 utils/mirror_vfd/CMakeLists.txt             |  22 +--
 utils/mirror_vfd/Makefile.am                |   2 +-
 utils/mirror_vfd/mirror_server.c            |  25 +++-
 utils/mirror_vfd/mirror_server_halten_sie.c | 214 ----------------------------
 utils/mirror_vfd/mirror_server_stop.c       | 214 ++++++++++++++++++++++++++++
 utils/mirror_vfd/mirror_writer.c            |  29 +++-
 12 files changed, 342 insertions(+), 270 deletions(-)
 delete mode 100644 utils/mirror_vfd/mirror_server_halten_sie.c
 create mode 100644 utils/mirror_vfd/mirror_server_stop.c

diff --git a/MANIFEST b/MANIFEST
index 01d2df4..50e88ca 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -2788,7 +2788,7 @@
 ./utils/mirror_vfd/mirror_remote.c
 ./utils/mirror_vfd/mirror_remote.h
 ./utils/mirror_vfd/mirror_server.c
-./utils/mirror_vfd/mirror_server_halten_sie.c
+./utils/mirror_vfd/mirror_server_stop.c
 ./utils/mirror_vfd/mirror_writer.c
 
 # high level libraries
diff --git a/src/H5FDmirror.c b/src/H5FDmirror.c
index ea1f516..bcbac08 100644
--- a/src/H5FDmirror.c
+++ b/src/H5FDmirror.c
@@ -62,7 +62,8 @@ typedef struct H5FD_mirror_t {
 #define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
 #define ADDR_OVERFLOW(A)    (HADDR_UNDEF==(A) || ((A) & ~(haddr_t)MAXADDR))
 
-#define _BSWAP_64(X)                                \
+#ifndef BSWAP_64
+#define BSWAP_64(X)                                \
     (uint64_t)(  (((X) & 0x00000000000000FF) << 56) \
                | (((X) & 0x000000000000FF00) << 40) \
                | (((X) & 0x0000000000FF0000) << 24) \
@@ -71,6 +72,7 @@ typedef struct H5FD_mirror_t {
                | (((X) & 0x0000FF0000000000) >> 24) \
                | (((X) & 0x00FF000000000000) >> 40) \
                | (((X) & 0xFF00000000000000) >> 56))
+#endif /* BSWAP_64 */
 
 /* Debugging flabs for verbose tracing -- nonzero to enable */
 #define MIRROR_DEBUG_OP_CALLS 0
@@ -387,7 +389,7 @@ H5FD__mirror_xmit_decode_uint64(uint64_t *out, const unsigned char *_buf)
     HDassert(_buf && out);
     HDmemcpy(&n, _buf, sizeof(n));
     if (TRUE == is_host_little_endian()) {
-        *out = _BSWAP_64(n);
+        *out = BSWAP_64(n);
     }
     else {
         *out = n;
@@ -484,7 +486,7 @@ H5FD__mirror_xmit_encode_uint64(unsigned char *_dest, uint64_t v)
     LOG_OP_CALL("H5FD__mirror_xmit_decode_uint64");
     HDassert(_dest);
     if (TRUE == is_host_little_endian()) {
-        n = _BSWAP_64(v);
+        n = BSWAP_64(v);
     }
     HDmemcpy(_dest, &n, sizeof(n));
     return 8;
@@ -813,7 +815,11 @@ H5FD_mirror_xmit_encode_open(unsigned char                 *dest,
     size_t n_writ = 0;
     LOG_OP_CALL("H5FD_mirror_xmit_encode_open");
     HDassert(dest && x);
-    HDbzero(dest, H5FD_MIRROR_XMIT_OPEN_SIZE);
+    /* clear entire structure, but especially its filepath string area */
+    for (n_writ = 0; n_writ < H5FD_MIRROR_XMIT_OPEN_SIZE; n_writ++) {
+        *(dest+n_writ) = 0;
+    }
+    n_writ = 0;
     n_writ += H5FD_mirror_xmit_encode_header(dest,
             (const H5FD_mirror_xmit_t *)&(x->pub));
     n_writ += H5FD__mirror_xmit_encode_uint32(&dest[n_writ], x->flags);
@@ -849,7 +855,11 @@ H5FD_mirror_xmit_encode_reply(unsigned char                  *dest,
     size_t n_writ = 0;
     LOG_OP_CALL("H5FD_mirror_xmit_encode_reply");
     HDassert(dest && x);
-    HDbzero(dest, H5FD_MIRROR_XMIT_REPLY_SIZE);
+    /* clear entire structure, but especially its message string area */
+    for (n_writ = 0; n_writ < H5FD_MIRROR_XMIT_REPLY_SIZE; n_writ++) {
+        *(dest+n_writ) = 0;
+    }
+    n_writ = 0;
     n_writ += H5FD_mirror_xmit_encode_header(dest,
             (const H5FD_mirror_xmit_t *)&(x->pub));
     n_writ += H5FD__mirror_xmit_encode_uint32(&dest[n_writ], x->status);
diff --git a/src/H5private.h b/src/H5private.h
index f7fb40b..95d4885 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -717,9 +717,6 @@ typedef struct {
 #ifndef HDbsearch
     #define HDbsearch(K,B,N,Z,F)  bsearch(K,B,N,Z,F)
 #endif /* HDbsearch */
-#ifndef HDbzero
-    #define HDbzero(A,B)   bzero((A),(B)) /* mirror VFD */
-#endif /* HDbzero */
 #ifndef HDcalloc
     #define HDcalloc(N,Z)    calloc(N,Z)
 #endif /* HDcalloc */
diff --git a/test/mirror_vfd.c b/test/mirror_vfd.c
index 00902dd..112d67a 100644
--- a/test/mirror_vfd.c
+++ b/test/mirror_vfd.c
@@ -101,6 +101,31 @@ static herr_t _populate_filepath(const char *dirname, const char *_basename,
 static hid_t create_mirroring_split_fapl(const char *_basename,
         struct mirrortest_filenames *names);
 
+static void mybzero(void *dest, size_t size);
+
+
+/* ----------------------------------------------------------------------------
+ * Function:   mybzero
+ *
+ * Purpose:    Have bzero simplicity and abstraction in (possible) absence of 
+ *             it being available.
+ *
+ * Programmer: Jacob Smith
+ *             2020-03-30
+ * ----------------------------------------------------------------------------
+ */
+static void
+mybzero(void *dest, size_t size)
+{
+    size_t i = 0;
+    char *s = NULL;
+    HDassert(dest != NULL);
+    s = (char *)dest;
+    for (i = 0; i < size; i++) {
+        *(s+i) = 0;
+    }
+} /* end mybzero() */
+
 
 /* ----------------------------------------------------------------------------
  * Function:   _populate_filepath
@@ -349,8 +374,8 @@ test_xmit_encode_decode(void)
 
         /* Start of buffer uint8_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[0] = 200;
         out = 0;
         if (H5FD__mirror_xmit_encode_uint8(buf, v) != 1) {
@@ -369,8 +394,8 @@ test_xmit_encode_decode(void)
 
         /* Middle of buffer uint8_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[3] = v;
         out = 0;
         if (H5FD__mirror_xmit_encode_uint8((buf+3), v) != 1) {
@@ -389,8 +414,8 @@ test_xmit_encode_decode(void)
 
         /* End of buffer uint8_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[7] = v;
         out = 0;
         if (H5FD__mirror_xmit_encode_uint8((buf+7), v) != 1) {
@@ -419,8 +444,8 @@ test_xmit_encode_decode(void)
 
         /* Start of buffer uint16_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[0] = 0x8F;
         expected[1] = 0x02;
         out = 0;
@@ -440,8 +465,8 @@ test_xmit_encode_decode(void)
 
         /* Middle of buffer uint16_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[3] = 0x8F;
         expected[4] = 0x02;
         out = 0;
@@ -468,8 +493,8 @@ test_xmit_encode_decode(void)
 
         /* End of buffer uint16_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[6] = 0x8F;
         expected[7] = 0x02;
         out = 0;
@@ -499,8 +524,8 @@ test_xmit_encode_decode(void)
 
         /* Start of buffer uint32_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[0] = 0x8F;
         expected[1] = 0x02;
         expected[2] = 0x00;
@@ -522,8 +547,8 @@ test_xmit_encode_decode(void)
 
         /* Middle of buffer uint32_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[3] = 0x8F;
         expected[4] = 0x02;
         expected[5] = 0x00;
@@ -552,8 +577,8 @@ test_xmit_encode_decode(void)
 
         /* End of buffer uint32_t
          */
-        HDbzero(buf, 8);
-        HDbzero(expected, 8);
+        mybzero(buf, 8);
+        mybzero(expected, 8);
         expected[4] = 0x8F;
         expected[5] = 0x02;
         expected[6] = 0x00;
@@ -585,8 +610,8 @@ test_xmit_encode_decode(void)
 
         /* Start of buffer uint64_t
          */
-        HDbzero(buf, 16);
-        HDbzero(expected, 16);
+        mybzero(buf, 16);
+        mybzero(expected, 16);
         expected[0] = 0x90;
         expected[1] = 0xDC;
         expected[2] = 0xBE;
@@ -612,8 +637,8 @@ test_xmit_encode_decode(void)
 
         /* Middle of buffer uint64_t
          */
-        HDbzero(buf, 16);
-        HDbzero(expected, 16);
+        mybzero(buf, 16);
+        mybzero(expected, 16);
         expected[3]  = 0x90;
         expected[4]  = 0xDC;
         expected[5]  = 0xBE;
@@ -646,8 +671,8 @@ test_xmit_encode_decode(void)
 
         /* End of buffer uint64_t
          */
-        HDbzero(buf, 16);
-        HDbzero(expected, 16);
+        mybzero(buf, 16);
+        mybzero(expected, 16);
         expected[8]  = 0x90;
         expected[9]  = 0xDC;
         expected[10] = 0xBE;
diff --git a/test/test_mirror.sh.in b/test/test_mirror.sh.in
index 3fdc673..9635c38 100644
--- a/test/test_mirror.sh.in
+++ b/test/test_mirror.sh.in
@@ -81,7 +81,7 @@ SERVER_ARGS="$SERVER_PORT $SERVER_VERBOSITY"
 nerrors=$?
 
 echo "Stopping Mirror Server"
-./mirror_server_halten_sie $SERVER_PORT
+./mirror_server_stop $SERVER_PORT
 
 ###############################################################################
 ## Report and exit
diff --git a/test/use_common.c b/test/use_common.c
index a986543..bf29936 100644
--- a/test/use_common.c
+++ b/test/use_common.c
@@ -21,10 +21,6 @@
 
 #include "use.h"
 
-#define H5D_FRIEND        /*suppress error about including H5Dpkg      */
-#define H5D_TESTING
-#include "H5Dpkg.h" /* TODO : used to verify chunk index type (yes?) -- is there a way to do this sanity-check using the public API instead? */
-
 /* ----------------------------------------------------------------------------
  * Print a common/shared usage message.
  * Receives program name to show default test file name (<program_name>.h5).
@@ -231,7 +227,7 @@ create_uc_file(options_t * opts)
     /* Check that the chunk index type is not version 1 B-tree.
      * Version 1 B-trees are not supported under SWMR.
      */
-    if (H5D__layout_idx_type_test(dsid, &idx_type) < 0)
+    if (H5Dget_chunk_index_type(dsid, &idx_type) < 0)
         return -1;
     if (idx_type == H5D_CHUNK_IDX_BTREE) {
         HDfprintf(stderr, "ERROR: Chunk index is version 1 B-tree: aborting.\n");
diff --git a/utils/mirror_vfd/CMakeLists.txt b/utils/mirror_vfd/CMakeLists.txt
index 405c420..1926352 100644
--- a/utils/mirror_vfd/CMakeLists.txt
+++ b/utils/mirror_vfd/CMakeLists.txt
@@ -23,22 +23,22 @@ set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};mirror_server
 set (H5_DEP_EXECUTABLES ${H5_DEP_EXECUTABLES} mirror_server)
 
 #-----------------------------------------------------------------------------
-# Add the mirror_server_halten_sie executable
+# Add the mirror_server_stop executable
 #-----------------------------------------------------------------------------
 
-set (mirror_server_halt_SOURCES ${HDF5_UTILS_MIRRORVFD_SOURCE_DIR}/mirror_server_halten_sie.c)
-add_executable (mirror_server_halt ${mirror_server_halt_SOURCES})
-target_include_directories (mirror_server_halt PRIVATE "${HDF5_UITLS_DIR};${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>")
+set (mirror_server_stop_SOURCES ${HDF5_UTILS_MIRRORVFD_SOURCE_DIR}/mirror_server_stop.c)
+add_executable (mirror_server_stop ${mirror_server_stop_SOURCES})
+target_include_directories (mirror_server_stop PRIVATE "${HDF5_UITLS_DIR};${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>")
 if (NOT BUILD_SHARED_LIBS)
-  TARGET_C_PROPERTIES (mirror_server_halt STATIC)
-  target_link_libraries (mirror_server_halt PRIVATE ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET})
+  TARGET_C_PROPERTIES (mirror_server_stop STATIC)
+  target_link_libraries (mirror_server_stop PRIVATE ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET})
 else ()
-  TARGET_C_PROPERTIES (mirror_server_halt SHARED)
-  target_link_libraries (mirror_server_halt PRIVATE ${HDF5_TOOLS_LIBSH_TARGET} ${HDF5_LIBSH_TARGET})
+  TARGET_C_PROPERTIES (mirror_server_stop SHARED)
+  target_link_libraries (mirror_server_stop PRIVATE ${HDF5_TOOLS_LIBSH_TARGET} ${HDF5_LIBSH_TARGET})
 endif ()
-set_target_properties (mirror_server_halt PROPERTIES FOLDER utils)
-set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};mirror_server_halt")
-set (H5_DEP_EXECUTABLES ${H5_DEP_EXECUTABLES} mirror_server_halt)
+set_target_properties (mirror_server_stop PROPERTIES FOLDER utils)
+set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};mirror_server_stop")
+set (H5_DEP_EXECUTABLES ${H5_DEP_EXECUTABLES} mirror_server_stop)
 
 ##############################################################################
 ##############################################################################
diff --git a/utils/mirror_vfd/Makefile.am b/utils/mirror_vfd/Makefile.am
index 448e4cd..96d3104 100644
--- a/utils/mirror_vfd/Makefile.am
+++ b/utils/mirror_vfd/Makefile.am
@@ -19,7 +19,7 @@ include $(top_srcdir)/config/commence.am
 
 AM_CPPFLAGS+=-I$(top_srcdir)/src
 
-bin_PROGRAMS = mirror_server mirror_server_halten_sie
+bin_PROGRAMS = mirror_server mirror_server_stop
 
 mirror_server_SOURCES = mirror_server.c mirror_writer.c mirror_remote.c
 #mirror_writer_SOURCES = mirror_writer.c mirror_remote.c
diff --git a/utils/mirror_vfd/mirror_server.c b/utils/mirror_vfd/mirror_server.c
index 314f067..2583e60 100644
--- a/utils/mirror_vfd/mirror_server.c
+++ b/utils/mirror_vfd/mirror_server.c
@@ -137,6 +137,27 @@ struct server_run {
 
 
 /* ---------------------------------------------------------------------------
+ * Function:   mybzero
+ *
+ * Purpose:    Introduce bzero without neededing it on the system.
+ *
+ * Programmer: Jacob Smith
+ *             2020-03-30
+ * ---------------------------------------------------------------------------
+ */
+static void mybzero(void *dest, size_t size)
+{
+    size_t i = 0;
+    char  *s = NULL;
+    HDassert(dest);
+    s = (char *)dest;
+    for (i = 0; i < size; i++) {
+        *(s+i) = 0;
+    }
+} /* end mybzero() */
+
+
+/* ---------------------------------------------------------------------------
  * Function:    usage
  *
  * Purpose:     Print the usage message to stdout.
@@ -187,8 +208,8 @@ parse_args(int argc, char **argv, struct op_args *args_out)
     args_out->log_prepend_type = 1;
     args_out->verbosity = MIRROR_LOG_DEFAULT_VERBOSITY;
     /* preset empty strings */
-    HDbzero(args_out->log_path,        PATH_MAX+1);
-    HDbzero(args_out->writer_log_path, PATH_MAX+1);
+    mybzero(args_out->log_path,        PATH_MAX+1);
+    mybzero(args_out->writer_log_path, PATH_MAX+1);
 
     if (argv == NULL || *argv == NULL) {
         mirror_log(NULL, V_ERR, "invalid argv pointer");
diff --git a/utils/mirror_vfd/mirror_server_halten_sie.c b/utils/mirror_vfd/mirror_server_halten_sie.c
deleted file mode 100644
index ccd5824..0000000
--- a/utils/mirror_vfd/mirror_server_halten_sie.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright by The HDF Group.                                               *
- * All rights reserved.                                                      *
- *                                                                           *
- * This file is part of HDF5.  The full HDF5 copyright notice, including     *
- * terms governing use, modification, and redistribution, is contained in    *
- * the COPYING file, which can be found at the root of the source code       *
- * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
- * If you do not have access to either file, you may request a copy from     *
- * help@hdfgroup.org.                                                        *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*
- * Purpose:     Stop the mirror server
- *              Exists for cross-platform, optionally remote shutdown.
- */
-
-#include "H5private.h" /* System compatability call-wrapper macros */
-
-#ifdef H5_HAVE_MIRROR_VFD
-
-#define MSHS_OPTS_MAGIC 0x613B1C15u /* sanity-checking constant */
-#define MSHS_IP_STR_SIZE 20
-#define MSHS_DEFAULT_IP "127.0.0.1"
-#define MSHS_DEFAULT_PORTNO 3000
-
-
-/* ----------------------------------------------------------------------------
- * Structure:   struct mshs_opts
- *
- * Purpose:     Convenience structure to hold options as parsed from the
- *              command line.
- *
- * `magic` (uint32_t)
- *      Semi-unique constant to help verify pointer integrity.
- *
- * `help` (int)
- *      Flag that the help argument was present.
- *
- * `portno` (int)
- *      Port number, as received from arguments.
- *
- * `ip` (char *)
- *      IP address string as received from arguments.
- *
- * ----------------------------------------------------------------------------
- */
-struct mshs_opts {
-    uint32_t    magic;
-    int         help;
-    int         portno;
-    char        ip[MSHS_IP_STR_SIZE + 1];
-};
-
-
-/* ----------------------------------------------------------------------------
- * Function:    usage
- *
- * Purpose:     Print usage message to stdout.
- * ----------------------------------------------------------------------------
- */
-static void
-usage(void)
-{
-    HDprintf("mirror_server_halten_sie [options]\n"                           \
-             "System-independent Mirror Server shutdown program.\n"           \
-             "Sends shutdown message to Mirror Server at given IP:port\n"     \
-             "\n"                                                             \
-             "Options:\n"                                                     \
-             "    -h | --help Print this usage message and exit.\n"           \
-             "    --ip=ADDR   IP Address of remote server (defaut %s)\n"      \
-             "    --port=PORT Handshake port of remote server (default %d)\n",
-             MSHS_DEFAULT_IP,
-             MSHS_DEFAULT_PORTNO);
-} /* end usage() */
-
-
-/* ----------------------------------------------------------------------------
- * Function:    parse_args
- *
- * Purpose:     Parse command-line arguments, populating the options struct
- *              pointer as appropriate.
- *              Default values will be set for unspecified options.
- *
- * Return:      0 on success, negative (-1) if error.
- * ----------------------------------------------------------------------------
- */
-static int
-parse_args(int argc, char **argv, struct mshs_opts *opts)
-{
-    int i = 0;
-
-    opts->magic = MSHS_OPTS_MAGIC;
-    opts->help = 0;
-    opts->portno = MSHS_DEFAULT_PORTNO;
-    HDstrncpy(opts->ip, MSHS_DEFAULT_IP, MSHS_IP_STR_SIZE);
-
-    for (i=1; i < argc; i++) { /* start with first possible option argument */
-        if (!HDstrncmp(argv[i], "-h", 3) || !HDstrncmp(argv[i], "--help", 7)) {
-            opts->help = 1;
-        }
-        else
-        if (!HDstrncmp(argv[i], "--ip=", 5)) {
-            HDstrncpy(opts->ip, argv[i]+5, MSHS_IP_STR_SIZE);
-        }
-        else
-        if (!HDstrncmp(argv[i], "--port=", 7)) {
-            opts->portno = HDatoi(argv[i]+7);
-        }
-        else {
-            HDprintf("Unrecognized option: '%s'\n", argv[i]);
-            usage();
-            opts->magic++; /* invalidate for sanity */
-            return -1;
-        }
-    } /* end for each argument from command line */
-
-    /* auto-replace 'localhost' with numeric IP */
-    if (!HDstrncmp(opts->ip, "localhost", 10)) { /* include null terminator */
-        HDstrncpy(opts->ip, "127.0.0.1", MSHS_IP_STR_SIZE);
-    }
-
-    return 0;
-} /* end parse_args() */
-
-
-/* ----------------------------------------------------------------------------
- * Function:    send_shutdown
- *
- * Purpose:     Create socket and send shutdown signal to remote server.
- *
- * Return:      0 on success, negative (-1) if error.
- * ----------------------------------------------------------------------------
- */
-static int
-send_shutdown(struct mshs_opts *opts)
-{
-    int                live_socket;
-    struct sockaddr_in target_addr;
-
-    if (opts->magic != MSHS_OPTS_MAGIC) {
-       HDprintf("invalid options structure\n");
-       return -1;
-    }
-
-    live_socket = HDsocket(AF_INET, SOCK_STREAM, 0);
-    if (live_socket < 0) {
-        HDprintf("ERROR socket()\n");
-        return -1;
-    }
-
-    target_addr.sin_family = AF_INET;
-    target_addr.sin_port = HDhtons((uint16_t)opts->portno);
-    target_addr.sin_addr.s_addr = HDinet_addr(opts->ip);
-    HDmemset(target_addr.sin_zero, '\0', sizeof(target_addr.sin_zero));
-
-    if (HDconnect(live_socket, (struct sockaddr *)&target_addr,
-            (socklen_t)sizeof(target_addr))
-        < 0)
-    {
-        HDprintf("ERROR connect() (%d)\n%s\n", errno, HDstrerror(errno));
-        return -1;
-    }
-
-    if (HDwrite(live_socket, "SHUTDOWN", 9) == -1) {
-        HDprintf("ERROR write() (%d)\n%s\n", errno, HDstrerror(errno));
-        return -1;
-    }
-
-    if (HDclose(live_socket) < 0) {
-        HDprintf("ERROR close() can't close socket\n");
-        return -1;
-    }
-
-    return 0;
-} /* end send_shutdown() */
-
-
-/* ------------------------------------------------------------------------- */
-int
-main(int argc, char **argv)
-{
-    struct mshs_opts opts;
-
-    if (parse_args(argc, argv, &opts) < 0) {
-        HDprintf("Unable to parse arguments\n");
-        return EXIT_FAILURE;
-    }
-
-    if (opts.help) {
-        usage();
-        return EXIT_SUCCESS;
-    }
-
-    if (send_shutdown(&opts) < 0) {
-        HDprintf("Unable to send shutdown command\n");
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-} /* end main() */
-
-#else /* H5_HAVE_MIRROR_VFD */
-
-
-/* ------------------------------------------------------------------------- */
-int
-main(int argc, char **argv)
-{
-    HDprintf("Mirror VFD not built -- unable to perform shutdown.\n");
-    return EXIT_FAILURE;
-}
-
-#endif /* H5_HAVE_MIRROR_VFD */
diff --git a/utils/mirror_vfd/mirror_server_stop.c b/utils/mirror_vfd/mirror_server_stop.c
new file mode 100644
index 0000000..ccd5824
--- /dev/null
+++ b/utils/mirror_vfd/mirror_server_stop.c
@@ -0,0 +1,214 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group.                                               *
+ * All rights reserved.                                                      *
+ *                                                                           *
+ * This file is part of HDF5.  The full HDF5 copyright notice, including     *
+ * terms governing use, modification, and redistribution, is contained in    *
+ * the COPYING file, which can be found at the root of the source code       *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
+ * If you do not have access to either file, you may request a copy from     *
+ * help@hdfgroup.org.                                                        *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose:     Stop the mirror server
+ *              Exists for cross-platform, optionally remote shutdown.
+ */
+
+#include "H5private.h" /* System compatability call-wrapper macros */
+
+#ifdef H5_HAVE_MIRROR_VFD
+
+#define MSHS_OPTS_MAGIC 0x613B1C15u /* sanity-checking constant */
+#define MSHS_IP_STR_SIZE 20
+#define MSHS_DEFAULT_IP "127.0.0.1"
+#define MSHS_DEFAULT_PORTNO 3000
+
+
+/* ----------------------------------------------------------------------------
+ * Structure:   struct mshs_opts
+ *
+ * Purpose:     Convenience structure to hold options as parsed from the
+ *              command line.
+ *
+ * `magic` (uint32_t)
+ *      Semi-unique constant to help verify pointer integrity.
+ *
+ * `help` (int)
+ *      Flag that the help argument was present.
+ *
+ * `portno` (int)
+ *      Port number, as received from arguments.
+ *
+ * `ip` (char *)
+ *      IP address string as received from arguments.
+ *
+ * ----------------------------------------------------------------------------
+ */
+struct mshs_opts {
+    uint32_t    magic;
+    int         help;
+    int         portno;
+    char        ip[MSHS_IP_STR_SIZE + 1];
+};
+
+
+/* ----------------------------------------------------------------------------
+ * Function:    usage
+ *
+ * Purpose:     Print usage message to stdout.
+ * ----------------------------------------------------------------------------
+ */
+static void
+usage(void)
+{
+    HDprintf("mirror_server_halten_sie [options]\n"                           \
+             "System-independent Mirror Server shutdown program.\n"           \
+             "Sends shutdown message to Mirror Server at given IP:port\n"     \
+             "\n"                                                             \
+             "Options:\n"                                                     \
+             "    -h | --help Print this usage message and exit.\n"           \
+             "    --ip=ADDR   IP Address of remote server (defaut %s)\n"      \
+             "    --port=PORT Handshake port of remote server (default %d)\n",
+             MSHS_DEFAULT_IP,
+             MSHS_DEFAULT_PORTNO);
+} /* end usage() */
+
+
+/* ----------------------------------------------------------------------------
+ * Function:    parse_args
+ *
+ * Purpose:     Parse command-line arguments, populating the options struct
+ *              pointer as appropriate.
+ *              Default values will be set for unspecified options.
+ *
+ * Return:      0 on success, negative (-1) if error.
+ * ----------------------------------------------------------------------------
+ */
+static int
+parse_args(int argc, char **argv, struct mshs_opts *opts)
+{
+    int i = 0;
+
+    opts->magic = MSHS_OPTS_MAGIC;
+    opts->help = 0;
+    opts->portno = MSHS_DEFAULT_PORTNO;
+    HDstrncpy(opts->ip, MSHS_DEFAULT_IP, MSHS_IP_STR_SIZE);
+
+    for (i=1; i < argc; i++) { /* start with first possible option argument */
+        if (!HDstrncmp(argv[i], "-h", 3) || !HDstrncmp(argv[i], "--help", 7)) {
+            opts->help = 1;
+        }
+        else
+        if (!HDstrncmp(argv[i], "--ip=", 5)) {
+            HDstrncpy(opts->ip, argv[i]+5, MSHS_IP_STR_SIZE);
+        }
+        else
+        if (!HDstrncmp(argv[i], "--port=", 7)) {
+            opts->portno = HDatoi(argv[i]+7);
+        }
+        else {
+            HDprintf("Unrecognized option: '%s'\n", argv[i]);
+            usage();
+            opts->magic++; /* invalidate for sanity */
+            return -1;
+        }
+    } /* end for each argument from command line */
+
+    /* auto-replace 'localhost' with numeric IP */
+    if (!HDstrncmp(opts->ip, "localhost", 10)) { /* include null terminator */
+        HDstrncpy(opts->ip, "127.0.0.1", MSHS_IP_STR_SIZE);
+    }
+
+    return 0;
+} /* end parse_args() */
+
+
+/* ----------------------------------------------------------------------------
+ * Function:    send_shutdown
+ *
+ * Purpose:     Create socket and send shutdown signal to remote server.
+ *
+ * Return:      0 on success, negative (-1) if error.
+ * ----------------------------------------------------------------------------
+ */
+static int
+send_shutdown(struct mshs_opts *opts)
+{
+    int                live_socket;
+    struct sockaddr_in target_addr;
+
+    if (opts->magic != MSHS_OPTS_MAGIC) {
+       HDprintf("invalid options structure\n");
+       return -1;
+    }
+
+    live_socket = HDsocket(AF_INET, SOCK_STREAM, 0);
+    if (live_socket < 0) {
+        HDprintf("ERROR socket()\n");
+        return -1;
+    }
+
+    target_addr.sin_family = AF_INET;
+    target_addr.sin_port = HDhtons((uint16_t)opts->portno);
+    target_addr.sin_addr.s_addr = HDinet_addr(opts->ip);
+    HDmemset(target_addr.sin_zero, '\0', sizeof(target_addr.sin_zero));
+
+    if (HDconnect(live_socket, (struct sockaddr *)&target_addr,
+            (socklen_t)sizeof(target_addr))
+        < 0)
+    {
+        HDprintf("ERROR connect() (%d)\n%s\n", errno, HDstrerror(errno));
+        return -1;
+    }
+
+    if (HDwrite(live_socket, "SHUTDOWN", 9) == -1) {
+        HDprintf("ERROR write() (%d)\n%s\n", errno, HDstrerror(errno));
+        return -1;
+    }
+
+    if (HDclose(live_socket) < 0) {
+        HDprintf("ERROR close() can't close socket\n");
+        return -1;
+    }
+
+    return 0;
+} /* end send_shutdown() */
+
+
+/* ------------------------------------------------------------------------- */
+int
+main(int argc, char **argv)
+{
+    struct mshs_opts opts;
+
+    if (parse_args(argc, argv, &opts) < 0) {
+        HDprintf("Unable to parse arguments\n");
+        return EXIT_FAILURE;
+    }
+
+    if (opts.help) {
+        usage();
+        return EXIT_SUCCESS;
+    }
+
+    if (send_shutdown(&opts) < 0) {
+        HDprintf("Unable to send shutdown command\n");
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+} /* end main() */
+
+#else /* H5_HAVE_MIRROR_VFD */
+
+
+/* ------------------------------------------------------------------------- */
+int
+main(int argc, char **argv)
+{
+    HDprintf("Mirror VFD not built -- unable to perform shutdown.\n");
+    return EXIT_FAILURE;
+}
+
+#endif /* H5_HAVE_MIRROR_VFD */
diff --git a/utils/mirror_vfd/mirror_writer.c b/utils/mirror_vfd/mirror_writer.c
index fe5dac7..e1ab1b2 100644
--- a/utils/mirror_vfd/mirror_writer.c
+++ b/utils/mirror_vfd/mirror_writer.c
@@ -157,11 +157,34 @@ struct mirror_writer_opts {
     char       *logpath;
 };
 
+static void mybzero(void *dest, size_t size);
+
 static int do_open(struct mirror_session *session,
         const H5FD_mirror_xmit_open_t *xmit_open);
 
 
 /* ---------------------------------------------------------------------------
+ * Function:   mybzero
+ *
+ * Purpose:    Introduce bzero without neededing it on the system.
+ *
+ * Programmer: Jacob Smith
+ *             2020-03-30
+ * ---------------------------------------------------------------------------
+ */
+static void mybzero(void *dest, size_t size)
+{
+    size_t i = 0;
+    char *s = NULL;
+    HDassert(dest);
+    s = (char *)dest;
+    for (i = 0; i < size; i++) {
+        *(s+i) = 0;
+    }
+} /* end mybzero() */
+
+
+/* ---------------------------------------------------------------------------
  * Function:    session_init
  *
  * Purpose:     Populate mirror_session structure with default and
@@ -199,7 +222,7 @@ session_init(struct mirror_writer_opts *opts)
     session->reply.pub.version       = H5FD_MIRROR_XMIT_CURR_VERSION;
     session->reply.pub.op            = H5FD_MIRROR_OP_REPLY;
     session->reply.pub.session_token = 0;
-    HDbzero(session->reply.message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
+    mybzero(session->reply.message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
 
     /* Options-derived population
      */
@@ -381,7 +404,7 @@ reply_ok(struct mirror_session *session)
     mirror_log(session->loginfo, V_ALL, "reply_ok()");
 
     reply->status = H5FD_MIRROR_STATUS_OK;
-    HDbzero(reply->message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
+    mybzero(reply->message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
     return _xmit_reply(session);
 } /* end reply_ok() */
 
@@ -876,7 +899,7 @@ receive_communique(
 
     mirror_log(session->loginfo, V_INFO, "receive_communique()");
 
-    HDbzero(comm->raw, comm->raw_size);
+    mybzero(comm->raw, comm->raw_size);
     comm->recd_die = 0;
 
     mirror_log(session->loginfo, V_INFO, "ready to receive"); /* TODO */
-- 
cgit v0.12