lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] master 4cafdca 02/22: Add lmi_md5sum utility impleme


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 4cafdca 02/22: Add lmi_md5sum utility implementing subset of standard md5sum
Date: Sat, 28 Mar 2020 18:23:35 -0400 (EDT)

branch: master
commit 4cafdca49f78038e154942cd4bcba00809d688b9
Author: Ilya Sinitsyn <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Add lmi_md5sum utility implementing subset of standard md5sum
    
    Implement a limited functionality variant of GNU 'md5sum' command line
    utility.
    
    This avoids dependency on the non-Cygwin MSW md5sum.exe binary as now
    lmi_md5sum.exe can be distributed as part of the fardel distribution and
    Cygwin md5sum can be used during lmi build.
---
 Makefile.am              |  11 ++
 authenticity_test.cpp    |  20 ++--
 install_miscellanea.make |  29 +-----
 md5sum_cli.cpp           | 259 +++++++++++++++++++++++++++++++++++++++++++++++
 objects.make             |   8 ++
 set_toolchain.sh         |   2 +-
 system_command_test.cpp  |   6 +-
 workhorse.make           |  14 +--
 8 files changed, 300 insertions(+), 49 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index b69df63..5620892 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,6 +44,7 @@ bin_PROGRAMS = \
     lmi_cli \
     lmi_wx \
     elapsed_time \
+    lmi_md5sum \
     generate_passkey \
     antediluvian_cli \
     ihs_crc_comp \
@@ -456,6 +457,16 @@ libwx_new_la_LIBADD = $(WX_LIBS)
 
 # auxiliary executables
 
+lmi_md5sum_SOURCES = \
+    getopt.cpp \
+    md5.cpp \
+    md5sum.cpp \
+    md5sum_cli.cpp
+lmi_md5sum_CXXFLAGS = $(AM_CXXFLAGS) $(BOOST_INCLUDE_FLAGS)
+lmi_md5sum_LDADD = \
+    $(BOOST_LIBS) \
+    libmain_auxiliary_common.la
+
 generate_passkey_SOURCES = \
     authenticity.cpp \
     calendar_date.cpp \
diff --git a/authenticity_test.cpp b/authenticity_test.cpp
index 4e51f33..9202864 100644
--- a/authenticity_test.cpp
+++ b/authenticity_test.cpp
@@ -110,15 +110,15 @@ PasskeyTest::~PasskeyTest()
     RemoveTestFiles(__FILE__, __LINE__);
 }
 
-/// Regrettably, invoking 'md5sum' through a shell just to confirm its
+/// Regrettably, invoking 'lmi_md5sum' through a shell just to confirm its
 /// availability writes its output to stdout; however, without this
 /// test, it would be difficult to tell whether downstream errors stem
 /// from that program's absence.
 
 void PasskeyTest::EnsureMd5sumBinaryIsFound() const
 {
-    std::cout << "  Result of 'md5sum --version':" << std::endl;
-    system_command("md5sum --version");
+    std::cout << "  Result of 'lmi_md5sum --version':" << std::endl;
+    system_command("lmi_md5sum --version");
 }
 
 void PasskeyTest::RemoveTestFiles(char const* file, int line) const
@@ -169,19 +169,19 @@ void PasskeyTest::InitializeDataFile() const
     BOOST_TEST_EQUAL("bf039dbb0e8061971a2c322c8336199c", md5_str(sum));
 }
 
-/// Write a data file to be passed to the 'md5sum' program.
+/// Write a data file to be passed to the 'lmi_md5sum' program.
 ///
 /// For production, a file with md5 sums of crucial files is provided.
 /// For this unit test, file 'coleridge' is the sole crucial file.
 ///
 /// This file consists of the md5 sum of the data file followed by two
 /// spaces and the name of the data file. Creating that file portably
-/// here by running 'md5sum' would require redirection, which isn't
-/// part of the standard C++ library, so the effect of 'md5sum' is
-/// instead emulated; testing that file here with 'md5sum' validates
-/// that emulation and guards against a bogus 'md5sum' program.
+/// here by running 'lmi_md5sum' would require redirection, which isn't
+/// part of the standard C++ library, so the effect of 'lmi_md5sum' is
+/// instead emulated; testing that file here with 'lmi_md5sum' validates
+/// that emulation and guards against a bogus 'lmi_md5sum' program.
 ///
