Hello community, here is the log from the commit of package md5deep for openSUSE:Factory checked in at 2012-03-12 20:15:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/md5deep (Old) and /work/SRC/openSUSE:Factory/.md5deep.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "md5deep", Maintainer is "" Changes: -------- --- /work/SRC/openSUSE:Factory/md5deep/md5deep.changes 2012-02-01 09:58:19.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.md5deep.new/md5deep.changes 2012-03-12 20:15:46.000000000 +0100 @@ -1,0 +2,15 @@ +Thu Feb 23 12:49:44 UTC 2012 - [email protected] + +- Updated to version 4.1 +- Add smp_flags and optflags to make +- update licente tag + +* New Features + + Added expert mode option to parse Windows PE files + +* Bug Fixes + + Fixed junction point handling on Win32 + +------------------------------------------------------------------- Old: ---- md5deep-4.0.1.tar.gz New: ---- md5deep-4.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ md5deep.spec ++++++ --- /var/tmp/diff_new_pack.s587sr/_old 2012-03-12 20:15:48.000000000 +0100 +++ /var/tmp/diff_new_pack.s587sr/_new 2012-03-12 20:15:48.000000000 +0100 @@ -16,17 +16,16 @@ # - Name: md5deep -Version: 4.0.1 +Version: 4.1 Release: 0 -License: GPL-2.0+ Summary: Compute MD5, SHA-1, SHA-256, Tiger or Whirlpool message digests -Url: http://md5deep.sourceforge.net/ +License: SUSE-Public-Domain and GPL-2.0+ Group: System/Base +Url: http://md5deep.sourceforge.net/ Source0: %{name}-%{version}.tar.gz -BuildRequires: gcc-c++ BuildRequires: fdupes +BuildRequires: gcc-c++ BuildRequires: python BuildRequires: python-devel Requires: python @@ -39,13 +38,13 @@ hashes in a variety of formats. %prep -%setup -q -n %{name}-%{version} +%setup -q %build if test -x ./configure; then %configure fi -make +make %{?_smp_mflags} CFLAGS="%{optflags}" %install @@ -56,12 +55,6 @@ # create hardlinks for the rest %fdupes %{buildroot} -#%check -# -# look how to do the checks in future -#cd tests -#sh tests.sh - %clean rm -rf %{buildroot} ++++++ md5deep-4.0.1.tar.gz -> md5deep-4.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/ChangeLog new/md5deep-4.1/ChangeLog --- old/md5deep-4.0.1/ChangeLog 2012-01-22 18:10:36.000000000 +0100 +++ new/md5deep-4.1/ChangeLog 2012-02-10 14:32:04.000000000 +0100 @@ -1,3 +1,35 @@ +2012-02-10 Jesse Kornblum <[email protected]>: + + * sample-hashes/sample.{c,jpg}: Added Windows executable with non-executable extension + * src/winpe.cpp, main.cpp, dig.cpp: Added comments + * configure.ac: Version bump to 4.1 + * src/*.cpp: Added $Id$ tags + +2012-02-08 Jesse Kornblum <[email protected]>: + + * src/dig.cpp, winpe.h, winpe.cpp, main.cpp: Added check for Windows PE files to expert mode. + +2012-01-30 Jesse Kornblum <[email protected]:> + + * src/display.cpp: Reverted previous change, but updated test for presence of vasprintf. + +2012-01-29 Jesse Kornblum <[email protected]>: + + * src/dig.cpp: Check for junction points before adding files to queue + * src/display.cpp: Removed redefinition of vasprintf. It is apparently now part of the compiler's stdio.h + +2012-01-28 Jesse Kornblum <[email protected]>: + + * configure.ac: Version bump to 4.0.2-001 + +2012-01-28 Simson Garfinkel <simsong@mucha> + + * src/display.cpp (display::dfxml_write): strange; sstream should have been stringstream. Well, it's fixed now. + +2012-01-23 Simson Garfinkel <[email protected]> + + * src/helpers.cpp: successfully removed itos(). + 2012-01-22 Jesse Kornblum <[email protected]>: * src/threadpool.h: Removed debugging fprintf @@ -25,7 +57,7 @@ * Makefile.am: Changed rule for converting man pages to Windows text files 2012-01-06 Jesse Kornblum <[email protected]> - + * configure.ac: Version bump to 4.0.0 * src/hashlist.cpp: Legibility changes only. * doc/Makefile: Updating man page locations diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/NEWS new/md5deep-4.1/NEWS --- old/md5deep-4.0.1/NEWS 2012-01-22 18:10:36.000000000 +0100 +++ new/md5deep-4.1/NEWS 2012-02-14 16:53:57.000000000 +0100 @@ -1,3 +1,15 @@ +** Changes in version 4.1.0 (14 Feb 2012) + +* New Features + + Added expert mode option to parse Windows PE files + +* Bug Fixes + + Fixed junction point handling on Win32 + + + ** Changes in version 4.0.1 (22 Jan 2012) * Bug Fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/TODO new/md5deep-4.1/TODO --- old/md5deep-4.0.1/TODO 2012-01-06 13:29:34.000000000 +0100 +++ new/md5deep-4.1/TODO 2012-02-08 16:13:55.000000000 +0100 @@ -75,3 +75,9 @@ and SHA256 go dramatically faster. + +================ +Remaining: + +* - Change all codes to UTF8 in all modes of operation +* - Option to include BOM in plain text output mode. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/configure new/md5deep-4.1/configure --- old/md5deep-4.0.1/configure 2012-01-22 18:10:37.000000000 +0100 +++ new/md5deep-4.1/configure 2012-02-10 14:32:06.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for MD5DEEP 4.0.1. +# Generated by GNU Autoconf 2.68 for MD5DEEP 4.1. # # Report bugs to <[email protected]>. # @@ -560,8 +560,8 @@ # Identity of this package. PACKAGE_NAME='MD5DEEP' PACKAGE_TARNAME='md5deep' -PACKAGE_VERSION='4.0.1' -PACKAGE_STRING='MD5DEEP 4.0.1' +PACKAGE_VERSION='4.1' +PACKAGE_STRING='MD5DEEP 4.1' PACKAGE_BUGREPORT='[email protected]' PACKAGE_URL='' @@ -1264,7 +1264,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures MD5DEEP 4.0.1 to adapt to many kinds of systems. +\`configure' configures MD5DEEP 4.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1334,7 +1334,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of MD5DEEP 4.0.1:";; + short | recursive ) echo "Configuration of MD5DEEP 4.1:";; esac cat <<\_ACEOF @@ -1429,7 +1429,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -MD5DEEP configure 4.0.1 +MD5DEEP configure 4.1 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1947,7 +1947,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by MD5DEEP $as_me 4.0.1, which was +It was created by MD5DEEP $as_me 4.1, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2764,7 +2764,7 @@ # Define the identity of the package. PACKAGE='md5deep' - VERSION='4.0.1' + VERSION='4.1' cat >>confdefs.h <<_ACEOF @@ -7253,7 +7253,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by MD5DEEP $as_me 4.0.1, which was +This file was extended by MD5DEEP $as_me 4.1, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7319,7 +7319,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -MD5DEEP config.status 4.0.1 +MD5DEEP config.status 4.1 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/configure.ac new/md5deep-4.1/configure.ac --- old/md5deep-4.0.1/configure.ac 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/configure.ac 2012-02-10 14:31:58.000000000 +0100 @@ -3,7 +3,7 @@ # AC_PREREQ(2.57) -AC_INIT([MD5DEEP],[4.0.1],[[email protected]]) +AC_INIT([MD5DEEP],[4.1],[[email protected]]) AC_CONFIG_FILES([Makefile src/Makefile man/Makefile tests/Makefile tests/testfiles/Makefile ]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([config.h]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/man/hashdeep.1 new/md5deep-4.1/man/hashdeep.1 --- old/md5deep-4.0.1/man/hashdeep.1 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/man/hashdeep.1 2012-02-14 16:53:57.000000000 +0100 @@ -1,4 +1,4 @@ -.TH HASHDEEP "1" "v4.0.1 \- 22 Jan 2012" "AFOSI" "United States Air Force" +.TH HASHDEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force" .SH NAME hashdeep \- Compute, compare, or audit multiple message digests @@ -9,7 +9,7 @@ .br .B hashdeep [-c <alg1>[,<alg2>]] [-k <file>] [-i <size>] [\-f <file>] -[\-o <fbcplsd>] [-amxwMXrespblvv] [\-F<bum>] [\-jnn] [\fBFILES\fR] +[\-o <fbcplsde>] [-amxwMXrespblvv] [\-F<bum>] [\-jnn] [\fBFILES\fR] .SH DESCRIPTION @@ -161,6 +161,8 @@ s \- Sockets .br d \- Solaris Doors +.br +e \- Windows PE executables .TP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/man/md5deep.1 new/md5deep-4.1/man/md5deep.1 --- old/md5deep-4.0.1/man/md5deep.1 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/man/md5deep.1 2012-02-14 16:53:57.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MD5DEEP "1" "v4.0.1 \- 22 Jan 2012" "AFOSI" "United States Air Force" +.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force" .SH NAME md5deep \- Compute and compare MD5 message digests @@ -18,7 +18,7 @@ .B md5deep [\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>] [\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>] -[\-o <fbcplsd>] [\-jnn] [[\fBFILES\fR] +[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR] .SH DESCRIPTION .PP @@ -219,6 +219,8 @@ s \- Sockets .br d \- Solaris Doors +.br +e \- Windows PE executables .TP \fB-jnn\fR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/man/sha1deep.1 new/md5deep-4.1/man/sha1deep.1 --- old/md5deep-4.0.1/man/sha1deep.1 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/man/sha1deep.1 2012-02-14 16:53:57.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MD5DEEP "1" "v4.0.1 \- 22 Jan 2012" "AFOSI" "United States Air Force" +.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force" .SH NAME md5deep \- Compute and compare MD5 message digests @@ -18,7 +18,7 @@ .B md5deep [\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>] [\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>] -[\-o <fbcplsd>] [\-jnn] [[\fBFILES\fR] +[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR] .SH DESCRIPTION .PP @@ -219,6 +219,8 @@ s \- Sockets .br d \- Solaris Doors +.br +e \- Windows PE executables .TP \fB-jnn\fR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/man/sha256deep.1 new/md5deep-4.1/man/sha256deep.1 --- old/md5deep-4.0.1/man/sha256deep.1 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/man/sha256deep.1 2012-02-14 16:53:57.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MD5DEEP "1" "v4.0.1 \- 22 Jan 2012" "AFOSI" "United States Air Force" +.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force" .SH NAME md5deep \- Compute and compare MD5 message digests @@ -18,7 +18,7 @@ .B md5deep [\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>] [\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>] -[\-o <fbcplsd>] [\-jnn] [[\fBFILES\fR] +[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR] .SH DESCRIPTION .PP @@ -219,6 +219,8 @@ s \- Sockets .br d \- Solaris Doors +.br +e \- Windows PE executables .TP \fB-jnn\fR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/man/tigerdeep.1 new/md5deep-4.1/man/tigerdeep.1 --- old/md5deep-4.0.1/man/tigerdeep.1 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/man/tigerdeep.1 2012-02-14 16:53:57.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MD5DEEP "1" "v4.0.1 \- 22 Jan 2012" "AFOSI" "United States Air Force" +.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force" .SH NAME md5deep \- Compute and compare MD5 message digests @@ -18,7 +18,7 @@ .B md5deep [\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>] [\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>] -[\-o <fbcplsd>] [\-jnn] [[\fBFILES\fR] +[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR] .SH DESCRIPTION .PP @@ -219,6 +219,8 @@ s \- Sockets .br d \- Solaris Doors +.br +e \- Windows PE executables .TP \fB-jnn\fR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/man/whirlpooldeep.1 new/md5deep-4.1/man/whirlpooldeep.1 --- old/md5deep-4.0.1/man/whirlpooldeep.1 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/man/whirlpooldeep.1 2012-02-14 16:53:57.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MD5DEEP "1" "v4.0.1 \- 22 Jan 2012" "AFOSI" "United States Air Force" +.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force" .SH NAME md5deep \- Compute and compare MD5 message digests @@ -18,7 +18,7 @@ .B md5deep [\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>] [\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>] -[\-o <fbcplsd>] [\-jnn] [[\fBFILES\fR] +[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR] .SH DESCRIPTION .PP @@ -219,6 +219,8 @@ s \- Sockets .br d \- Solaris Doors +.br +e \- Windows PE executables .TP \fB-jnn\fR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/Makefile.am new/md5deep-4.1/src/Makefile.am --- old/md5deep-4.0.1/src/Makefile.am 2012-01-06 13:29:31.000000000 +0100 +++ new/md5deep-4.1/src/Makefile.am 2012-02-08 16:13:55.000000000 +0100 @@ -8,7 +8,7 @@ all_sources = $(ALGS) main.cpp hashlist.cpp multihash.cpp display.cpp \ hash.cpp dig.cpp helpers.cpp xml.cpp xml.h files.cpp common.h main.h \ utf8.h utf8/checked.h utf8/core.h utf8/unchecked.h \ - threadpool.h threadpool.cpp + threadpool.h threadpool.cpp winpe.cpp winpe.h hashdeep_SOURCES = $(all_sources) md5deep_SOURCES = $(all_sources) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/Makefile.in new/md5deep-4.1/src/Makefile.in --- old/md5deep-4.0.1/src/Makefile.in 2012-01-22 18:10:37.000000000 +0100 +++ new/md5deep-4.1/src/Makefile.in 2012-02-10 14:32:06.000000000 +0100 @@ -60,7 +60,7 @@ am__objects_2 = $(am__objects_1) main.$(OBJEXT) hashlist.$(OBJEXT) \ multihash.$(OBJEXT) display.$(OBJEXT) hash.$(OBJEXT) \ dig.$(OBJEXT) helpers.$(OBJEXT) xml.$(OBJEXT) files.$(OBJEXT) \ - threadpool.$(OBJEXT) + threadpool.$(OBJEXT) winpe.$(OBJEXT) am_hashdeep_OBJECTS = $(am__objects_2) hashdeep_OBJECTS = $(am_hashdeep_OBJECTS) hashdeep_LDADD = $(LDADD) @@ -207,7 +207,7 @@ all_sources = $(ALGS) main.cpp hashlist.cpp multihash.cpp display.cpp \ hash.cpp dig.cpp helpers.cpp xml.cpp xml.h files.cpp common.h main.h \ utf8.h utf8/checked.h utf8/core.h utf8/unchecked.h \ - threadpool.h threadpool.cpp + threadpool.h threadpool.cpp winpe.cpp winpe.h hashdeep_SOURCES = $(all_sources) md5deep_SOURCES = $(all_sources) @@ -325,6 +325,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadpool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tiger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whirlpool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/winpe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml.Po@am__quote@ .c.o: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/dig.cpp new/md5deep-4.1/src/dig.cpp --- old/md5deep-4.0.1/src/dig.cpp 2012-01-06 13:29:31.000000000 +0100 +++ new/md5deep-4.1/src/dig.cpp 2012-02-10 14:31:58.000000000 +0100 @@ -15,9 +15,10 @@ * and call hash_file(fn) for every file that needs to be hashes. */ -// $Id: dig.cpp 557 2011-12-17 22:23:34Z xchatty $ +// $Id: dig.cpp 618 2012-02-10 12:12:38Z jessekornblum $ #include "main.h" +#include "winpe.h" #include <iostream> /**************************************************************** @@ -33,7 +34,7 @@ tstring fn = global::get_realpath(fn_); dir_table_t::iterator pos = dir_table.find(fn); if(pos==dir_table.end()){ - ocb.internal_error("%s: Directory %s not found in done_processing_dir", progname.c_str(), fn.c_str()); + ocb.internal_error("%s: Directory '%s' not found in done_processing_dir", progname.c_str(), fn.c_str()); // will not be reached. } dir_table.erase(pos); @@ -43,9 +44,10 @@ void state::processing_dir(const tstring &fn_) { tstring fn = global::get_realpath(fn_); - if(dir_table.find(fn)!=dir_table.end()){ - ocb.internal_error("%s: Attempt to add existing %s in processing_dir", progname.c_str(), fn.c_str()); - // will not be reached. + if (dir_table.find(fn)!=dir_table.end()) + { + ocb.internal_error("%s: Attempt to add existing %s in processing_dir", progname.c_str(), fn.c_str()); + // will not be reached. } dir_table.insert(fn); } @@ -138,6 +140,8 @@ << ":" << global::make_utf8(pszMessage) << "\n"; LocalFree(pszMessage); } + + // An NTFS Junction Point is like a hard link on *nix but only works // on the same filesystem and only for directories. Unfortunately they // can also create infinite loops for programs that recurse filesystems. @@ -148,34 +152,41 @@ // given filename is a junction point. Otherwise it returns FALSE. bool state::is_junction_point(const std::wstring &fn) { - int status = FALSE; - - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - - hFind = FindFirstFile(fn.c_str(), &FindFileData); - if (INVALID_HANDLE_VALUE != hFind) { - if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - // We're going to skip this reparse point no matter what, - // but we may want to display a message just in case. - // TODO: Maybe have the option to follow symbolic links? - status = TRUE; - - if (IO_REPARSE_TAG_MOUNT_POINT == FindFileData.dwReserved0) { - ocb.error_filename(fn,"Junction point, skipping"); - } else if (IO_REPARSE_TAG_SYMLINK == FindFileData.dwReserved0) { - ocb.error_filename(fn,"Symbolic link, skipping"); - } else { - ocb.error_filename(fn,"Unknown reparse point 0x%"PRIx32", skipping", - FindFileData.dwReserved0); - } - } - - // We don't error check this call as there's nothing to do differently - // if it fails. - FindClose(hFind); + int status = false; + + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + + hFind = FindFirstFile(fn.c_str(), &FindFileData); + if (INVALID_HANDLE_VALUE != hFind) + { + if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + { + // We're going to skip this reparse point no matter what, + // but we may want to display a message just in case. + // TODO: Maybe have the option to follow symbolic links? + status = true; + + if (IO_REPARSE_TAG_MOUNT_POINT == FindFileData.dwReserved0) + { + ocb.error_filename(fn,"Junction point, skipping"); + } + else if (IO_REPARSE_TAG_SYMLINK == FindFileData.dwReserved0) + { + ocb.error_filename(fn,"Symbolic link, skipping"); + } + else + { + ocb.error_filename(fn,"Unknown reparse point 0x%"PRIx32", skipping", + FindFileData.dwReserved0); + } } - return status; + + // We don't error check this call as there's nothing to do differently + // if it fails. + FindClose(hFind); + } + return status; } // This is experimental code for reparse point process // We don't use it yet, but I don't want to delete it @@ -349,24 +360,31 @@ * 4. Process them. */ std::vector<tstring> dir_entries; - while ((entry = _treaddir(current_dir)) != NULL) { - if (is_special_dir(entry->d_name)) continue; // ignore . and .. - - // compute full path - // don't append if the DIR_SEPARATOR if there is already one there - tstring new_file = fn; - if(new_file.size()==0 || new_file[new_file.size()-1]!=DIR_SEPARATOR){ - new_file.push_back(DIR_SEPARATOR); - } - new_file.append(entry->d_name); - dir_entries.push_back(new_file); + while ((entry = _treaddir(current_dir)) != NULL) + { + // ignore . and .. + if (is_special_dir(entry->d_name)) + continue; + + // compute full path + // don't append if the DIR_SEPARATOR if there is already one there + tstring new_file = fn; + + if (0 == new_file.size() || new_file[new_file.size()-1]!=DIR_SEPARATOR) + { + new_file.push_back(DIR_SEPARATOR); + } + new_file.append(entry->d_name); #ifdef _WIN32 - if (is_junction_point(new_file)){ // whatever this is, ignore it - continue; - } + /// Windows Junction points + if (is_junction_point(new_file)){ + continue; + } #endif + dir_entries.push_back(new_file); + } _tclosedir(current_dir); // done with this directory @@ -417,6 +435,14 @@ #define TLSTAT(path,buf) lstat(path,buf) #endif +/* This is coming... */ +#if 0 +HFILE filehandle; +(void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo); +file->fileindexhi = fileinfo.nFileIndexHigh; +file->fileindexlo = fileinfo.nFileIndexLow; +#endif + /* Return the 'decoded' file type of a file. * If an error is found and ocb is provided, send the error to ocb. * If filesize and ctime are provided, give them. @@ -486,7 +512,37 @@ if (link_type) *link_type = type; return true; } - + + +/// Returns true if the filename fn is a Windows PE executable +/// +/// If the filename is a PE executable but does not have an executable +/// extension, displays an error message. If the file cannot be read, +/// returns false. +/// +/// @param fn Filename to examine +bool state::should_hash_winpe(const tstring &fn) +{ + bool executable_extension = has_executable_extension(fn); + + FILE * handle = _tfopen(fn.c_str(),_TEXT("rb")); + if (NULL == handle) + { + ocb.error_filename(fn,"%s", strerror(errno)); + return false; + } + + unsigned char buffer[PETEST_BUFFER_SIZE] = {0}; + size_t size = fread(buffer,1,PETEST_BUFFER_SIZE,handle); + fclose(handle); + + bool status = is_pe_file(buffer, size); + + if (status and not executable_extension) + ocb.error_filename(fn,"Is Windows executable but does not have executable extension"); + + return status; +} /* * Type should be the result of calling lstat on the file. @@ -496,47 +552,66 @@ */ bool state::should_hash_expert(const tstring &fn, file_types type) { - file_types link_type=stat_unknown; - switch(type) { - case stat_directory: - if (mode_recursive){ - process_dir(fn); - } - else { - ocb.error_filename(fn,"Is a directory"); - } - return FALSE; + file_types link_type=stat_unknown; + if (stat_directory == type) + { + if (mode_recursive) + process_dir(fn); + else + ocb.error_filename(fn,"Is a directory"); + + return false; + } - // We can't just return s->mode & mode_X because mode_X is - // a 64-bit value. When that value gets converted back to int, - // the high part of it is lost. + if (mode_winpe) + { + // The user could have requested PE files *and* something else + // therefore we don't return false here if the file is not a PE. + // Note that we have to check for directories first! + if (should_hash_winpe(fn)) + return true; + } + switch(type) + { + // We can't just return s->mode & mode_X because mode_X is + // a 64-bit value. When that value gets converted back to int, + // the high part of it is lost. + #define RETURN_IF_MODE(A) if (A) return true; break; - case stat_regular: RETURN_IF_MODE(mode_regular); - case stat_block: RETURN_IF_MODE(mode_block); - case stat_character: RETURN_IF_MODE(mode_character); - case stat_pipe: RETURN_IF_MODE(mode_pipe); - case stat_socket: RETURN_IF_MODE(mode_socket); - case stat_door: RETURN_IF_MODE(mode_door); - case stat_symlink: - - // Although it might appear that we need nothing more than - // return (s->mode & mode_symlink); - // that doesn't work. That logic gets into trouble when we're - // running in recursive mode on a symlink to a directory. - // The program attempts to open the directory entry itself - // and gets into an infinite loop. - - if (!(mode_symlink)) return false; - if (should_hash_symlink(fn,&link_type)){ - return should_hash_expert(fn,link_type); - } - return false; - case stat_unknown: - ocb.error_filename(fn,"unknown file type"); - return false; + case stat_directory: + // This case should be handled above. This statement is + // here to avoid compiler warnings + ocb.internal_error("Did not handle directory entry in should_hash_expert()"); + + case stat_regular: RETURN_IF_MODE(mode_regular); + case stat_block: RETURN_IF_MODE(mode_block); + case stat_character: RETURN_IF_MODE(mode_character); + case stat_pipe: RETURN_IF_MODE(mode_pipe); + case stat_socket: RETURN_IF_MODE(mode_socket); + case stat_door: RETURN_IF_MODE(mode_door); + case stat_symlink: + + // Although it might appear that we need nothing more than + // return (s->mode & mode_symlink); + // that doesn't work. That logic gets into trouble when we're + // running in recursive mode on a symlink to a directory. + // The program attempts to open the directory entry itself + // and gets into an infinite loop. + + if (!(mode_symlink)) + return false; + if (should_hash_symlink(fn,&link_type)) + { + return should_hash_expert(fn,link_type); } return false; + case stat_unknown: + ocb.error_filename(fn,"unknown file type"); + return false; + } + + return false; } @@ -547,9 +622,10 @@ bool state::should_hash(const tstring &fn) { - file_types type = state::file_type(fn,&ocb,0,0,0,0); + file_types type = state::file_type(fn,&ocb,0,0,0,0); - if (mode_expert) return should_hash_expert(fn,type); + if (mode_expert) + return should_hash_expert(fn,type); if (type == stat_directory) { if (mode_recursive){ @@ -598,9 +674,9 @@ std::wstring win32_dirname(const std::wstring &fn) { size_t loc = fn.rfind(DIR_SEPARATOR); - if(loc==tstring::npos){ - std::cerr << "returning empty\n"; - return tstring(); // return empty string + if (loc==tstring::npos) + { + return tstring(); // return empty string } return fn.substr(0,loc); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/display.cpp new/md5deep-4.1/src/display.cpp --- old/md5deep-4.0.1/src/display.cpp 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/src/display.cpp 2012-02-10 14:31:58.000000000 +0100 @@ -2,6 +2,8 @@ #include "utf8.h" #include <stdarg.h> +// $Id: display.cpp 618 2012-02-10 12:12:38Z jessekornblum $ + /** * * display.cpp: @@ -56,7 +58,7 @@ /* * on mingw the have_vasprintf check succedes, but it really isn't there */ -#if !defined(HAVE_VASPRINTF) || defined(_WIN32) +#if defined(HAVE_VASPRINTF) && defined(__MINGW_H) extern "C" { /** * We do not have vasprintf. @@ -823,7 +825,9 @@ if(dfxml){ std::string attrs; if(opt_verbose && fdht->workerid>=0){ - attrs = "workerid='"+itos(fdht->workerid)+"'"; + std::stringstream ss; + ss << "workerid='" << fdht->workerid << "'"; + attrs = ss.str(); } lock(); dfxml->push("fileobject",attrs); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/helpers.cpp new/md5deep-4.1/src/helpers.cpp --- old/md5deep-4.0.1/src/helpers.cpp 2012-01-06 13:29:31.000000000 +0100 +++ new/md5deep-4.1/src/helpers.cpp 2012-01-29 21:09:30.000000000 +0100 @@ -10,20 +10,10 @@ // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // -// $Id: helpers.cpp 468 2011-08-13 00:16:48Z xchatty $ +// $Id: helpers.cpp 601 2012-01-24 17:45:03Z xchatty $ #include "main.h" -std::string itos(uint64_t i) -{ - char buf[256]; - snprintf(buf,sizeof(buf),"%"PRIu64,i); - return std::string(buf); -} - - - - // Remove the newlines, if any. Works on both DOS and *nix newlines void chop_line(char *s) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/main.cpp new/md5deep-4.1/src/main.cpp --- old/md5deep-4.0.1/src/main.cpp 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/src/main.cpp 2012-02-10 14:31:58.000000000 +0100 @@ -1,6 +1,6 @@ /* * - * $Id: main.cpp 595 2012-01-22 00:28:03Z xchatty $ + * $Id: main.cpp 618 2012-02-10 12:12:38Z jessekornblum $ * * This is the main() function and support functions for hashdeep and md5deep. * @@ -172,9 +172,9 @@ ocb.status("-B - verbose mode; repeat for more verbosity"); ocb.status("-C - Macintosh only --- use Common Crypto hash functions"); ocb.status("-Fb - I/O mode buffered; -Fu unbuffered; -Fm memory-mapped"); - ocb.status("-o[bcpflsd] - only process certain types of files:"); + ocb.status("-o[bcpflsde] - only process certain types of files:"); ocb.status(" b=block dev; c=character dev; p=named pipe"); - ocb.status(" f=regular file; l=symlink; s=socket; d=door"); + ocb.status(" f=regular file; l=symlink; s=socket; d=door e=Windows PE"); ocb.status("-Dnn - set debug level to nn"); } if(usage_count==3){ // -hhh - adds debugging information @@ -233,9 +233,9 @@ ocb.status("-C - Macintosh only --- use Common Crypto hash functions"); ocb.status("-Fb - I/O mode buffered; -Fu unbuffered; -Fm memory-mapped"); ocb.status("-ffilename - take list of files to hash from filename"); - ocb.status("-o[bcpflsd] - only process certain types of files:"); + ocb.status("-o[bcpflsde] - only process certain types of files:"); ocb.status(" b=block dev; c=character dev; p=named pipe"); - ocb.status(" f=regular file; l=symlink; s=socket; d=door"); + ocb.status(" f=regular file; l=symlink; s=socket; d=door e=Windows PE"); ocb.status("-Dnn - set debug level to nn"); } if(usage_count==3){ // -hhh @@ -556,22 +556,24 @@ { for(unsigned int i=0;i<strlen(arg);i++){ switch(arg[i]){ + case 'e': // Windows PE executables + mode_winpe = true; break; case 'b': // Block Device - mode_block = true; break; + mode_block = true; break; case 'c': // Character Device - mode_character = true; break; + mode_character = true; break; case 'p': // Named Pipe - mode_pipe=true; break; + mode_pipe=true; break; case 'f': // Regular File - mode_regular=true; break; + mode_regular=true; break; case 'l': // Symbolic Link - mode_symlink=true; break; + mode_symlink=true; break; case 's': // Socket - mode_socket=true; break; + mode_socket=true; break; case 'd': // Door (Solaris) - mode_door=true; break; + mode_door=true; break; default: - ocb.error("%s: Unrecognized file type: %c", progname.c_str(),arg[i]); + ocb.error("%s: Unrecognized file type: %c", progname.c_str(),arg[i]); } } } @@ -790,6 +792,79 @@ #endif } + +#if 0 +// See http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html +tstring global::getcwd() +{ + std::string path; + typedef std::pair<dev_t, ino_t> file_id; + + bool success = false; + int start_fd = open(".", O_RDONLY); //Keep track of start directory, so can jump back to it later + if (start_fd == -1) { + fprintf(stderr,"global::getcwd(): Cannot open '.': %s\n",strerror(errno)); + exit(1); + } + struct stat sb; + if (fstat(start_fd, &sb)==0) { + file_id current_id(sb.st_dev, sb.st_ino); + if (!stat("/", &sb)){ //Get info for root directory, so we can determine when we hit it + std::vector<std::string> path_components; + file_id root_id(sb.st_dev, sb.st_ino); + + // while we are not at the root, keep going up... + while (current_id != root_id){ + bool pushed = false; + if (!chdir("..")){ //Keep recursing towards root each iteration + DIR *dir = opendir("."); + if (dir) { + dirent *entry; + while ((entry = readdir(dir))){ + //We loop through each entry trying to find where we came from + if (strcmp(entry->d_name,".")==0) continue; // ignore . + if (strcmp(entry->d_name,"..")==0) continue; + if (lstat(entry->d_name, &sb)==0){ + file_id child_id(sb.st_dev, sb.st_ino); + if (child_id == current_id){ + //We found where we came from, add its name to the list + path_components.push_back(entry->d_name); + pushed = true; + break; + } + } + } + closedir(dir); + if (pushed && !stat(".", &sb)){ + //If we have a reason to continue, we update the current dir id + current_id = file_id(sb.st_dev, sb.st_ino); + } + } //Else, Uh oh, can't read information at this level + } + if (!pushed) { break; } //If we didn't obtain any info this pass, no reason to continue + } + + if (current_id == root_id){ + //Unless they're equal, we failed above + //Built the path, will always end with a slash + path = "/"; + for (std::vector<std::string>::reverse_iterator i = path_components.rbegin(); + i != path_components.rend(); + ++i){ + path += *i+"/"; + } + success = true; + } + fchdir(start_fd); + } + } + close(start_fd); + return path; +} +#endif + + + /* Return the canonicalized absolute pathname in UTF-8 on Windows and POSIX systems */ tstring global::get_realpath(const tstring &fn) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/main.h new/md5deep-4.1/src/main.h --- old/md5deep-4.0.1/src/main.h 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/src/main.h 2012-02-08 16:13:55.000000000 +0100 @@ -12,7 +12,7 @@ * * It then creates all the C++ classes and structures used. * - * $Id: main.h,v 1.14 2007/12/28 01:49:36 jessekornblum Exp $ + * $Id: main.h 612 2012-02-08 15:01:56Z jessekornblum $ */ @@ -746,30 +746,31 @@ stat_unknown=254 } file_types; - state():mode_recursive(false), // do we recurse? - mode_warn_only(false), // for loading hash files - - // these determine which files get hashed - mode_expert(false), - mode_regular(false), - mode_directory(false), - mode_door(false), - mode_block(false), - mode_character(false), - mode_pipe(false), - mode_socket(false), - mode_symlink(false), - - // command line argument - argc(0),argv(0), - - // these have something to do with hash files that are loaded - h_field(0), - h_plain(0),h_bsd(0), - h_md5deep_size(0), - h_hashkeeper(0),h_ilook(0),h_ilook3(0),h_ilook4(0), h_nsrl20(0), h_encase(0), - usage_count(0) // allows -hh to print extra help - {}; + state():mode_recursive(false), // do we recurse? + mode_warn_only(false), // for loading hash files + + // these determine which files get hashed + mode_expert(false), + mode_regular(false), + mode_directory(false), + mode_door(false), + mode_block(false), + mode_character(false), + mode_pipe(false), + mode_socket(false), + mode_symlink(false), + mode_winpe(false), + + // command line argument + argc(0),argv(0), + + // these have something to do with hash files that are loaded + h_field(0), + h_plain(0),h_bsd(0), + h_md5deep_size(0), + h_hashkeeper(0),h_ilook(0),h_ilook3(0),h_ilook4(0), h_nsrl20(0), h_encase(0), + usage_count(0) // allows -hh to print extra help + {}; bool mode_recursive; bool mode_warn_only; @@ -784,6 +785,7 @@ bool mode_pipe; bool mode_socket; bool mode_symlink; + bool mode_winpe; /* Command line arguments */ @@ -853,6 +855,7 @@ int identify_hash_file_type(FILE *f,uint32_t *expected_hashes); // identify the hash file type bool should_hash_symlink(const tstring &fn,file_types *link_type); + bool should_hash_winpe(const tstring &fn); bool should_hash_expert(const tstring &fn, file_types type); bool should_hash(const tstring &fn); @@ -907,7 +910,6 @@ // helper.cpp // ------------------------------------------------------------------ -std::string itos(uint64_t i); void chop_line(char *s); off_t find_file_size(FILE *f,class display *ocb); // Return the size, in bytes of an open file stream. On error, return -1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/threadpool.cpp new/md5deep-4.1/src/threadpool.cpp --- old/md5deep-4.0.1/src/threadpool.cpp 2012-01-22 18:10:30.000000000 +0100 +++ new/md5deep-4.1/src/threadpool.cpp 2012-02-10 14:31:58.000000000 +0100 @@ -2,6 +2,8 @@ *** THREADING SUPPORT ****************************************************************/ +// $Id: threadpool.cpp 618 2012-02-10 12:12:38Z jessekornblum $ + #include "main.h" #ifdef HAVE_PTHREAD diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/winpe.cpp new/md5deep-4.1/src/winpe.cpp --- old/md5deep-4.0.1/src/winpe.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/md5deep-4.1/src/winpe.cpp 2012-02-10 14:31:58.000000000 +0100 @@ -0,0 +1,84 @@ +// MD5DEEP - winpe.cpp +// +// By Jesse Kornblum +// +// This is a work of the US Government. In accordance with 17 USC 105, +// copyright protection is not available for any work of the US Government. +// +// 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. +// +// $Id: winpe.cpp 618 2012-02-10 12:12:38Z jessekornblum $ +// + +#include "main.h" + + +bool has_executable_extension(const tstring &fn) +{ + size_t last_period = fn.find_last_of(_TEXT(".")); + + // If there is no extension, we're done. + if (std::string::npos == last_period) + return false; + + // Get the file extension and convert it to lowercase + tstring extension = fn.substr(last_period); + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + +#define CHECK_EXEC(A) if (A == extension) return true; + CHECK_EXEC(_TEXT(".exe")); + CHECK_EXEC(_TEXT(".dll")); + CHECK_EXEC(_TEXT(".com")); + CHECK_EXEC(_TEXT(".sys")); + CHECK_EXEC(_TEXT(".cpl")); + CHECK_EXEC(_TEXT(".hxs")); + CHECK_EXEC(_TEXT(".hxi")); + CHECK_EXEC(_TEXT(".olb")); + CHECK_EXEC(_TEXT(".rll")); + CHECK_EXEC(_TEXT(".mui")); + CHECK_EXEC(_TEXT(".tlb")); + + return false; +} + + +bool is_pe_file(const unsigned char * buffer, size_t size) +{ + // We need at least 0x40 bytes to hold an IMAGE_DOS_HEADER + // and the signature of a PE header. + if (NULL == buffer or size < 0x40) + return false; + + // Is the MZ header's signature 'MZ'? + uint16_t mz_header = buffer[0] | (buffer[1] << 8); + if (0x5a4d != mz_header) + return false; + + // Find the PE header. It's the e_lfanew field in the IMAGE_DOS_HEADER + // structure, which is at offset 0x3c. + // This line is equivalent to: + // uint16_t pe_offset = *(uint16_t *)(buffer + 0x3c); + // but is not affected by the endianness of the system. + // This value should be a uint16_t according to the IMAGE_DOS_HEADER + // but that merits us a compiler warning. size_t *should* be wider than + // 16 bits on your platform. Or else you need a better platform. Just sayin'. + size_t pe_offset = buffer[0x3c] | (buffer[0x3d] << 8); + + // Do we have enough data to do this check? + if (pe_offset + 4 > size) + return false; + + // Is the PE header's signature 'PE '? The PE signature should begin + // at the location specified by the PE offset in the DOS header + // This line is equivalent to: + // uint32_t signature = *(uint32_t *)(buffer + pe_offset); + // but is not affected by the endianness of the system. + const unsigned char * tmp = buffer+pe_offset; + uint32_t signature=tmp[0] | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24); + if (signature != 0x4550) + return false; + + return true; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/winpe.h new/md5deep-4.1/src/winpe.h --- old/md5deep-4.0.1/src/winpe.h 1970-01-01 01:00:00.000000000 +0100 +++ new/md5deep-4.1/src/winpe.h 2012-02-08 16:13:55.000000000 +0100 @@ -0,0 +1,26 @@ +// MD5DEEP - winpe.h +// +// By Jesse Kornblum +// +// This is a work of the US Government. In accordance with 17 USC 105, +// copyright protection is not available for any work of the US Government. +// +// 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. +// +// $Id: winpe.h 612 2012-02-08 15:01:56Z jessekornblum $ +// + +#include "main.h" + +#define PETEST_BUFFER_SIZE 8192 + +/// Returns true if 'fn' ends with an extension which is normally executable on Microsoft Windows +bool has_executable_extension(const tstring &fn); + +/// Returns true if the data in buffer is the start of a PE executable +/// +/// @param buffer The buffer to test +/// @param size Size of the buffer in bytes +bool is_pe_file(const unsigned char * buffer, size_t size); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/md5deep-4.0.1/src/xml.cpp new/md5deep-4.1/src/xml.cpp --- old/md5deep-4.0.1/src/xml.cpp 2012-01-06 13:29:31.000000000 +0100 +++ new/md5deep-4.1/src/xml.cpp 2012-02-10 14:31:58.000000000 +0100 @@ -16,6 +16,7 @@ * not subject to copyright. */ +// $Id: xml.cpp 618 2012-02-10 12:12:38Z jessekornblum $ #include "common.h" // normally you remove this Files old/md5deep-4.0.1/tests/testfiles/testfiles.zip and new/md5deep-4.1/tests/testfiles/testfiles.zip differ -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