-/// Postcondition: the file passes a test with the 'md5sum' program.
+/// Postcondition: the file passes a test with the 'lmi_md5sum' program.
 
 void PasskeyTest::InitializeMd5sumFile() const
 {
@@ -197,7 +197,7 @@ void PasskeyTest::InitializeMd5sumFile() const
     os << "  coleridge\n";
     os.close();
 
-    std::string s = "md5sum --check --status " + std::string(md5sum_file());
+    std::string s = "lmi_md5sum --check --status " + 
std::string(md5sum_file());
     system_command(s);
 }
 
diff --git a/install_miscellanea.make b/install_miscellanea.make
index 556f27e..ba8ae9c 100644
--- a/install_miscellanea.make
+++ b/install_miscellanea.make
@@ -47,7 +47,6 @@ third_party_source_dir  := $(dest_dir)/src
 boost_archive    := boost_1_33_1.tar.bz2
 cgicc_archive    := cgicc-3.1.4.tar.bz2
 jing_archive     := jing-20091111.zip
-md5sum_msw_exe   := md5sum.exe
 sample_archive   := lmi-data-20050618T1440Z.tar.bz2
 trang_archive    := trang-20091111.zip
 xmlwrapp_archive := xmlwrapp-0.9.0.tar.gz
@@ -56,14 +55,12 @@ file_list := \
   $(boost_archive) \
   $(cgicc_archive) \
   $(jing_archive) \
-  $(md5sum_msw_exe) \
   $(sample_archive) \
   $(trang_archive) \
   $(xmlwrapp_archive) \
 
 boost cgicc xmlwrapp: stem = $(basename $(basename $($@_archive)))
 jing trang:           stem =            $(basename $($@_archive))
-md5sum_msw:           stem = $(md5sum_msw_exe)
 sample:               stem = data
 
 # URLs and archive md5sums 
#####################################################
@@ -71,7 +68,6 @@ sample:               stem = data
 $(boost_archive)-url    := $(sf_mirror)/boost/$(boost_archive)
 $(cgicc_archive)-url    := ftp://ftp.gnu.org/pub/gnu/cgicc/$(cgicc_archive)
 $(jing_archive)-url     := 
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/$(jing_archive)
-$(md5sum_msw_exe)-url   := 
https://github.com/vadz/lmi/releases/download/new-cygwin-makefiles/md5sum.exe
 $(sample_archive)-url   := 
https://download.savannah.gnu.org/releases/lmi/$(sample_archive)
 $(trang_archive)-url    := 
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/$(trang_archive)
 $(xmlwrapp_archive)-url := 
https://github.com/vslavik/xmlwrapp/releases/download/v0.9.0/$(xmlwrapp_archive)
@@ -79,7 +75,6 @@ $(xmlwrapp_archive)-url := 
https://github.com/vslavik/xmlwrapp/releases/download
 $(boost_archive)-md5    := 2b999b2fb7798e1737d1fff8fac602ef
 $(cgicc_archive)-md5    := 6cb5153fc9fa64b4e50c7962aa557bbe
 $(jing_archive)-md5     := 13eef193921409a1636377d1efbf9843
-$(md5sum_msw_exe)-md5   := eb574b236133e60c989c6f472f07827b
 $(sample_archive)-md5   := e7f07133abfc3b9c2252dfa3b61191bc
 $(trang_archive)-md5    := 9d31799b948c350850eb9dd14e5b832d
 $(xmlwrapp_archive)-md5 := 5e8ac678ab03b7c60ce61ac5424e0849
@@ -120,7 +115,7 @@ ad_hoc_dir_exists = \
 # Targets 
######################################################################
 
 .PHONY: all
-all: boost cgicc jing md5sum_msw sample trang xmlwrapp
+all: boost cgicc jing sample trang xmlwrapp
 
 # Patches were generated according to this advice:
 #
@@ -188,28 +183,6 @@ jing: $(file_list)
        $(MV) $(ad_hoc_dir)/$(stem)/bin/$@.jar         $(dest_dir)/rng
        $(MV) $(ad_hoc_dir)/$(stem)/bin/xercesImpl.jar $(dest_dir)/rng
 
-# The 'md5sum_msw' binary is redistributed to msw end users for
-# authentication, so the 'fardel' target requires it. On other
-# platforms, it cannot be executed directly, but it is needed for
-# creating a cross 'fardel' and for running cross unit tests.
-#
-# It is placed in lmi's 'third_party/bin/' subdirectory--imperatively
-# not in lmi's 'local/bin/' subdirectory, which is added to $PATH.
-# For cygwin builds, the expressly downloaded 'md5sum.exe' is kept off
-# $PATH to prevent it from shadowing cygwin's own version. However,
-# for cross builds, it cannot shadow the native 'md5sum', yet some
-# cross-built unit tests require an msw binary, so add its directory
-# to $WINEPATH to make those tests work (incidentally, 'wine' doesn't
-# find it if it's simply symlinked).
-#
-# Should the given URL ever become invalid, see:
-#   http://www.openoffice.org/dev_docs/using_md5sums.html#links
-# to find another.
-
-.PHONY: md5sum_msw
-md5sum_msw: $(file_list)
-       $(CP) --preserve $(cache_dir)/$(stem) $(third_party_bin_dir)
-
 # The 'clobber' target doesn't remove $(prefix)/data because that
 # directory might contain valuable user-customized files; hence, in
 # this case, $(MKDIR) must be allowed to fail.
diff --git a/md5sum_cli.cpp b/md5sum_cli.cpp
new file mode 100644
index 0000000..b558882
--- /dev/null
+++ b/md5sum_cli.cpp
@@ -0,0 +1,259 @@
+// Limited functionality variant of GNU `md5sum` program.
+//
+// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 
2013, 2014, 2015, 2016, 2017, 2018, 2019 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; ifnot, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#include "pchfile.hpp"
+
+#include "getopt.hpp"
+#include "main_common.hpp"
+#include "md5sum.hpp"
+
+#include <iostream>
+
+int usage(int status)
+{
+    if(status != EXIT_SUCCESS)
+        {
+        std::cerr << "Try 'lmi_md5sum --help' for more information.\n";
+        }
+    else
+        {
+        std::cout
+            <<
+R"(Usage: lmi_md5sum [OPTION]... [FILE]...
+Print or check MD5 (128-bit) checksums.
+
+  -b, --binary   read in binary mode (default)
+  -c, --check    read MD5 sums from the FILEs and check them
+  -t, --text     read in text mode
+
+The following two options are useful only when verifying checksums:
+      --quiet    don't print OK for each successfully verified file
+      --status   don't output anything, status code shows success
+
+      --help     display this help and exit
+      --version  output version information and exit
+
+The sums are computed as described in RFC 1321.  When checking, the input
+should be a former output of this program. The default mode is to print a
+line with checksum, a space, a character indicating input mode ('*' for binary
+' ' for text or where binary is insignificant), and name for each FILE.
+
+This program is a limited functionality variant of GNU 'md5sum' utility
+and is part of the 'Let Me Illustrate' project.
+)"
+        ;
+        }
+    return status;
+}
+
+void version()
+{
+    std::cout
+        <<
+R"(lmi_md5sum 0.9
+
+This program is a limited functionality variant of GNU 'md5sum' utility
+and is part of the 'Let Me Illustrate' project.
+)"
+        ;
+}
+
+// For long options that have no equivalent short option, use a
+// non-character as a pseudo short option, starting with CHAR_MAX + 1.
+enum
+{
+    STATUS_OPTION = CHAR_MAX + 1,
+    QUIET_OPTION,
+    HELP_OPTION,
+    VERSION_OPTION
+};
+
+int try_main(int argc, char* argv[])
+{
+    bool all_ok = true;
+    int c;
+    int option_index = 0;
+    struct Option long_options[] =
+        {
+            {"binary"      ,NO_ARG   ,0 ,'b'            ,0 ,""},
+            {"check"       ,NO_ARG   ,0 ,'c'            ,0 ,""},
+            {"quiet"       ,NO_ARG   ,0 ,QUIET_OPTION   ,0 ,""},
+            {"status"      ,NO_ARG   ,0 ,STATUS_OPTION  ,0 ,""},
+            {"text"        ,NO_ARG   ,0 ,'t'            ,0 ,""},
+            {"help"        ,NO_ARG   ,0 ,HELP_OPTION    ,0 ,""},
+            {"version"     ,NO_ARG   ,0 ,VERSION_OPTION ,0 ,""},
+            {0             ,NO_ARG   ,0 ,0              ,0 ,""}
+        };
+
+    bool show_help = false;
+    bool show_version = false;
+    bool binary = true;
+    bool have_input_mode_option = false;
+    bool do_check = false;
+    bool command_line_syntax_error = false;
+
+    // With --check, don't generate any output.
+    // The exit code indicates success or failure.
+    bool status_only = false;
+
+    // With --check, suppress the "OK" printed for each verified file.
+    bool quiet = false;
+
+    GetOpt getopt_long
+        (argc
+        ,argv
+        ,"chv"
+        ,long_options
+        ,&option_index
+        ,1
+        );
+
+    while(EOF != (c = getopt_long ()))
+        {
+        switch (c)
+            {
+            case 'b':
+                have_input_mode_option = true;
+                break;
+            case 'c':
+                do_check = true;
+                break;
+            case QUIET_OPTION:
+                quiet = true;
+                break;
+            case STATUS_OPTION:
+                status_only = true;
+                break;
+            case 't':
+                binary = false;
+                have_input_mode_option = true;
+                break;
+            case HELP_OPTION:
+                show_help = true;
+                break;
+            case VERSION_OPTION:
+                show_version = true;
+                break;
+            default:
+                // Error message was already given from getopt() code, so no 
need
+                // to output anything else here, but do flush its output so 
that it
+                // appears before the usage message.
+                std::fflush(stderr);
+
+                command_line_syntax_error = true;
+            }
+
+        if(command_line_syntax_error)
+            break;
+        }
+
+    if(command_line_syntax_error)
+        {
+        std::cerr << "Try 'lmi_md5sum --help' for more information." << 
std::endl;
+        return EXIT_FAILURE;
+        }
+    if(have_input_mode_option && do_check)
+        {
+        std::cerr
+            << "The --binary and --text options are meaningless when "
+            << "verifying checksums."
+            << std::endl
+            ;
+        return usage(EXIT_FAILURE);
+        }
+    if(status_only && !do_check)
+        {
+        std::cerr
+            << "The --status option is meaningful only when verifying 
checksums."
+            << std::endl
+            ;
+        return usage(EXIT_FAILURE);
+        }
+    if(quiet && !do_check)
+        {
+        std::cerr
+            << "The --quiet option is meaningful only when verifying 
checksums."
+            << std::endl
+            ;
+        return usage(EXIT_FAILURE);
+        }
+    if(show_help)
+        {
+        return usage(EXIT_SUCCESS);
+        }
+
+    if(show_version)
+        {
+        version();
+        return EXIT_SUCCESS;
+        }
+
+    try
+        {
+        for(int i = getopt_long.optind; i < argc; ++i)
+            {
+            char const* filename = argv[i];
+            std::string md5;
+
+            if(do_check)
+                {
+                auto const sums = md5_read_checksum_file(filename);
+
+                for(auto const& s : sums)
+                    {
+                    md5 = md5_calculate_file_checksum(s.filename, s.file_mode);
+
+                    bool const current_ok = md5 == s.md5sum;
+                    if(!status_only)
+                        {
+                        if(!current_ok || !quiet)
+                            {
+                            std::cout
+                                << s.filename.string()
+                                << ": "
+                                << (current_ok ? "OK" : "FAILED")
+                                << std::endl
+                                ;
+                            }
+                        }
+                    all_ok &= current_ok;
+                    }
+                }
+            else
+                {
+                md5 = md5_calculate_file_checksum
+                    (filename
+                    ,binary ? md5_file_mode::binary : md5_file_mode::text
+                    );
+
+                std::cout << md5 << " " << (binary ? "*" : " ") << filename << 
std::endl;
+                }
+            }
+        }
+    catch(std::runtime_error const& e)
+        {
+        if(!status_only)
+            std::cerr << "lmi_md5sum: " << e.what() << std::endl;
+        return EXIT_FAILURE;
+        }
+
+    return all_ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/objects.make b/objects.make
index 2ac7dca..8b9dc0e 100644
--- a/objects.make
+++ b/objects.make
@@ -1084,6 +1084,14 @@ elapsed_time$(EXEEXT): \
   system_command_non_wx.o \
   timer.o \
 
+lmi_md5sum$(EXEEXT): \
+  $(boost_filesystem_objects) \
+  $(main_auxiliary_common_objects) \
+  getopt.o \
+  md5.o \
+  md5sum.o \
+  md5sum_cli.o \
+
 generate_passkey$(EXEEXT): \
   $(boost_filesystem_objects) \
   $(main_auxiliary_common_objects) \
diff --git a/set_toolchain.sh b/set_toolchain.sh
index e2f959c..70ed5b8 100755
--- a/set_toolchain.sh
+++ b/set_toolchain.sh
@@ -90,7 +90,7 @@ local   lmi_build_type
 local      prefix="/opt/lmi"
 local localbindir="$prefix/local/${LMI_COMPILER}_${LMI_TRIPLET}/bin"
 local locallibdir="$prefix/local/${LMI_COMPILER}_${LMI_TRIPLET}/lib"
-# $winebindir is where 'install_miscellanea.make' places 'md5sum.exe'.
+# $winebindir is where 'make install' places 'lmi_md5sum.exe'.
 local  winebindir="$prefix"/third_party/bin
 
 # Running a command like this many times:
diff --git a/system_command_test.cpp b/system_command_test.cpp
index 88d4805..cac4984 100644
--- a/system_command_test.cpp
+++ b/system_command_test.cpp
@@ -39,13 +39,13 @@ int test_main(int, char*[])
     os1 << "e87dfb7b7c7f87985d3eff4782c172b8  eraseme\n";
     os1.close();
 
-    system_command("md5sum --check --status eraseme.md5");
+    system_command("lmi_md5sum --check --status eraseme.md5");
 
     BOOST_TEST_THROW
-        (system_command("md5sum --check --status eraseme")
+        (system_command("lmi_md5sum --check --status eraseme")
         ,std::runtime_error
         ,lmi_test::what_regex
-            ("Exit code [0-9]* from command 'md5sum --check --status 
eraseme'.")
+            ("Exit code [0-9]* from command 'lmi_md5sum --check --status 
eraseme'.")
         );
 
 #if !defined LMI_MSW
diff --git a/workhorse.make b/workhorse.make
index 6995430..2b84580 100644
--- a/workhorse.make
+++ b/workhorse.make
@@ -112,6 +112,7 @@ ifeq (,$(USE_SO_ATTRIBUTES))
     bcc_ld$(EXEEXT) \
     bcc_rc$(EXEEXT) \
     elapsed_time$(EXEEXT) \
+    lmi_md5sum$(EXEEXT) \
     generate_passkey$(EXEEXT) \
     ihs_crc_comp$(EXEEXT) \
     rate_table_tool$(EXEEXT) \
@@ -1058,7 +1059,6 @@ installable_binaries := \
   $(default_targets) \
   $(wildcard $(localbindir)/*$(SHREXT)) \
   $(wildcard $(locallibdir)/*$(SHREXT)) \
-  $(wildcard $(prefix)/third_party/bin/*$(EXEEXT)) \
 
 .PHONY: install
 install: $(default_targets)
@@ -1076,6 +1076,7 @@ ifeq (,$(USE_SO_ATTRIBUTES))
 else
        @$(ECHO) "Can't build product_files$(EXEEXT) with USE_SO_ATTRIBUTES."
 endif
+       @$(CP) --preserve lmi_md5sum$(EXEEXT) $(prefix)/third_party/bin
 
 
################################################################################
 
@@ -1176,11 +1177,11 @@ fardel_files := \
 
 # Sensitive files are authenticated at run time.
 #
-# Binary files other than 'md5sum$(EXEEXT)' are not authenticated
+# Binary files other than 'lmi_md5sum$(EXEEXT)' are not authenticated
 # because they aren't easily forged but are sizable enough to make
 # authentication too slow. An incorrect version of any such file might
 # be distributed by accident, but that problem would not be caught by
-# generating an md5sum for the incorrect file. 'md5sum$(EXEEXT)' is
+# generating an md5sum for the incorrect file. 'lmi_md5sum$(EXEEXT)' is
 # however authenticated because replacing it with a program that
 # always reports success would circumvent authentication.
 #
@@ -1199,7 +1200,7 @@ fardel_checksummed_files = \
   $(extra_fardel_checksummed_files) \
   *.dat *.database *.funds *.ndx *.policy *.rounding *.strata *.xst \
   expiry \
-  md5sum$(EXEEXT) \
+  lmi_md5sum$(EXEEXT) \
 
 .PHONY: fardel
 fardel: install
@@ -1207,15 +1208,14 @@ fardel: install
        @$(MAKE) --file=$(this_makefile) --directory=$(fardel_dir) wrap_fardel
        @$(ECHO) "Created '$(fardel_name)' archive in '$(fardel_root)'."
 
-# A native 'md5sum$(EXEEXT)' must be provided because lmi uses it for
-# run-time authentication.
+# A native 'lmi_md5sum$(EXEEXT)' is provided to be used by end users.
 #
 # $(CP) is used without '--update' so that custom extra files can
 # replace defaults regardless of their datestamps.
 
 .PHONY: wrap_fardel
 wrap_fardel:
-       @$(CP) $(prefix)/third_party/bin/md5sum$(EXEEXT) .
+       @$(CP) $(prefix)/third_party/bin/lmi_md5sum$(EXEEXT) .
        @$(CP) $(datadir)/configurable_settings.xml .
        @$(CP) $(datadir)/company_logo.png .
        @$(CP) $(datadir)/group_quote_banner.png .



reply via email to

[Prev in Thread] Current Thread [Next in Thread]