[Forensics-changes] [ssdeep] 01/01: Imported Upstream version 2.11

Helmut Grohne helmutg at moszumanska.debian.org
Tue Sep 16 07:41:11 UTC 2014


This is an automated email from the git hooks/post-receive script.

helmutg pushed a commit to branch upstream
in repository ssdeep.

commit fa39296ea3c10165644e704499cf479163994c32
Author: Helmut Grohne <helmut at subdivi.de>
Date:   Sat Sep 13 16:20:41 2014 +0200

    Imported Upstream version 2.11
---
 AUTHORS       |   2 +-
 ChangeLog     |  72 ++++-
 Makefile.am   |   4 +-
 Makefile.in   | 303 +++++++++++--------
 NEWS          |  36 ++-
 README        |   4 +-
 aclocal.m4    | 378 +++++++++++++++---------
 compile       | 347 ++++++++++++++++++++++
 configure     | 109 +++++--
 configure.ac  |  11 +-
 cycles.cpp    |  22 +-
 dig.cpp       | 509 +++++++++++++++++---------------
 engine.cpp    |  62 ++--
 filedata.cpp  |  28 +-
 filedata.h    |  12 +-
 fuzzy.c       | 912 +++++++++++++++++++++++++++++++++-------------------------
 fuzzy.h       | 263 +++++++++++------
 helpers.cpp   |  10 +-
 main.cpp      |  68 ++---
 main.h        |   8 +-
 match.cpp     |  21 +-
 missing       | 460 ++++++++++-------------------
 sample.c      |   4 +-
 ssdeep.1      |  36 +--
 ssdeep.h      |  24 +-
 tchar-local.h |   5 +-
 26 files changed, 2243 insertions(+), 1467 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 6d0f01d..48c23df 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1 @@
-ssdeep was written by Jesse Kornblum
+ssdeep was written by Jesse Kornblum and Helmut Grohne.
diff --git a/ChangeLog b/ChangeLog
index caff8fa..420bbde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,71 @@
-2012-07-23: Jesse Korblum <research at jessekornblum.com>:
+2014-09-09: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.c: Fixing edge case bug for signature creation.
+	* fuzzy.h: Prevent copying with constructor.
+
+2014-07-23: Jesse Kornblum <research at jessekornblum.com>:
+
+	* sample.c, README: Fixed -l flag in compile instructions.
+
+2014-05-14: Jesse Kornblum <research at jessekornblum.com>:
+
+	* filedata.h: Added destructor method, constructor copy by reference.
+	* Minor cleanup and code formatting.
+
+2014-05-08: Jesse Kornblum <research at jessekornblum.com>:
+
+	* Version bump to 2.10.1, updates for compiling on Fedora Core 20
+
+2013-11-25: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.c: Revised check for equal signature to be case sensitive
+
+2013-11-15: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.c: Declare signatures which are equal as matching 100%
+
+2013-09-21: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.c, fuzzy.h: Added fuzzy_clone function
+
+2013-07-24: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.h: Moving include guard to the top of the file.
+
+2013-07-16: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.c: Fix heap corruption bug #15.
+	* dig.c: Removed extra call to GetFileAttributes
+
+2013-07-09: Jesse Kornblum <research at jessekornblum.com>:
+
+	* dig.cpp, engine.cpp, helpers.cpp: Created separate directory traversal code
+	for Win32 systems.
+
+2013-06-01: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.c: Experimental thread-safe patch from Helmut Grohne.
+	* fuzzy.h: Experimental thread-safe patch from Helmut Grohne.
+
+2013-05-25: Jesse Kornblum <research at jessekornblum.com>:
+
+	* fuzzy.c: Fixed bug on string scoring.
+
+2013-03-12: Jesse Kornblum <research at jessekornblum.com>:
+
+	* Changelog: Spelled my own name correctly.
+	* fuzzy.c: Fixed memory leak, bug 3607641.
+
+2012-07-23: Jesse Kornblum <research at jessekornblum.com>:
 
 	* main.cpp, match.cpp: Renamed the match_pretty function for clarity.
-	
-2012-07-17: Jesse Korblum <research at jessekornblum.com>:
+
+2012-07-17: Jesse Kornblum <research at jessekornblum.com>:
 
 	* match.cpp: Fixing bugs in matching, clustering modes
 	* main.cpp: Clarifying comments. Added sanity check for -c, -g
 
-2012-07-16: Jesse Korblum <research at jessekornblum.com>:
+2012-07-16: Jesse Kornblum <research at jessekornblum.com>:
 
 	* filedata.cpp: Added includes for *nix compilation
 
@@ -29,7 +87,7 @@
 	* main.cpp: Added flags for clustering mode
 	* ssdeep.h: Added flags for clustering mode
 	* match.cpp: Setting up for clustering mode
-	
+
 2012-05-25 Jesse Kornblum <research at jessekornblum.com>:
 
 	* main.cpp: Updated command line argument processing
@@ -40,7 +98,7 @@
 	* match.cpp: Convert to C++
 
 2012-04-24 Jesse Kornblum <research at jessekornblum.com>:
-	
+
 	* ssdeep.1: Updating support for stdin, clarifying modes
         * Makefile.am: LF to CR/LF change now done by zip program
 	* ssdeep.h: Adding Doxygen comments
@@ -54,7 +112,7 @@
 2012-04-15: Jesse Kornblum <research at jessekornblum.com>:
 
 	* main.c: Fixed error handling in getopt processing
-	
+
 2012-02-16 Jesse Kornblum <research at jessekornblum.com>:
 
 	* main.c: Bump copyright to 2012 in usage message. Add flag for clustering
diff --git a/Makefile.am b/Makefile.am
index 66dd2ff..ea90344 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ ACLOCAL_AMFLAGS = -I m4
 
 lib_LTLIBRARIES=libfuzzy.la
 libfuzzy_la_SOURCES=fuzzy.c edit_dist.c find-file-size.c
-libfuzzy_la_LDFLAGS=-no-undefined -version-info 2:0:0
+libfuzzy_la_LDFLAGS=-static -no-undefined -version-info 2:0:0
 
 include_HEADERS=fuzzy.h
 
@@ -58,7 +58,7 @@ win-package: win-docs
 	rm -rf $(distdir) $(WINDOWSDOCS)
 
 world: distclean
-	./configure --host=i386-mingw32
+	./configure --host=i686-w64-mingw32
 	make win-package
 	make dist
 
diff --git a/Makefile.in b/Makefile.in
index f097098..c63371f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
 # @configure_input@
 
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
 
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -17,23 +17,51 @@
 
 
 VPATH = @srcdir@
-am__make_dryrun = \
-  { \
-    am__dry=no; \
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
     case $$MAKEFLAGS in \
       *\\[\ \	]*) \
-        echo 'am--echo: ; @echo "AM"  OK' | $(MAKE) -f - 2>/dev/null \
-          | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-      *) \
-        for am__flg in $$MAKEFLAGS; do \
-          case $$am__flg in \
-            *=*|--*) ;; \
-            *n*) am__dry=yes; break;; \
-          esac; \
-        done;; \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
     esac; \
-    test $$am__dry = yes; \
-  }
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
 pkgdatadir = $(datadir)/@PACKAGE@
 pkgincludedir = $(includedir)/@PACKAGE@
 pkglibdir = $(libdir)/@PACKAGE@
@@ -54,11 +82,11 @@ build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = ssdeep$(EXEEXT)
 subdir = .
-DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
-	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
-	$(srcdir)/config.h.in $(top_srcdir)/configure AUTHORS COPYING \
-	ChangeLog INSTALL NEWS TODO config.guess config.sub depcomp \
-	install-sh ltmain.sh missing
+DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
+	$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/configure $(am__configure_deps) \
+	$(srcdir)/config.h.in depcomp $(include_HEADERS) COPYING TODO \
+	compile config.guess config.sub install-sh missing ltmain.sh
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -102,7 +130,11 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
 libfuzzy_la_LIBADD =
 am_libfuzzy_la_OBJECTS = fuzzy.lo edit_dist.lo find-file-size.lo
 libfuzzy_la_OBJECTS = $(am_libfuzzy_la_OBJECTS)
-libfuzzy_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+AM_V_lt = $(am__v_lt_ at AM_V@)
+am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libfuzzy_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(libfuzzy_la_LDFLAGS) $(LDFLAGS) -o $@
 PROGRAMS = $(bin_PROGRAMS)
@@ -111,31 +143,61 @@ am_ssdeep_OBJECTS = main.$(OBJEXT) match.$(OBJEXT) engine.$(OBJEXT) \
 	helpers.$(OBJEXT) ui.$(OBJEXT)
 ssdeep_OBJECTS = $(am_ssdeep_OBJECTS)
 ssdeep_DEPENDENCIES = libfuzzy.la
-ssdeep_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-	--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
-	$(ssdeep_LDFLAGS) $(LDFLAGS) -o $@
+ssdeep_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(ssdeep_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
 DEFAULT_INCLUDES = -I. at am__isrc@
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
 am__mv = mv -f
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_ at AM_V@)
+am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
 CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
-	$(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
 	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
-LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-	--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo "  CXX     " $@;
+am__v_CXX_1 = 
 CXXLD = $(CXX)
-CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-	--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
-	$(LDFLAGS) -o $@
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo "  CXXLD   " $@;
+am__v_CXXLD_1 = 
 SOURCES = $(libfuzzy_la_SOURCES) $(ssdeep_SOURCES)
 DIST_SOURCES = $(libfuzzy_la_SOURCES) $(ssdeep_SOURCES)
 am__can_run_installinfo = \
@@ -147,6 +209,24 @@ man1dir = $(mandir)/man1
 NROFF = nroff
 MANS = $(man_MANS)
 HEADERS = $(include_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+	$(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
@@ -170,6 +250,7 @@ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
 distcleancheck_listfiles = find . -type f -print
 ACLOCAL = @ACLOCAL@
 AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
 AR = @AR@
 AS = @AS@
 AUTOCONF = @AUTOCONF@
@@ -292,7 +373,7 @@ ssdeep_LDFLAGS = -static
 ACLOCAL_AMFLAGS = -I m4
 lib_LTLIBRARIES = libfuzzy.la
 libfuzzy_la_SOURCES = fuzzy.c edit_dist.c find-file-size.c
-libfuzzy_la_LDFLAGS = -no-undefined -version-info 2:0:0
+libfuzzy_la_LDFLAGS = -static -no-undefined -version-info 2:0:0
 include_HEADERS = fuzzy.h
 man_MANS = ssdeep.1
 ssdeep_SOURCES = main.cpp match.cpp engine.cpp filedata.cpp   	\
@@ -356,6 +437,7 @@ $(srcdir)/config.h.in:  $(am__configure_deps)
 
 distclean-hdr:
 	-rm -f config.h stamp-h1
+
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
 	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
@@ -390,8 +472,9 @@ clean-libLTLIBRARIES:
 	  echo rm -f $${locs}; \
 	  rm -f $${locs}; \
 	}
+
 libfuzzy.la: $(libfuzzy_la_OBJECTS) $(libfuzzy_la_DEPENDENCIES) $(EXTRA_libfuzzy_la_DEPENDENCIES) 
-	$(libfuzzy_la_LINK) -rpath $(libdir) $(libfuzzy_la_OBJECTS) $(libfuzzy_la_LIBADD) $(LIBS)
+	$(AM_V_CCLD)$(libfuzzy_la_LINK) -rpath $(libdir) $(libfuzzy_la_OBJECTS) $(libfuzzy_la_LIBADD) $(LIBS)
 install-binPROGRAMS: $(bin_PROGRAMS)
 	@$(NORMAL_INSTALL)
 	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
@@ -401,10 +484,12 @@ install-binPROGRAMS: $(bin_PROGRAMS)
 	fi; \
 	for p in $$list; do echo "$$p $$p"; done | \
 	sed 's/$(EXEEXT)$$//' | \
-	while read p p1; do if test -f $$p || test -f $$p1; \
-	  then echo "$$p"; echo "$$p"; else :; fi; \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
 	done | \
-	sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
 	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
 	sed 'N;N;N;s,\n, ,g' | \
 	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -425,7 +510,8 @@ uninstall-binPROGRAMS:
 	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
 	files=`for p in $$list; do echo "$$p"; done | \
 	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-	      -e 's/$$/$(EXEEXT)/' `; \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
 	test -n "$$list" || exit 0; \
 	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
 	cd "$(DESTDIR)$(bindir)" && rm -f $$files
@@ -438,9 +524,10 @@ clean-binPROGRAMS:
 	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
 	echo " rm -f" $$list; \
 	rm -f $$list
+
 ssdeep$(EXEEXT): $(ssdeep_OBJECTS) $(ssdeep_DEPENDENCIES) $(EXTRA_ssdeep_DEPENDENCIES) 
 	@rm -f ssdeep$(EXEEXT)
-	$(ssdeep_LINK) $(ssdeep_OBJECTS) $(ssdeep_LDADD) $(LIBS)
+	$(AM_V_CXXLD)$(ssdeep_LINK) $(ssdeep_OBJECTS) $(ssdeep_LDADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -461,46 +548,46 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ui.Po at am__quote@
 
 .c.o:
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c $<
 
 .c.obj:
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
- at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
 
 .c.lo:
- at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
 .cpp.o:
- at am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
 
 .cpp.obj:
- at am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
- at am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
 .cpp.lo:
- at am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
 
 mostlyclean-libtool:
 	-rm -f *.lo
@@ -575,26 +662,15 @@ uninstall-includeHEADERS:
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
 	dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
 
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-	unique=`for i in $$list; do \
-	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-	  done | \
-	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-	      END { if (nonempty) { for (i in files) print i; }; }'`; \
-	mkid -fID $$unique
-tags: TAGS
-
-TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
-		$(TAGS_FILES) $(LISP)
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
 	set x; \
 	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
-	unique=`for i in $$list; do \
-	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-	  done | \
-	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	$(am__define_uniq_tagged_files); \
 	shift; \
 	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
 	  test -n "$$unique" || unique=$$empty_fix; \
@@ -606,15 +682,11 @@ TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
 	      $$unique; \
 	  fi; \
 	fi
-ctags: CTAGS
-CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
-		$(TAGS_FILES) $(LISP)
-	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
-	unique=`for i in $$list; do \
-	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-	  done | \
-	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
 	test -z "$(CTAGS_ARGS)$$unique" \
 	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
 	     $$unique
@@ -623,18 +695,16 @@ GTAGS:
 	here=`$(am__cd) $(top_builddir) && pwd` \
 	  && $(am__cd) $(top_srcdir) \
 	  && gtags -i $(GTAGS_ARGS) "$$here"
-
 cscope: cscope.files
 	test ! -s cscope.files \
 	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
-
 clean-cscope:
 	-rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
 
-cscope.files: clean-cscope  cscopelist
-
-cscopelist:  $(HEADERS) $(SOURCES) $(LISP)
-	list='$(SOURCES) $(HEADERS) $(LISP)'; \
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
 	case "$(srcdir)" in \
 	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
 	  *) sdir=$(subdir)/$(srcdir) ;; \
@@ -652,19 +722,6 @@ distclean-tags:
 	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
 
 distdir: $(DISTFILES)
-	@list='$(MANS)'; if test -n "$$list"; then \
-	  list=`for p in $$list; do \
-	    if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
-	    if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
-	  if test -n "$$list" && \
-	    grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
-	    echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
-	    grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/         /' >&2; \
-	    echo "       to fix them, install help2man, remove and regenerate the man pages;" >&2; \
-	    echo "       typically 'make maintainer-clean' will remove them" >&2; \
-	    exit 1; \
-	  else :; fi; \
-	else :; fi
 	$(am__remove_distdir)
 	test -d "$(distdir)" || mkdir "$(distdir)"
 	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -756,9 +813,9 @@ distcheck: dist
 	*.zip*) \
 	  unzip $(distdir).zip ;;\
 	esac
-	chmod -R a-w $(distdir); chmod u+w $(distdir)
-	mkdir $(distdir)/_build
-	mkdir $(distdir)/_inst
+	chmod -R a-w $(distdir)
+	chmod u+w $(distdir)
+	mkdir $(distdir)/_build $(distdir)/_inst
 	chmod a-w $(distdir)
 	test -d $(distdir)/_build || exit 0; \
 	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
@@ -940,11 +997,11 @@ uninstall-man: uninstall-man1
 
 .MAKE: all install-am install-strip
 
-.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
 	clean-binPROGRAMS clean-cscope clean-generic \
-	clean-libLTLIBRARIES clean-libtool cscope cscopelist ctags \
-	dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \
-	dist-tarZ dist-xz dist-zip distcheck distclean \
+	clean-libLTLIBRARIES clean-libtool cscope cscopelist-am ctags \
+	ctags-am dist dist-all dist-bzip2 dist-gzip dist-lzip \
+	dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \
 	distclean-compile distclean-generic distclean-hdr \
 	distclean-libtool distclean-tags distcleancheck distdir \
 	distuninstallcheck dvi dvi-am html html-am info info-am \
@@ -957,7 +1014,7 @@ uninstall-man: uninstall-man1
 	installcheck installcheck-am installdirs maintainer-clean \
 	maintainer-clean-generic mostlyclean mostlyclean-compile \
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-	tags uninstall uninstall-am uninstall-binPROGRAMS \
+	tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
 	uninstall-includeHEADERS uninstall-libLTLIBRARIES \
 	uninstall-man uninstall-man1
 
@@ -996,7 +1053,7 @@ win-package: win-docs
 	rm -rf $(distdir) $(WINDOWSDOCS)
 
 world: distclean
-	./configure --host=i386-mingw32
+	./configure --host=i686-w64-mingw32
 	make win-package
 	make dist
 
diff --git a/NEWS b/NEWS
index eebb31c..ce4d88a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,29 @@
+** Version 2.11 - 11 Sep 2014
+
+* New Features
+
+  - Added fuzzy_clone function to the API.
+  - Moved to modern Win32 compiler.
+
+* Bug Fixes
+
+  - Fixed edge case on signature generaion. Behavior now matches v2.9 again.
+
+
+** Version 2.10 - 17 Jul 2013
+
+* New Features
+
+  - Fuzzy Hashing engine re-written to be thread safe.
+
+* Bug Fixes
+
+  - Able to handle long file paths on Win32.
+  - Fixed bug on comparing signatures with the same block size.
+  - Fixed crash on comparing short signatures.
+  - Fixed memory leak
+
+
 ** Version 2.9 - 23 Jul 2012
 
 * New Features
@@ -18,7 +44,7 @@
   - Converted to C++
 
 * Bug Fixes
-  
+
   - Fixed filename display on Win32.
   - Fixed support for large files on some platforms.
   - Fixed errors in handling command line argument processing.
@@ -35,7 +61,7 @@
     any file large enough to produce a meaningful result.
 
 * Bug Fixes
-  
+
   - Standard errors are now sent to stderr, not stdout.
 
 
@@ -89,7 +115,7 @@
 * New Features
 
   - Added capability to compare two or more files containing signatures
-    against one another. 
+    against one another.
 
 * Bug Fixes
 
@@ -106,7 +132,7 @@
 
 * Bug Fixes
 
-  - Fixed -p mode to display output 
+  - Fixed -p mode to display output
 
 
 
@@ -139,7 +165,7 @@
   - Added -p mode to improve -d mode. Prints bi-directional matches together
     and omits self matches.
   - Added LARGEFILE_SOURCE define to Linux version to allow processing
-    of large files. (You never know...) 
+    of large files. (You never know...)
 
 * Bug Fixes
 
diff --git a/README b/README
index b3f1ed0..990ea9d 100644
--- a/README
+++ b/README
@@ -73,7 +73,7 @@ sigantures did not match.
 
 To compile the program using gcc:
 
-   $ gcc -Wall -I/usr/local/include -L/usr/local/lib sample.c -Lfuzzy
+   $ gcc -Wall -I/usr/local/include -L/usr/local/lib sample.c -lfuzzy
 
 Using mingw:
 
@@ -107,4 +107,4 @@ A sample program that uses the API is in sample.c.
 - Jesse D. Kornblum, "Identifying almost identical files using context 
 triggered piecewise hashing", Digital Investigaton, 3(S):91-97, 
 September 2006, http://dx.doi.org/10.1016/j.diin.2006.06.015,
-The Proceedings of the 6th Annual Digital Forensic Research Workshop
\ No newline at end of file
+The Proceedings of the 6th Annual Digital Forensic Research Workshop
diff --git a/aclocal.m4 b/aclocal.m4
index ee7e65e..1a69b6d 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.12.2 -*- Autoconf -*-
+# generated automatically by aclocal 1.13.4 -*- Autoconf -*-
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -11,6 +11,7 @@
 # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 # PARTICULAR PURPOSE.
 
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
@@ -1325,7 +1326,7 @@ ia64-*-hpux*)
   rm -rf conftest*
   ;;
 
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
@@ -1339,7 +1340,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_i386"
 	    ;;
-	  ppc64-*linux*|powerpc64-*linux*)
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
 	    LD="${LD-ld} -m elf32ppclinux"
 	    ;;
 	  s390x-*linux*)
@@ -1358,7 +1362,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_x86_64"
 	    ;;
-	  ppc*-*linux*|powerpc*-*linux*)
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
 	    LD="${LD-ld} -m elf64ppc"
 	    ;;
 	  s390*-*linux*|s390*-*tpf*)
@@ -2682,10 +2689,14 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu)
   # before this can be enabled.
   hardcode_into_libs=yes
 
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -8606,24 +8617,22 @@ m4_ifndef([_LT_PROG_F77],		[AC_DEFUN([_LT_PROG_F77])])
 m4_ifndef([_LT_PROG_FC],		[AC_DEFUN([_LT_PROG_FC])])
 m4_ifndef([_LT_PROG_CXX],		[AC_DEFUN([_LT_PROG_CXX])])
 
-# Copyright (C) 2002-2012 Free Software Foundation, Inc.
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 8
-
 # AM_AUTOMAKE_VERSION(VERSION)
 # ----------------------------
 # Automake X.Y traces this macro to ensure aclocal.m4 has been
 # generated from the m4 files accompanying Automake X.Y.
 # (This private macro should not be called outside this file.)
 AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.12'
+[am__api_version='1.13'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.12.2], [],
+m4_if([$1], [1.13.4], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -8639,21 +8648,19 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.12.2])dnl
+[AM_AUTOMAKE_VERSION([1.13.4])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
 
 # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 2
-
 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
 # $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
 # '$srcdir', '$srcdir/..', or '$srcdir/../..'.
@@ -8701,14 +8708,12 @@ am_aux_dir=`cd $ac_aux_dir && pwd`
 
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 10
-
 # AM_CONDITIONAL(NAME, SHELL-CONDITION)
 # -------------------------------------
 # Define a conditional.
@@ -8734,13 +8739,12 @@ AC_CONFIG_COMMANDS_PRE(
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 17
 
 # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
 # written in clear, in which case automake, when reading aclocal.m4,
@@ -8926,19 +8930,18 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
 
 # Generate code to set up dependency tracking.              -*- Autoconf -*-
 
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 6
 
 # _AM_OUTPUT_DEPENDENCY_COMMANDS
 # ------------------------------
 AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
 [{
-  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # Older Autoconf quotes --file arguments for eval, but not when files
   # are listed without --file.  Let's play safe and only enable the eval
   # if we detect the quoting.
   case $CONFIG_FILES in
@@ -8967,7 +8970,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
     DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
     test -z "$DEPDIR" && continue
     am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "am__include" && continue
+    test -z "$am__include" && continue
     am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
     # Find all dependency output files, they are included files with
     # $(DEPDIR) in their names.  We invoke sed twice because it is the
@@ -9001,27 +9004,14 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
      [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
 ])
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 8
-
-# AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
-AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
-
 # Do all the work for Automake.                             -*- Autoconf -*-
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 19
-
 # This macro actually does too much.  Some checks are only needed if
 # your package does certain things.  But this isn't really a big deal.
 
@@ -9037,7 +9027,7 @@ AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
 # arguments mandatory, and then we can depend on a new Autoconf
 # release and drop the old call support.
 AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_PREREQ([2.62])dnl
+[AC_PREREQ([2.65])dnl
 dnl Autoconf wants to disallow AM_ names.  We explicitly allow
 dnl the ones we care about.
 m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@@ -9067,8 +9057,7 @@ AC_SUBST([CYGPATH_W])
 dnl Distinguish between old-style and new-style calls.
 m4_ifval([$2],
 [AC_DIAGNOSE([obsolete],
-[$0: two- and three-arguments forms are deprecated.  For more info, see:
-http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation])
+             [$0: two- and three-arguments forms are deprecated.])
 m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
  AC_SUBST([PACKAGE], [$1])dnl
  AC_SUBST([VERSION], [$2])],
@@ -9122,18 +9111,15 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJC],
 		  [_AM_DEPENDENCIES([OBJC])],
 		  [m4_define([AC_PROG_OBJC],
 			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
-dnl Support for Objective C++ was only introduced in Autoconf 2.65,
-dnl but we still cater to Autoconf 2.62.
-m4_ifdef([AC_PROG_OBJCXX],
-[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
 		  [_AM_DEPENDENCIES([OBJCXX])],
 		  [m4_define([AC_PROG_OBJCXX],
-			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl
+			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
 ])
-_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
-dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the
-dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
-dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
 AC_CONFIG_COMMANDS_PRE(dnl
 [m4_provide_if([_AM_COMPILER_EXEEXT],
   [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
@@ -9167,14 +9153,12 @@ for _am_header in $config_headers :; do
 done
 echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 8
-
 # AM_PROG_INSTALL_SH
 # ------------------
 # Define $install_sh.
@@ -9190,14 +9174,12 @@ if test x"${install_sh}" != xset; then
 fi
 AC_SUBST([install_sh])])
 
-# Copyright (C) 2003-2012 Free Software Foundation, Inc.
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 2
-
 # Check whether the underlying file-system supports filenames
 # with a leading dot.  For instance MS-DOS doesn't.
 AC_DEFUN([AM_SET_LEADING_DOT],
@@ -9213,14 +9195,12 @@ AC_SUBST([am__leading_dot])])
 
 # Check to see how 'make' treats includes.	            -*- Autoconf -*-
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 5
-
 # AM_MAKE_INCLUDE()
 # -----------------
 # Check to see how make treats includes.
@@ -9265,14 +9245,12 @@ rm -f confinc confmf
 
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 7
-
 # AM_MISSING_PROG(NAME, PROGRAM)
 # ------------------------------
 AC_DEFUN([AM_MISSING_PROG],
@@ -9280,11 +9258,10 @@ AC_DEFUN([AM_MISSING_PROG],
 $1=${$1-"${am_missing_run}$2"}
 AC_SUBST($1)])
 
-
 # AM_MISSING_HAS_RUN
 # ------------------
-# Define MISSING if not defined so far and test if it supports --run.
-# If it does, set am_missing_run to use it, otherwise, to nothing.
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
 AC_DEFUN([AM_MISSING_HAS_RUN],
 [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
 AC_REQUIRE_AUX_FILE([missing])dnl
@@ -9297,24 +9274,51 @@ if test x"${MISSING+set}" != xset; then
   esac
 fi
 # Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
-  am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
 else
   am_missing_run=
   AC_MSG_WARN(['missing' script is too old or missing])
 fi
 ])
 
+#  -*- Autoconf -*-
+# Obsolete and "removed" macros, that must however still report explicit
+# error messages when used, to smooth transition.
+#
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([AM_CONFIG_HEADER],
+[AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl
+AC_CONFIG_HEADERS($@)])
+
+AC_DEFUN([AM_PROG_CC_STDC],
+[AC_PROG_CC
+am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc
+AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should simply use the 'AC][_PROG_CC' macro instead.
+Also, your code should no longer depend upon 'am_cv_prog_cc_stdc',
+but upon 'ac_cv_prog_cc_stdc'.])])
+
+AC_DEFUN([AM_C_PROTOTYPES],
+         [AC_FATAL([automatic de-ANSI-fication support has been removed])])
+AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES])
+
 # Helper functions for option handling.                     -*- Autoconf -*-
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 6
-
 # _AM_MANGLE_OPTION(NAME)
 # -----------------------
 AC_DEFUN([_AM_MANGLE_OPTION],
@@ -9340,14 +9344,12 @@ AC_DEFUN([_AM_IF_OPTION],
 
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 9
-
 # AM_SANITY_CHECK
 # ---------------
 AC_DEFUN([AM_SANITY_CHECK],
@@ -9423,13 +9425,71 @@ AC_CONFIG_COMMANDS_PRE(
 rm -f conftest.file
 ])
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2009-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 2
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
 
 # AM_PROG_INSTALL_STRIP
 # ---------------------
@@ -9453,14 +9513,12 @@ fi
 INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
 AC_SUBST([INSTALL_STRIP_PROGRAM])])
 
-# Copyright (C) 2006-2012 Free Software Foundation, Inc.
+# Copyright (C) 2006-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 3
-
 # _AM_SUBST_NOTMAKE(VARIABLE)
 # ---------------------------
 # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
@@ -9474,14 +9532,12 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
 
 # Check how to create a tarball.                            -*- Autoconf -*-
 
-# Copyright (C) 2004-2012 Free Software Foundation, Inc.
+# Copyright (C) 2004-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 3
-
 # _AM_PROG_TAR(FORMAT)
 # --------------------
 # Check how to create a tarball in format FORMAT.
@@ -9495,76 +9551,114 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
 # Substitute a variable $(am__untar) that extract such
 # a tarball read from stdin.
 #     $(am__untar) < result.tar
+#
 AC_DEFUN([_AM_PROG_TAR],
 [# Always define AMTAR for backward compatibility.  Yes, it's still used
 # in the wild :-(  We should find a proper way to deprecate it ...
 AC_SUBST([AMTAR], ['$${TAR-tar}'])
-m4_if([$1], [v7],
-     [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
-     [m4_case([$1], [ustar],, [pax],,
-              [m4_fatal([Unknown tar format])])
-AC_MSG_CHECKING([how to create a $1 tar archive])
-# Loop over all known methods to create a tar archive until one works.
+
+# We'll loop over all known methods to create a tar archive until one works.
 _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
-_am_tools=${am_cv_prog_tar_$1-$_am_tools}
-# Do not fold the above two line into one, because Tru64 sh and
-# Solaris sh will not grok spaces in the rhs of '-'.
-for _am_tool in $_am_tools
-do
-  case $_am_tool in
-  gnutar)
-    for _am_tar in tar gnutar gtar;
-    do
-      AM_RUN_LOG([$_am_tar --version]) && break
-    done
-    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
-    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
-    am__untar="$_am_tar -xf -"
-    ;;
-  plaintar)
-    # Must skip GNU tar: if it does not support --format= it doesn't create
-    # ustar tarball either.
-    (tar --version) >/dev/null 2>&1 && continue
-    am__tar='tar chf - "$$tardir"'
-    am__tar_='tar chf - "$tardir"'
-    am__untar='tar xf -'
-    ;;
-  pax)
-    am__tar='pax -L -x $1 -w "$$tardir"'
-    am__tar_='pax -L -x $1 -w "$tardir"'
-    am__untar='pax -r'
-    ;;
-  cpio)
-    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
-    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
-    am__untar='cpio -i -H $1 -d'
-    ;;
-  none)
-    am__tar=false
-    am__tar_=false
-    am__untar=false
-    ;;
-  esac
 
-  # If the value was cached, stop now.  We just wanted to have am__tar
-  # and am__untar set.
-  test -n "${am_cv_prog_tar_$1}" && break
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
 
-  # tar/untar a dummy directory, and stop if the command works
-  rm -rf conftest.dir
-  mkdir conftest.dir
-  echo GrepMe > conftest.dir/file
-  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
   rm -rf conftest.dir
-  if test -s conftest.tar; then
-    AM_RUN_LOG([$am__untar <conftest.tar])
-    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
-  fi
-done
-rm -rf conftest.dir
 
-AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
-AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
 AC_SUBST([am__tar])
 AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
diff --git a/compile b/compile
new file mode 100755
index 0000000..531136b
--- /dev/null
+++ b/compile
@@ -0,0 +1,347 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2012-10-14.11; # UTC
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey at cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# 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.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" ""	$nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+  file=$1
+  case $file in
+    / | /[!/]*) # absolute file, and not a UNC file
+      if test -z "$file_conv"; then
+	# lazily determine how to convert abs files
+	case `uname -s` in
+	  MINGW*)
+	    file_conv=mingw
+	    ;;
+	  CYGWIN*)
+	    file_conv=cygwin
+	    ;;
+	  *)
+	    file_conv=wine
+	    ;;
+	esac
+      fi
+      case $file_conv/,$2, in
+	*,$file_conv,*)
+	  ;;
+	mingw/*)
+	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+	  ;;
+	cygwin/*)
+	  file=`cygpath -m "$file" || echo "$file"`
+	  ;;
+	wine/*)
+	  file=`winepath -w "$file" || echo "$file"`
+	  ;;
+      esac
+      ;;
+  esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+    if test -f "$dir/lib$lib.a"; then
+      found=yes
+      lib=$dir/lib$lib.a
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+  # Assume a capable shell
+  lib_path=
+  shared=:
+  linker_opts=
+  for arg
+  do
+    if test -n "$eat"; then
+      eat=
+    else
+      case $1 in
+	-o)
+	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
+	  eat=1
+	  case $2 in
+	    *.o | *.[oO][bB][jJ])
+	      func_file_conv "$2"
+	      set x "$@" -Fo"$file"
+	      shift
+	      ;;
+	    *)
+	      func_file_conv "$2"
+	      set x "$@" -Fe"$file"
+	      shift
+	      ;;
+	  esac
+	  ;;
+	-I)
+	  eat=1
+	  func_file_conv "$2" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-I*)
+	  func_file_conv "${1#-I}" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-l)
+	  eat=1
+	  func_cl_dashl "$2"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-l*)
+	  func_cl_dashl "${1#-l}"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-L)
+	  eat=1
+	  func_cl_dashL "$2"
+	  ;;
+	-L*)
+	  func_cl_dashL "${1#-L}"
+	  ;;
+	-static)
+	  shared=false
+	  ;;
+	-Wl,*)
+	  arg=${1#-Wl,}
+	  save_ifs="$IFS"; IFS=','
+	  for flag in $arg; do
+	    IFS="$save_ifs"
+	    linker_opts="$linker_opts $flag"
+	  done
+	  IFS="$save_ifs"
+	  ;;
+	-Xlinker)
+	  eat=1
+	  linker_opts="$linker_opts $2"
+	  ;;
+	-*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+	  func_file_conv "$1"
+	  set x "$@" -Tp"$file"
+	  shift
+	  ;;
+	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+	  func_file_conv "$1" mingw
+	  set x "$@" "$file"
+	  shift
+	  ;;
+	*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+      esac
+    fi
+    shift
+  done
+  if test -n "$linker_opts"; then
+    linker_opts="-link$linker_opts"
+  fi
+  exec "$@" $linker_opts
+  exit 1
+}
+
+eat=
+
+case $1 in
+  '')
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake at gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
+    func_cl_wrapper "$@"      # Doesn't return...
+    ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+	# configure might choose to run compile as 'compile cc -o foo foo.c'.
+	# So we strip '-o arg' only if arg is an object.
+	eat=1
+	case $2 in
+	  *.o | *.obj)
+	    ofile=$2
+	    ;;
+	  *)
+	    set x "$@" -o "$2"
+	    shift
+	    ;;
+	esac
+	;;
+      *.c)
+	cfile=$1
+	set x "$@" "$1"
+	shift
+	;;
+      *)
+	set x "$@" "$1"
+	shift
+	;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no '-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # '.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/configure b/configure
index 536dff8..218df6f 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for SSDEEP 2.9.
+# Generated by GNU Autoconf 2.69 for SSDEEP 2.11.
 #
 # Report bugs to <research at jessekornblum.com>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='SSDEEP'
 PACKAGE_TARNAME='ssdeep'
-PACKAGE_VERSION='2.9'
-PACKAGE_STRING='SSDEEP 2.9'
+PACKAGE_VERSION='2.11'
+PACKAGE_STRING='SSDEEP 2.11'
 PACKAGE_BUGREPORT='research at jessekornblum.com'
 PACKAGE_URL=''
 
@@ -690,6 +690,10 @@ build_os
 build_vendor
 build_cpu
 build
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
 am__untar
 am__tar
 AMTAR
@@ -754,6 +758,7 @@ SHELL'
 ac_subst_files=''
 ac_user_opts='
 enable_option_checking
+enable_silent_rules
 enable_dependency_tracking
 enable_shared
 enable_static
@@ -1317,7 +1322,7 @@ if test "$ac_init_help" = "long"; then
   # 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 SSDEEP 2.9 to adapt to many kinds of systems.
+\`configure' configures SSDEEP 2.11 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1387,7 +1392,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of SSDEEP 2.9:";;
+     short | recursive ) echo "Configuration of SSDEEP 2.11:";;
    esac
   cat <<\_ACEOF
 
@@ -1395,6 +1400,8 @@ Optional Features:
   --disable-option-checking  ignore unrecognized --enable/--with options
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
   --enable-dependency-tracking
                           do not reject slow dependency extractors
   --disable-dependency-tracking
@@ -1494,7 +1501,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-SSDEEP configure 2.9
+SSDEEP configure 2.11
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1984,7 +1991,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by SSDEEP $as_me 2.9, which was
+It was created by SSDEEP $as_me 2.11, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2332,7 +2339,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-am__api_version='1.12'
+am__api_version='1.13'
 
 ac_aux_dir=
 for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@@ -2545,8 +2552,8 @@ if test x"${MISSING+set}" != xset; then
   esac
 fi
 # Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
-  am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
 else
   am_missing_run=
   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
@@ -2786,6 +2793,45 @@ else
 fi
 rmdir .tst 2>/dev/null
 
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
 if test "`cd $srcdir && pwd`" != "`pwd`"; then
   # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
   # is not polluted with repeated "-I."
@@ -2808,7 +2854,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='ssdeep'
- VERSION='2.9'
+ VERSION='2.11'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2848,6 +2894,10 @@ mkdir_p='$(MKDIR_P)'
 # in the wild :-(  We should find a proper way to deprecate it ...
 AMTAR='$${TAR-tar}'
 
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
 am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
 
 
@@ -2855,6 +2905,7 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
 
 
 
+
 ac_config_files="$ac_config_files Makefile"
 
 ac_config_headers="$ac_config_headers config.h"
@@ -4600,7 +4651,6 @@ test -z "$OBJDUMP" && OBJDUMP=objdump
 
 
 
-#AC_PROG_LIBTOOL
 case `pwd` in
   *\ * | *\	*)
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
@@ -6934,7 +6984,7 @@ ia64-*-hpux*)
   rm -rf conftest*
   ;;
 
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
@@ -6952,7 +7002,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_i386"
 	    ;;
-	  ppc64-*linux*|powerpc64-*linux*)
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
 	    LD="${LD-ld} -m elf32ppclinux"
 	    ;;
 	  s390x-*linux*)
@@ -6971,7 +7024,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_x86_64"
 	    ;;
-	  ppc*-*linux*|powerpc*-*linux*)
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
 	    LD="${LD-ld} -m elf64ppc"
 	    ;;
 	  s390*-*linux*|s390*-*tpf*)
@@ -11126,10 +11182,14 @@ fi
   # before this can be enabled.
   hardcode_into_libs=yes
 
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -14957,10 +15017,14 @@ fi
   # before this can be enabled.
   hardcode_into_libs=yes
 
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -15307,7 +15371,7 @@ case $host in
   *-*-*linux*-*)
 $as_echo "#define __LINUX__ 1" >>confdefs.h
  ;;
-  *-*-mingw32)   LIBS="-liberty $LIBS" && CPPFLAGS="-DUNICODE -D_UNICODE $CPPFLAGS"
+  *-*-mingw32)   LIBS="-static-libgcc -static-libstdc++ $LIBS" && CPPFLAGS="-DUNICODE -D_UNICODE $CPPFLAGS"
 esac
 
 
@@ -15989,7 +16053,6 @@ DEFS=-DHAVE_CONFIG_H
 
 ac_libobjs=
 ac_ltlibobjs=
-U=
 for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
   # 1. Remove the extension, and $U if already installed.
   ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
@@ -16430,7 +16493,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by SSDEEP $as_me 2.9, which was
+This file was extended by SSDEEP $as_me 2.11, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -16496,7 +16559,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-SSDEEP config.status 2.9
+SSDEEP config.status 2.11
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -17602,7 +17665,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
 
   case $ac_file$ac_mode in
     "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
-  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # Older Autoconf quotes --file arguments for eval, but not when files
   # are listed without --file.  Let's play safe and only enable the eval
   # if we detect the quoting.
   case $CONFIG_FILES in
@@ -17653,7 +17716,7 @@ $as_echo X"$mf" |
     DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
     test -z "$DEPDIR" && continue
     am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "am__include" && continue
+    test -z "$am__include" && continue
     am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
     # Find all dependency output files, they are included files with
     # $(DEPDIR) in their names.  We invoke sed twice because it is the
diff --git a/configure.ac b/configure.ac
index cfbd491..a83dab6 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([SSDEEP],[2.9],[research at jessekornblum.com])
+AC_INIT([SSDEEP],[2.11],[research at jessekornblum.com])
 AM_INIT_AUTOMAKE
 
 AC_CONFIG_FILES([Makefile])
@@ -9,7 +9,6 @@ AC_CANONICAL_HOST
 AC_PROG_CC
 AC_PROG_CXX
 AC_LIBTOOL_WIN32_DLL
-#AC_PROG_LIBTOOL
 AM_PROG_LIBTOOL
 AC_PROG_INSTALL
 
@@ -17,7 +16,7 @@ AC_CONFIG_MACRO_DIR([m4])
 
 case $host in
   *-*-*linux*-*) AC_DEFINE([__LINUX__],1,[Linux operating system functions]) ;;
-  *-*-mingw32)   LIBS="-liberty $LIBS" && CPPFLAGS="-DUNICODE -D_UNICODE $CPPFLAGS"
+  *-*-mingw32)   LIBS="-static-libgcc -static-libstdc++ $LIBS" && CPPFLAGS="-DUNICODE -D_UNICODE $CPPFLAGS"
 esac
 
 
@@ -47,9 +46,9 @@ AC_CHECK_HEADERS([sys/mount.h],[],[],
 [#ifdef HAVE_SYS_TYPES_H
  # include <sys/types.h>
  #endif
- #ifdef HAVE_SYS_PARAM_H                                                     
- # include <sys/param.h>                           
- #endif])                 
+ #ifdef HAVE_SYS_PARAM_H
+ # include <sys/param.h>
+ #endif])
 
 AC_FUNC_FSEEKO
 
diff --git a/cycles.cpp b/cycles.cpp
index 9c9b206..ad944e7 100644
--- a/cycles.cpp
+++ b/cycles.cpp
@@ -12,7 +12,7 @@
  *
  */
 
-// $Id: cycles.cpp 144 2012-04-24 14:59:33Z jessekornblum $
+// $Id: cycles.cpp 184 2013-07-10 05:24:26Z jessekornblum $
 
 #include "ssdeep.h"
 
@@ -43,10 +43,10 @@ static void dump_table(void)
 int done_processing_dir(TCHAR *fn)
 {
   dir_table *last, *temp;
-  TCHAR *d_name = (TCHAR *)malloc(sizeof(TCHAR) * PATH_MAX);
+  TCHAR *d_name = (TCHAR *)malloc(sizeof(TCHAR) * SSDEEP_PATH_MAX);
 
 #ifdef _WIN32
-  _wfullpath(d_name,fn,PATH_MAX);
+  _wfullpath(d_name,fn,SSDEEP_PATH_MAX);
 #else
   realpath(fn,d_name);
 #endif
@@ -62,7 +62,7 @@ int done_processing_dir(TCHAR *fn)
 
   temp = my_table;
 
-  if (!_tcsncmp(d_name,temp->name,PATH_MAX))
+  if (!_tcsncmp(d_name,temp->name,SSDEEP_PATH_MAX))
   {
     my_table = my_table->next;
     free(temp->name);
@@ -75,7 +75,7 @@ int done_processing_dir(TCHAR *fn)
   {
     last = temp;
     temp = temp->next;
-    if (!_tcsncmp(d_name,temp->name,PATH_MAX))
+    if (!_tcsncmp(d_name,temp->name,SSDEEP_PATH_MAX))
     {
       last->next = temp->next;
       free(temp->name);
@@ -99,10 +99,10 @@ int done_processing_dir(TCHAR *fn)
 int processing_dir(TCHAR *fn)
 {
   dir_table *new_dir, *temp;
-  TCHAR *d_name = (TCHAR *)malloc(sizeof(TCHAR) * PATH_MAX);
+  TCHAR *d_name = (TCHAR *)malloc(sizeof(TCHAR) * SSDEEP_PATH_MAX);
 
 #ifdef _WIN32
-  _wfullpath(d_name,fn,PATH_MAX);
+  _wfullpath(d_name,fn,SSDEEP_PATH_MAX);
 #else
   realpath(fn,d_name);
 #endif
@@ -122,7 +122,7 @@ int processing_dir(TCHAR *fn)
   while (temp->next != NULL)
   {
     /* We should never be adding a directory that is already here */
-    if (!_tcsncmp(temp->name,d_name,PATH_MAX))
+    if (!_tcsncmp(temp->name,d_name,SSDEEP_PATH_MAX))
     {
       internal_error("%s: Attempt to add existing %s in processing_dir",
 		     __progname, d_name);
@@ -151,9 +151,9 @@ int have_processed_dir(TCHAR *fn)
   if (my_table == NULL)
     return FALSE;
 
-  d_name = (TCHAR *)malloc(sizeof(TCHAR) * PATH_MAX);
+  d_name = (TCHAR *)malloc(sizeof(TCHAR) * SSDEEP_PATH_MAX);
 #ifdef _WIN32
-  _wfullpath(d_name,fn,PATH_MAX);
+  _wfullpath(d_name,fn,SSDEEP_PATH_MAX);
 #else
   realpath(fn,d_name);
 #endif
@@ -161,7 +161,7 @@ int have_processed_dir(TCHAR *fn)
   temp = my_table;
   while (temp != NULL)
   {
-    if (!_tcsncmp(temp->name,d_name,PATH_MAX))
+    if (!_tcsncmp(temp->name,d_name,SSDEEP_PATH_MAX))
     {
       free(d_name);
       return TRUE;
diff --git a/dig.cpp b/dig.cpp
index 6fe2415..3ff77f9 100644
--- a/dig.cpp
+++ b/dig.cpp
@@ -4,55 +4,60 @@
 //
 // 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: dig.cpp 151 2012-07-14 03:13:38Z jessekornblum $
+// $Id: dig.cpp 191 2013-07-16 17:55:00Z jessekornblum $
 
 #include "ssdeep.h"
 
-static TCHAR DOUBLE_DIR[4] = 
-  { (TCHAR)DIR_SEPARATOR, 
+#define STATUS_OK   FALSE
+
+static int is_special_dir(TCHAR *d)
+{
+  return ((!_tcsncmp(d,_TEXT("."),1) && (_tcslen(d) == 1)) ||
+          (!_tcsncmp(d,_TEXT(".."),2) && (_tcslen(d) == 2)));
+}
+
+#ifndef _WIN32
+
+static TCHAR DOUBLE_DIR[4] =
+  { (TCHAR)DIR_SEPARATOR,
     (TCHAR)DIR_SEPARATOR,
     0
   };
 
-// RBF - WTF is going on with removing double slash and Windows defines?!?
-
-#ifndef _WIN32
 static void remove_double_slash(TCHAR *fn)
 {
   size_t tsize = sizeof(TCHAR);
-  //  TCHAR DOUBLE_DIR[4];
   TCHAR *tmp = fn, *new_str;
 
-  // RBF - Why on earth do we generate DOUBLE_DIR dynamically *every time*?
-  //  _sntprintf(DOUBLE_DIR,3,_TEXT("%c%c"),DIR_SEPARATOR,DIR_SEPARATOR);
-
   new_str = _tcsstr(tmp,DOUBLE_DIR);
   while (NULL != new_str)
   {
+    /*
 #ifdef _WIN32
-    /* On Windows, we have to allow the first two characters to be slashes
-       to account for UNC paths. e.g. \\SERVER\dir\path  */
+    // On Windows, we have to allow the first two characters to be slashes
+    // to account for UNC paths. e.g. \\SERVER\dir\path
     if (tmp == fn)
-    {  
+    {
       ++tmp;
-    } 
+    }
     else
     {
 #endif  // ifdef _WIN32
-    
+    */
       _tmemmove(new_str,new_str+tsize,_tcslen(new_str));
 
+      /*
 #ifdef _WIN32
     }
 #endif  // ifdef _WIN32
+      */
 
     new_str = _tcsstr(tmp,DOUBLE_DIR);
-
   }
 }
 
@@ -64,30 +69,30 @@ static void remove_single_dirs(TCHAR *fn)
 
   for (pos = 0 ; pos < sz ; pos++)
   {
-    /* Catch strings that end with /. (e.g. /foo/.)  */
-    if (pos > 0 && 
-	fn[pos-1] == _TEXT(DIR_SEPARATOR) && 
+    // Catch strings that end with /. (e.g. /foo/.)
+    if (pos > 0 &&
+	fn[pos-1] == _TEXT(DIR_SEPARATOR) &&
 	fn[pos]   == _TEXT('.') &&
 	fn[pos+1] == 0)
       fn[pos] = 0;
-    
+
     if (fn[pos] == _TEXT('.') && fn[pos+1] == _TEXT(DIR_SEPARATOR))
     {
       if (chars_found && fn[pos-1] == _TEXT(DIR_SEPARATOR))
       {
 	_tmemmove(fn+(pos*tsize),(fn+((pos+2)*tsize)),(sz-pos) * tsize);
-	
-	/* In case we have ././ we shift back one! */
+
+	// In case we have ././ we shift back one!
 	--pos;
 
       }
     }
-    else 
+    else
       ++chars_found;
   }
 }
 
-/* Removes all "../" references from the absolute path fn */
+// Removes all "../" references from the absolute path fn
 void remove_double_dirs(TCHAR *fn)
 {
   size_t pos, next_dir, sz = _tcslen(fn), tsize = sizeof(TCHAR);
@@ -103,46 +108,46 @@ void remove_double_dirs(TCHAR *fn)
 	   If not, we can't tell later on if the pos <= 0 or
 	   that the previous character was a DIR_SEPARATOR.
 	   This matters when we're looking at ..foo/ as an input */
-	
+
 	if (fn[pos-1] == _TEXT(DIR_SEPARATOR))
 	{
-	  
+
 	  next_dir = pos + 2;
-	  
+
 	  /* Back up to just before the previous DIR_SEPARATOR
 	     unless we're already at the start of the string */
 	  if (pos > 1)
 	    pos -= 2;
 	  else
 	    pos = 0;
-	  
+
 	  while (fn[pos] != _TEXT(DIR_SEPARATOR) && pos > 0)
 	    --pos;
-	  
+
 	  switch(fn[next_dir])
 	  {
 	  case DIR_SEPARATOR:
 	    _tmemmove(fn+pos,fn+next_dir,((sz - next_dir) + 1) * tsize);
 	    break;
-	    
+
 	  case 0:
 	    /* If we have /.. ending the filename */
 	    fn[pos+1] = 0;
 	    break;
-	    
-	    /* If we have ..foo, we should do nothing, but skip 
+
+	    /* If we have ..foo, we should do nothing, but skip
 	       over these double dots */
 	  default:
 	    pos = next_dir;
 	  }
 	}
       }
-      
+
       /* If we have two dots starting off the string, we should prepend
 	 a DIR_SEPARATOR and ignore the two dots. That is:
 	 from the root directory the path ../foo is really just /foo */
-    
-      else 
+
+      else
       {
 	fn[pos] = _TEXT(DIR_SEPARATOR);
 	_tmemmove(fn+pos+1,fn+pos+3,sz-(pos+3));
@@ -152,100 +157,24 @@ void remove_double_dirs(TCHAR *fn)
     }
   }
 }
-#endif  // ifndef _WIN32
-
-
-/* On Win32 systems directories are handled... differently
-   Attempting to process d: causes an error, but d:\ does not.
-   Conversely, if you have a directory "foo",
-   attempting to process d:\foo\ causes an error, but d:\foo does not.
-   The following turns d: into d:\ and d:\foo\ into d:\foo */
-
-#ifdef _WIN32
-static void clean_name_win32(TCHAR *fn)
-{
-  size_t length = _tcslen(fn);
-
-  if (length < 2)
-    return;
-
-  if (length == 2 && fn[1] == _TEXT(':'))
-  {
-    fn[length+1] = 0;
-    fn[length]   = _TEXT(DIR_SEPARATOR);
-    return;
-  }
-
-  if (fn[length-1] == _TEXT(DIR_SEPARATOR) && length != 3)
-  {
-    fn[length - 1] = 0;
-  }
-}
-
-static int is_win32_device_file(TCHAR *fn)
-{
-  /* Specifications for device files came from
-     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/createfile.asp
-
-     -- Physical devices (like hard drives) are 
-        \\.\PhysicalDriveX where X is a digit from 0 to 9
-     -- Tape devices is \\.\tapeX where X is a digit from 0 to 9
-     -- Logical volumes is \\.\X: where X is a letter */
-
-  if (!_tcsnicmp(fn, _TEXT("\\\\.\\physicaldrive"),17) &&
-      (_tcslen(fn) == 18) && 
-      isdigit(fn[17]))
-    return TRUE;
-
-  if (!_tcsnicmp(fn, _TEXT("\\\\.\\tape"),8) &&
-      (_tcslen(fn) == 9) && 
-      isdigit(fn[8]))
-    return TRUE;
- 
-  if ((!_tcsnicmp(fn,_TEXT("\\\\.\\"),4)) &&
-      (_tcslen(fn) == 6) &&
-      (isalpha(fn[4])) &&
-      (fn[5] == ':'))
-    return TRUE;
-
-  return FALSE;
-}
 
-#endif  /* ifdef _WIN32 */
 
+// We don't need to call these functions when running in Windows
+// as we've already called real_path() on them in main.c. These
+// functions are necessary in *nix so that we can clean up the
+// path names without removing the names of symbolic links. They
+// are also called when the user has specified an absolute path
+// but has included extra double dots or such.
 
 static void clean_name(state *s, TCHAR *fn)
 {
-#ifdef _WIN32
-  clean_name_win32(fn);
-#else
-
-  /* We don't need to call these functions when running in Windows
-     as we've already called real_path() on them in main.c. These
-     functions are necessary in *nix so that we can clean up the 
-     path names without removing the names of symbolic links. They
-     are also called when the user has specified an absolute path
-     but has included extra double dots or such. */
-
-  if (!(s->mode & mode_relative))
-  {
+  if (not (s->mode & mode_relative)) {
     remove_double_slash(fn);
     remove_single_dirs(fn);
     remove_double_dirs(fn);
   }
-#endif
-}
-
-
-
-
-static int is_special_dir(TCHAR *d)
-{
-  return ((!_tcsncmp(d,_TEXT("."),1) && (_tcslen(d) == 1)) ||
-          (!_tcsncmp(d,_TEXT(".."),2) && (_tcslen(d) == 2)));
 }
 
-#define STATUS_OK   FALSE
 
 static int process_dir(state *s, TCHAR *fn)
 {
@@ -254,8 +183,6 @@ static int process_dir(state *s, TCHAR *fn)
   _TDIR *current_dir;
   struct _tdirent *entry;
 
-  //  print_status (_TEXT("Called process_dir(%s)"), fn);
-
   if (have_processed_dir(fn))
   {
     print_error_unicode(s,fn,"symlink creates cycle");
@@ -264,31 +191,31 @@ static int process_dir(state *s, TCHAR *fn)
 
   if (!processing_dir(fn))
     internal_error("%s: Cycle checking failed to register directory.", fn);
-  
-  if ((current_dir = _topendir(fn)) == NULL) 
+
+  if ((current_dir = _topendir(fn)) == NULL)
   {
     print_error_unicode(s,fn,"%s", strerror(errno));
     return STATUS_OK;
-  }    
+  }
 
-  new_file = (TCHAR *)malloc(sizeof(TCHAR) * PATH_MAX);
+  new_file = (TCHAR *)malloc(sizeof(TCHAR) * SSDEEP_PATH_MAX);
   if (NULL == new_file)
     internal_error("%s: Out of memory", __progname);
 
-  while ((entry = _treaddir(current_dir)) != NULL) 
+  while ((entry = _treaddir(current_dir)) != NULL)
   {
     if (is_special_dir(entry->d_name))
       continue;
-    
-    _sntprintf(new_file,PATH_MAX,_TEXT("%s%c%s"),
+
+    _sntprintf(new_file,SSDEEP_PATH_MAX,_TEXT("%s%c%s"),
 	       fn,DIR_SEPARATOR,entry->d_name);
 
     return_value = process_normal(s,new_file);
-
   }
+
   free(new_file);
   _tclosedir(current_dir);
-  
+
   if (!done_processing_dir(fn))
     internal_error("%s: Cycle checking failed to unregister directory.", fn);
 
@@ -300,27 +227,27 @@ static int file_type_helper(_tstat_t sb)
 {
   if (S_ISREG(sb.st_mode))
     return file_regular;
-  
+
   if (S_ISDIR(sb.st_mode))
     return file_directory;
-  
+
   if (S_ISBLK(sb.st_mode))
     return file_block;
-  
+
   if (S_ISCHR(sb.st_mode))
     return file_character;
-  
+
   if (S_ISFIFO(sb.st_mode))
     return file_pipe;
 
   /* These file types do not exist in Win32 */
 #ifndef _WIN32
-  
+
   if (S_ISSOCK(sb.st_mode))
     return file_socket;
-  
+
   if (S_ISLNK(sb.st_mode))
-    return file_symlink;  
+    return file_symlink;
 #endif   /* ifndef _WIN32 */
 
 
@@ -353,7 +280,6 @@ static int file_type(state *s, TCHAR *fn)
 }
 
 
-#ifndef _WIN32
 static int should_hash_symlink(state *s, TCHAR *fn, int *link_type)
 {
   int type;
@@ -364,7 +290,7 @@ static int should_hash_symlink(state *s, TCHAR *fn, int *link_type)
 
   // We must look at what this symlink points to before we process it.
   // The normal file_type function uses lstat to examine the file,
-  // we use stat to examine what this symlink points to. 
+  // we use stat to examine what this symlink points to.
   if (_sstat(fn,&sb))
     {
       print_error_unicode(s,fn,"%s",strerror(errno));
@@ -382,13 +308,12 @@ static int should_hash_symlink(state *s, TCHAR *fn, int *link_type)
 	  print_error_unicode(s,fn,"Is a directory");
 	}
       return FALSE;
-    }    
+    }
 
   if (link_type != NULL)
     *link_type = type;
-  return TRUE;    
+  return TRUE;
 }
-#endif
 
 
 #define RETURN_IF_MODE(A) \
@@ -397,12 +322,9 @@ if (s->mode & A) \
 break;
 
 
-
-
-
 static int should_hash(state *s, TCHAR *fn)
 {
-  int type = file_type(s,fn);
+  int type = file_type(s, fn);
 
   if (NULL == s || NULL == fn)
     fatal_error("%s: Null state passed into should_hash", __progname);
@@ -411,26 +333,36 @@ static int should_hash(state *s, TCHAR *fn)
   {
     if (s->mode & mode_recursive)
       process_dir(s,fn);
-    else 
+    else
     {
       print_error_unicode(s,fn,"Is a directory");
     }
     return FALSE;
   }
 
-#ifndef _WIN32
   if (type == file_symlink)
     return should_hash_symlink(s,fn,NULL);
-#endif
 
   if (type == file_unknown)
     return FALSE;
 
-  /* By default we hash anything we can't identify as a "bad thing" */
+  // By default we hash anything we can't identify as a "bad thing"
   return TRUE;
 }
 
 
+int process_normal(state *s, TCHAR *fn)
+{
+  clean_name(s,fn);
+
+  if (should_hash(s,fn))
+    return (hash_file(s,fn));
+
+  return FALSE;
+}
+#endif   // ifndef _WIN32
+
+
 /// The largest number of bytes we can process from stdin
 /// This limit is arbitrary and can be adjusted at will
 #define MAX_STDIN_BUFFER      536870912
@@ -441,7 +373,7 @@ int process_stdin(state *s)
   if (NULL == s)
     return TRUE;
 
-  char sum[FUZZY_MAX_RESULT];  
+  char sum[FUZZY_MAX_RESULT];
   unsigned char * buffer = (unsigned char *)malloc(sizeof(unsigned char ) * MAX_STDIN_BUFFER);
   if (NULL == buffer)
     return TRUE;
@@ -471,115 +403,226 @@ int process_stdin(state *s)
 }
 
 
-int process_normal(state *s, TCHAR *fn)
+
+
+#ifdef _WIN32
+static int is_win32_device_file(TCHAR *fn)
 {
-  clean_name(s,fn);
+  /* Specifications for device files came from
+     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/createfile.asp
+
+     -- Physical devices (like hard drives) are
+        \\.\PhysicalDriveX where X is a digit from 0 to 9
+     -- Tape devices is \\.\tapeX where X is a digit from 0 to 9
+     -- Logical volumes is \\.\X: where X is a letter */
+
+  if (!_tcsnicmp(fn, _TEXT("\\\\.\\physicaldrive"),17) &&
+      (_tcslen(fn) == 18) &&
+      isdigit(fn[17]))
+    return TRUE;
+
+  if (!_tcsnicmp(fn, _TEXT("\\\\.\\tape"),8) &&
+      (_tcslen(fn) == 9) &&
+      isdigit(fn[8]))
+    return TRUE;
+
+  if ((!_tcsnicmp(fn,_TEXT("\\\\.\\"),4)) &&
+      (_tcslen(fn) == 6) &&
+      (isalpha(fn[4])) &&
+      (fn[5] == ':'))
+    return TRUE;
 
-  if (should_hash(s,fn))
-    return (hash_file(s,fn));
-  
   return FALSE;
 }
 
 
-#ifdef _WIN32
-int process_win32(state *s, TCHAR *fn)
+bool process_dir_win32(state *s, TCHAR *fn) {
+  TCHAR new_fn[SSDEEP_PATH_MAX];
+
+  if (have_processed_dir(fn)) {
+    print_error_unicode(s, fn, "Cycle detected");
+    return true;
+  }
+
+  processing_dir(fn);
+
+  _sntprintf(new_fn,
+	     SSDEEP_PATH_MAX,
+	     _TEXT("%s\\*"),
+	     fn);
+
+  process_win32(s, new_fn);
+
+  done_processing_dir(fn);
+  return false;
+}
+
+
+bool process_win32(state *s, TCHAR *fn)
 {
-  int rc, status = STATUS_OK;
-  TCHAR *asterisk, *question, *tmp, *dirname, *new_fn;
-  WIN32_FIND_DATAW FindFileData;
+  int rc;
+  size_t len;
   HANDLE hFind;
+  TCHAR dirname[SSDEEP_PATH_MAX], new_fn[SSDEEP_PATH_MAX], expanded_fn[SSDEEP_PATH_MAX];
+  WIN32_FIND_DATAW FindFileData;
+
+  if (NULL == s or NULL == fn)
+    return true;
 
-  //  print_status("Called process_win32(%S)", fn);
+  //print_status("process_win32 got %S", fn);
 
   if (is_win32_device_file(fn))
-    return (hash_file(s,fn));
+    return hash_file(s, fn);
+  if (is_special_dir(fn))
+    return false;
+
+  // Most Win32 programs reject 'c:'
+  // as an error or use it to alias the current working directory on c:.
+  // As a convenience to users, we're going to accept 'c:'. To do this
+  // we change it into 'c:\'
+  if (_tcslen(fn) == 2 and isalpha(fn[0]) and fn[1] == _TEXT(':')) {
+    fn[2] = _TEXT(DIR_SEPARATOR);
+    fn[3] = 0;
+  }
+
+  // FindFirstFile doesn't accept '\' as the trailing character.
+  // If we get '\' as a trailing character, we assume this is a directory
+  // and handle that according. In recursive mode, go through the directory
+  // entries. Otherwise, return an error.
+  len = _tcslen(fn);
+  if (fn[len-1] == _TEXT(DIR_SEPARATOR)) {
+    if (s->mode & mode_recursive) {
+      fn[len]   = _TEXT('*');
+      fn[len+1] = 0;
+    } else {
+      print_error_unicode(s, fn, "Is a directory");
+      return false;
+    }
+  }
+
+  //print_status("cleaned name %S", fn);
 
-  /* Filenames without wildcards can be processed by the
-     normal recursion code. */
-  asterisk = _tcschr(fn,L'*');
-  question = _tcschr(fn,L'?');
-  if (NULL == asterisk && NULL == question)
-    return (process_normal(s,fn));
-  
-  hFind = FindFirstFile(fn, &FindFileData);
+  // If we don't have it already, create the expanded filename.
+  // "C:\foo\bar.txt" --> "\\?\C:\foo\bar.txt"
+  if (not expanded_path(fn) and
+      not (s->mode & mode_relative)) {
+    _sntprintf(expanded_fn,
+	       SSDEEP_PATH_MAX,
+	       _TEXT("\\\\?\\%s"),
+	       fn);
+  }
+  else {
+    _tcsncpy(expanded_fn, fn, SSDEEP_PATH_MAX);
+  }
+  //print_status("expanded filename %S", expanded_fn);
+
+  hFind = FindFirstFile(expanded_fn, &FindFileData);
   if (INVALID_HANDLE_VALUE == hFind)
   {
-    print_error_unicode(s,fn,"No such file or directory");
-    return STATUS_OK;
+    // We don't display an error if there was a wildcard anywhere in the
+    // original filename, e.g. C:\foo\*. When this happens it means we just
+    // didn't find any matching files.
+    // Note that we still display errors with the original 'fn'
+    if (not _tcsstr(fn, _TEXT("*")))
+      print_error_unicode(s, fn, "No such file or directory");
+    return false;
   }
-  
-#define FATAL_ERROR_UNK(A) if (NULL == A) fatal_error("%s: %s", __progname, strerror(errno));
-#define FATAL_ERROR_MEM(A) if (NULL == A) fatal_error("%s: Out of memory", __progname);
-  
-  MD5DEEP_ALLOC(TCHAR,new_fn,PATH_MAX);
-  
-  dirname = _tcsdup(fn);
-  FATAL_ERROR_MEM(dirname);
-  
+
+  _tcsncpy(dirname, fn, SSDEEP_PATH_MAX);
   my_dirname(dirname);
-  
-  rc = 1;
-  while (0 != rc)
-  {
-    if (!(is_special_dir(FindFileData.cFileName)))
-    {
-      /* The filename we've found doesn't include any path information.
-	 We have to add it back in manually. Thankfully Windows doesn't
-	 allow wildcards in the early part of the path. For example,
-	 we will never see:  c:\bin\*\tools 
 
-	 Because the wildcard is always in the last part of the input
-	 (e.g. c:\bin\*.exe) we can use the original dirname, combined
-	 with the filename we've found, to make the new filename. */
+  do {
+    // The filename we've found doesn't include any path information.
+    // That is, for the file C:\foo\bar.txt, we have bar.txt.
+    // We have to add the path information back in manually.
+    // Thankfully Windows doesn't allow wildcards in the early part
+    // of the path. For example, we will never see:  c:\bin\*\tools
+    //
+    // Because the wildcard is always in the last part of the input
+    // (e.g. c:\bin\*.exe) we can use the original dirname, combined
+    // with the filename we've found, to make the new filename.
+    if (not is_special_dir(FindFileData.cFileName)) {
 
       //      print_status("Found file: %S", FindFileData.cFileName);
 
-
-      if (s->mode & mode_relative)
-      {
-	_sntprintf(new_fn,PATH_MAX,
-		   _TEXT("%s%s"), dirname, FindFileData.cFileName);
+      _sntprintf(new_fn,
+		 SSDEEP_PATH_MAX,
+		 _TEXT("%s%s"),
+		 dirname,
+		 FindFileData.cFileName);
+      if (not expanded_path(new_fn) and
+	  not (s->mode & mode_relative)) {
+	_sntprintf(expanded_fn,
+		   SSDEEP_PATH_MAX,
+		   _TEXT("\\\\?\\%s"),
+		   new_fn);
+      } else {
+	_tcsncpy(expanded_fn, new_fn, SSDEEP_PATH_MAX);
       }
-      else
-      {	  
-	MD5DEEP_ALLOC(TCHAR,tmp,PATH_MAX);
-	_sntprintf(tmp,PATH_MAX,_TEXT("%s%s"),dirname,FindFileData.cFileName);
-	_wfullpath(new_fn,tmp,PATH_MAX);
-	free(tmp);
+
+      //      print_status("Getting attributes for %S", expanded_fn);
+      DWORD dwFileAttributes = FindFileData.dwFileAttributes;
+
+      if (INVALID_FILE_ATTRIBUTES == dwFileAttributes) {
+	print_error_unicode(s, new_fn, "File read error");
+      } else if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+	if (s->mode & mode_recursive) {
+	  process_dir_win32(s, new_fn);
+	}
+
+      // TODO Add support for symbolic links
+      /*
+      } else if (dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+	// Generally we skip reparse points (e.g. symbolic links,
+	// junction points, etc) UNLESS it's part of single
+	// instance storage. Single Instance Storage "is a system's
+	// ability to keep one copy of content that multiple users
+	// or computers share". See
+	// http://blogs.technet.com/b/filecab/archive/2006/02/03/single-instance-store-sis-in-windows-storage-server-r2.aspx
+	switch (FindFileData.dwReserved0) {
+	case IO_REPARSE_TAG_MOUNT_POINT:
+	  print_error_unicode(s, new_fn, "Junction point, skipping.");
+	  break;
+
+	case IO_REPARSE_TAG_SYMLINK:
+	  print_error_unicode(s, new_fn, "Symbolic link, skipping.");
+	  break;
+
+	case IO_REPARSE_TAG_SIS:
+	  hash_file(s, new_fn);
+	  break;
+
+	default:
+	  print_error_unicode(s,
+			      new_fn,
+			      "Unknown reparse point 0x%"PRIx32", skipping. Please report this to the developers",
+			      FindFileData.dwReserved0);
+	  break;
+	}
+      */
+
+      } else {
+	hash_file(s, new_fn);
       }
-      
-      process_normal(s,new_fn); 
     }
-    
+
     rc = FindNextFile(hFind, &FindFileData);
-    if (0 == rc)
-      if (ERROR_NO_MORE_FILES != GetLastError())
-      {
-	/* The Windows API for getting an intelligible error message
-	   is beserk. Rather than play their silly games, we 
-	   acknowledge that an unknown error occured and hope we
-	   can continue. */
-	print_error_unicode(s,fn,"Unknown error while expanding wildcard");
-	free(dirname);
-	free(new_fn);
-	return STATUS_OK;
-      }
+  } while (rc != 0);
+
+  if (GetLastError() != ERROR_NO_MORE_FILES) {
+    // The Windows API for getting an intelligible error message
+    // is beserk. Rather than play their silly games, we
+    // acknowledge that an unknown error occured and hope we
+    // can continue.
+    print_error_unicode(s, new_fn, "Unknown error during directory traversal");
+    return true;
   }
-  
+
   rc = FindClose(hFind);
-  if (0 == rc)
-  {
-    print_error_unicode(s,
-			fn,
-			"Unknown error while cleaning up wildcard expansion");
+  if (0 == rc) {
+    print_error_unicode(s, fn, "Unknown error cleaning up directory traversal");
   }
 
-  free(dirname);
-  free(new_fn);
-
-  return status;
+  return false;
 }
 #endif
-
-
diff --git a/engine.cpp b/engine.cpp
index 0087625..41f19f6 100644
--- a/engine.cpp
+++ b/engine.cpp
@@ -1,43 +1,40 @@
-// $Id: engine.cpp 163 2012-07-17 19:59:54Z jessekornblum $ 
+// $Id: engine.cpp 211 2014-05-14 18:20:23Z jessekornblum $ 
 
 #include "main.h"
 #include "ssdeep.h"
 #include "match.h"
 
-
 #define MAX_STATUS_MSG   78
 
-bool display_result(state *s, const TCHAR * fn, const char * sum)
-{
+bool display_result(state *s, const TCHAR * fn, const char * sum) {
   // Only spend the extra time to make a Filedata object if we need to
-  if (MODE(mode_match_pretty) or MODE(mode_match) or MODE(mode_directory))
-  {
+  if (MODE(mode_match_pretty) or MODE(mode_match) or MODE(mode_directory)) {
     Filedata * f;
-
-    try 
-    {
+    
+    try {
       f = new Filedata(fn, sum);
     } 
-    catch (std::bad_alloc)
-    {
+    catch (std::bad_alloc) {
       fatal_error("%s: Unable to create Filedata object in engine.cpp:display_result()", __progname);
     }
 
-    if (MODE(mode_match_pretty)) 
-    {
-      if (match_add(s,f))
-	print_error_unicode(s,fn,"Unable to add hash to set of known hashes");
+    if (MODE(mode_match_pretty)) {
+      if (match_add(s, f))
+	print_error_unicode(s, fn, "Unable to add hash to set of known hashes");
     }
-    else
-    {
+    else {
       // This block is for MODE(mode_match) or MODE(mode_directory)
-      match_compare(s,f);
-
-      if (MODE(mode_directory))
-	if (match_add(s,f))
+      match_compare(s, f);
+      
+      if (MODE(mode_directory)) {
+	if (match_add(s, f))
 	  print_error_unicode(s,
 			      fn,
 			      "Unable to add hash to set of known hashes");
+      } else {
+	// We haven't add f to the set of knowns, so let's free it.
+	delete f;
+      }
     }
   }
   else
@@ -50,7 +47,7 @@ bool display_result(state *s, const TCHAR * fn, const char * sum)
     }
 
     printf ("%s,\"", sum);
-    display_filename(stdout,fn,TRUE);
+    display_filename(stdout, fn, TRUE);
     print_status("\"");
   }
 
@@ -58,14 +55,27 @@ bool display_result(state *s, const TCHAR * fn, const char * sum)
 }
 
 
-int hash_file(state *s, TCHAR *fn)
-{
+int hash_file(state *s, TCHAR *fn) {
   size_t fn_length;
   char *sum;
   TCHAR *my_filename, *msg;
   FILE *handle;
-  
-  handle = _tfopen(fn,_TEXT("rb"));
+
+#ifdef WIN32  
+  TCHAR expanded_fn[SSDEEP_PATH_MAX];
+  if (not expanded_path(fn)) {
+    _sntprintf(expanded_fn, 
+	       SSDEEP_PATH_MAX,
+	       _TEXT("\\\\?\\%s"), 
+	       fn);
+  } else {
+    _tcsncpy(expanded_fn, fn, SSDEEP_PATH_MAX);
+  }
+  handle = _tfopen(expanded_fn, _TEXT("rb"));
+# else
+  handle = fopen(fn, "rb");
+#endif
+
   if (NULL == handle)
   {
     print_error_unicode(s,fn,"%s", strerror(errno));
diff --git a/filedata.cpp b/filedata.cpp
index bd7c3a9..a46ebda 100644
--- a/filedata.cpp
+++ b/filedata.cpp
@@ -1,5 +1,5 @@
 // SSDEEP
-// $Id: filedata.cpp 163 2012-07-17 19:59:54Z jessekornblum $
+// $Id: filedata.cpp 214 2014-09-09 23:31:07Z jessekornblum $
 // Copyright (C) 2012 Kyrus. See COPYING for details.
 
 #ifdef HAVE_CONFIG_H
@@ -56,7 +56,7 @@ void Filedata::clear_cluster(void)
 }
 
 
-Filedata::Filedata(const TCHAR *fn, const char * sig, const char * match_file)
+Filedata::Filedata(const TCHAR * fn, const char * sig, const char * match_file)
 {
   m_signature = std::string(sig);
   if (not valid())
@@ -75,7 +75,7 @@ Filedata::Filedata(const TCHAR *fn, const char * sig, const char * match_file)
 }
 
 
-Filedata::Filedata(const std::string sig, const char * match_file)
+Filedata::Filedata(const std::string& sig, const char * match_file)
 {
   // Set the easy stuff first
   m_cluster = NULL;
@@ -106,45 +106,49 @@ Filedata::Filedata(const std::string sig, const char * match_file)
 
     return;
   }
-  
+
   // There is a filename. Ok.
   // Advance past the comma and quotation mark.
   start += 2;
-  
+
   // Look for the second quotation mark, which should be at the end
-  // of the string. 
+  // of the string.
   stop = sig.find_last_of('"');
   if (stop != sig.size() - 1)
     throw std::bad_alloc();
-  
+
   // Strip off the final quotation mark and record the filename
   std::string tmp = sig.substr(start,(stop - start));
 
   // Strip off the filename from the signature. Remember that "start"
   // now points to two characters ahead of the comma
   m_signature = sig.substr(0,start-2);
-  
+
   // Unescape any quotation marks in the filename
   while (tmp.find(std::string("\\\"")) != std::string::npos)
     tmp.replace(tmp.find(std::string("\\\"")),2,std::string("\""));
-  
+
 #ifndef _WIN32
   m_filename = strdup(tmp.c_str());
 #else
   char * tmp2 = strdup(tmp.c_str());
-  
-  // On Win32 we have to do a kludgy cast from ordinary char 
+
+  // On Win32 we have to do a kludgy cast from ordinary char
   // values to the TCHAR values we use internally. Because we may have
   // reset the string length, get it again.
   // The extra +1 is for the terminating newline
   size_t i, sz = strlen(tmp2);
   m_filename = (TCHAR *)malloc(sizeof(TCHAR) * (sz + 1));
-  if (NULL == m_filename)
+  if (NULL == m_filename) {
+    free (tmp2);
     throw std::bad_alloc();
+  }
 
   for (i = 0 ; i < sz ; i++)
     m_filename[i] = (TCHAR)(tmp2[i]);
   m_filename[i] = 0;
+
+  free (tmp2);
 #endif
 }
 
diff --git a/filedata.h b/filedata.h
index 0290b69..f7fea74 100644
--- a/filedata.h
+++ b/filedata.h
@@ -4,11 +4,13 @@
 /// @file filedata.h
 // Copyright (C) 2012 Kyrus. See COPYING for details
 
-// $Id: filedata.h 160 2012-07-17 01:00:07Z jessekornblum $
+// $Id: filedata.h 214 2014-09-09 23:31:07Z jessekornblum $
 
 #include <set>
 #include <string>
 #include <iostream>
+#include <stdlib.h>
+#include <assert.h>
 #include "tchar-local.h"
 
 /// Contains a fuzzy hash and associated metadata for file
@@ -25,9 +27,9 @@ class Filedata
   /// Creates a new Filedata object with the given filename and signature
   ///
   /// If sig is not valid, throws std::bad_alloc
-  Filedata(const std::string sig, const char * match_file = NULL);
+  Filedata(const std::string& sig, const char * match_file = NULL);
 
-  /// Returns the file's fuzzy hash without a filename. 
+  /// Returns the file's fuzzy hash without a filename.
   /// std::string("[blocksize]:[sig1]:[sig2]")
   std::string get_signature(void) const { return m_signature; }
 
@@ -47,7 +49,11 @@ class Filedata
   std::set<Filedata* >* get_cluster(void) const { return m_cluster; }
   void clear_cluster(void);
 
+  ~Filedata() { if (m_filename) { free(m_filename); } }
+
  private:
+  Filedata(const Filedata &other) { assert(false); /* never copy */ }
+
   std::set<Filedata *> * m_cluster;
 
   /// Original signature in the form [blocksize]:[sig1]:[sig2]
diff --git a/fuzzy.c b/fuzzy.c
index a883588..66c882d 100644
--- a/fuzzy.c
+++ b/fuzzy.c
@@ -1,376 +1,487 @@
-
-// ssdeep
-// Copyright (C) 2012 Kyrus
-// Copyright (C) 2006 ManTech International Corporation
-//
-// $Id: fuzzy.c 152 2012-07-14 18:09:45Z jessekornblum $
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// 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; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-// 
-// The code in this file, and this file only, is based on SpamSum, part 
-// of the Samba project: 
-//   http://www.samba.org/ftp/unpacked/junkcode/spamsum/
-//
-// Because of where this file came from, any program that contains it
-// must be licensed under the terms of the General Public License (GPL).
-// See the file COPYING for details. The author's original comments
-// about licensing are below:
-// 
-//
-//
-// This is a checksum routine that is specifically designed for spam. 
-// Copyright Andrew Tridgell <tridge at samba.org> 2002
-//
-// This code is released under the GNU General Public License version 2
-// or later.  Alteratively, you may also use this code under the terms
-// of the Perl Artistic license.
-//
-// If you wish to distribute this code under the terms of a different
-// free software license then please ask me. If there is a good reason
-// then I will probably say yes.
-//
-
-#include "main.h"
+/* ssdeep
+ * Copyright (C) 2002 Andrew Tridgell <tridge at samba.org>
+ * Copyright (C) 2006 ManTech International Corporation
+ * Copyright (C) 2013 Helmut Grohne <helmut at subdivi.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Earlier versions of this code were named fuzzy.c and can be found at:
+ *     http://www.samba.org/ftp/unpacked/junkcode/spamsum/
+ *     http://ssdeep.sf.net/
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include "fuzzy.h"
 
-off_t find_file_size(FILE *h);
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define likely(x)       __builtin_expect(!!(x), 1)
+#define unlikely(x)     __builtin_expect(!!(x), 0)
+#else
+#define likely(x) x
+#define unlikely(x) x
+#endif
 
-#define MIN_BLOCKSIZE  3
-#define ROLLING_WINDOW 7
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
 
-#define HASH_PRIME     0x01000193
-#define HASH_INIT      0x28021967
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
 
-// Our input buffer when reading files to hash
-#define BUFFER_SIZE  8192
+#define ROLLING_WINDOW 7
+#define MIN_BLOCKSIZE 3
+#define HASH_PRIME 0x01000193
+#define HASH_INIT 0x28021967
+#define NUM_BLOCKHASHES 31
 
-static struct {
+struct roll_state {
   unsigned char window[ROLLING_WINDOW];
   uint32_t h1, h2, h3;
   uint32_t n;
-} roll_state;
-
+};
 
-//
-// A rolling hash, based on the Adler checksum. By using a rolling hash
-// we can perform auto resynchronisation after inserts/deletes
-//
-// internally, h1 is the sum of the bytes in the window and h2
-// is the sum of the bytes times the index
-//
-// h3 is a shift/xor based rolling hash, and is mostly needed to ensure that
-// we can cope with large blocksize values
-//
-static inline uint32_t roll_hash(unsigned char c)
-{
-  roll_state.h2 -= roll_state.h1;
-  roll_state.h2 += ROLLING_WINDOW * c;
-  
-  roll_state.h1 += c;
-  roll_state.h1 -= roll_state.window[roll_state.n % ROLLING_WINDOW];
-  
-  roll_state.window[roll_state.n % ROLLING_WINDOW] = c;
-  roll_state.n++;
-  
-  // The original spamsum AND'ed this value with 0xFFFFFFFF which
-  // in theory should have no effect. This AND has been removed 
-  // for performance (jk)
-  roll_state.h3 = (roll_state.h3 << 5); //& 0xFFFFFFFF;
-  roll_state.h3 ^= c;
-  
-  return roll_state.h1 + roll_state.h2 + roll_state.h3;
+static void roll_init(/*@out@*/ struct roll_state *self) {
+	memset(self, 0, sizeof(struct roll_state));
 }
 
-//
-// reset the state of the rolling hash and return the initial rolling hash value
-//
-static uint32_t roll_reset(void)
-{	
-  memset(&roll_state, 0, sizeof(roll_state));
-  return 0;
-}
+/*
+ * a rolling hash, based on the Adler checksum. By using a rolling hash
+ * we can perform auto resynchronisation after inserts/deletes
+
+ * internally, h1 is the sum of the bytes in the window and h2
+ * is the sum of the bytes times the index
 
-// a simple non-rolling hash, based on the FNV hash 
-static inline uint32_t sum_hash(unsigned char c, uint32_t h)
+ * h3 is a shift/xor based rolling hash, and is mostly needed to ensure that
+ * we can cope with large blocksize values
+ */
+static void roll_hash(struct roll_state *self, unsigned char c)
 {
-  h *= HASH_PRIME;
-  h ^= c;
-  return h;
-}
+  self->h2 -= self->h1;
+  self->h2 += ROLLING_WINDOW * (uint32_t)c;
+
+  self->h1 += (uint32_t)c;
+  self->h1 -= (uint32_t)self->window[self->n % ROLLING_WINDOW];
 
-typedef struct _ss_context {
-  char *ret, *p;
-  // This is the file size, which should be uint64_t, but we
-  // generally do not process files that large here.
-  uint32_t total_chars;
-  uint32_t h, h2, h3;
-  uint32_t j, n, i, k;
-  uint32_t block_size;
-  char ret2[SPAMSUM_LENGTH/2 + 1];
-} ss_context;
+  self->window[self->n % ROLLING_WINDOW] = c;
+  self->n++;
 
+  /* The original spamsum AND'ed this value with 0xFFFFFFFF which
+   * in theory should have no effect. This AND has been removed
+   * for performance (jk) */
+  self->h3 <<= 5;
+  self->h3 ^= c;
+}
 
-static void ss_destroy(ss_context *ctx)
+static uint32_t roll_sum(const struct roll_state *self)
 {
-  if (ctx->ret != NULL)
-    free(ctx->ret);
+  return self->h1 + self->h2 + self->h3;
 }
 
+/* A simple non-rolling hash, based on the FNV hash. */
+static uint32_t sum_hash(unsigned char c, uint32_t h)
+{
+  return (h * HASH_PRIME) ^ c;
+}
 
-static int ss_init(ss_context *ctx, FILE *handle)
+/* A blockhash contains a signature state for a specific (implicit) blocksize.
+ * The blocksize is given by SSDEEP_BS(index). The h and halfh members are the
+ * FNV hashes, where halfh stops to be reset after digest is SPAMSUM_LENGTH/2
+ * long. The halfh hash is needed be able to truncate digest for the second
+ * output hash to stay compatible with ssdeep output. */
+struct blockhash_context
 {
-  if (NULL == ctx)
-    return TRUE;
+  uint32_t h, halfh;
+  char digest[SPAMSUM_LENGTH];
+  char halfdigest;
+  unsigned int dlen;
+};
 
-  ctx->ret = (char *)malloc(sizeof(char) * FUZZY_MAX_RESULT);
-  if (ctx->ret == NULL)
-    return TRUE;
+struct fuzzy_state
+{
+  unsigned int bhstart, bhend;
+  struct blockhash_context bh[NUM_BLOCKHASHES];
+  size_t total_size;
+  struct roll_state roll;
+};
 
-  if (handle != NULL)
-    ctx->total_chars = find_file_size(handle);
+#define SSDEEP_BS(index) (((uint32_t)MIN_BLOCKSIZE) << (index))
 
-  ctx->block_size = MIN_BLOCKSIZE;
-  while (ctx->block_size * SPAMSUM_LENGTH < ctx->total_chars) {
-    ctx->block_size = ctx->block_size * 2;
-  }
+/*@only@*/ /*@null@*/ struct fuzzy_state *fuzzy_new(void)
+{
+  struct fuzzy_state *self;
+  if(NULL == (self = malloc(sizeof(struct fuzzy_state))))
+    /* malloc sets ENOMEM */
+    return NULL;
+  self->bhstart = 0;
+  self->bhend = 1;
+  self->bh[0].h = HASH_INIT;
+  self->bh[0].halfh = HASH_INIT;
+  self->bh[0].digest[0] = '\0';
+  self->bh[0].halfdigest = '\0';
+  self->bh[0].dlen = 0;
+  self->total_size = 0;
+  roll_init(&self->roll);
+  return self;
+}
 
-  return FALSE;
+/*@only@*/ /*@null@*/ struct fuzzy_state *fuzzy_clone(const struct fuzzy_state *state)
+{
+  struct fuzzy_state *newstate;
+  if (NULL == (newstate = malloc(sizeof(struct fuzzy_state))))
+    /* malloc sets ENOMEM */
+    return NULL;
+  memcpy(newstate, state, sizeof(struct fuzzy_state));
+  return newstate;
 }
 
-static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-static void ss_engine(ss_context *ctx, 
-		      const unsigned char *buffer, 
-		      uint32_t buffer_size)
+static void fuzzy_try_fork_blockhash(struct fuzzy_state *self)
 {
-  uint32_t i;
-
-  if (NULL == ctx || NULL == buffer)
+  struct blockhash_context *obh, *nbh;
+  if (self->bhend >= NUM_BLOCKHASHES)
     return;
+  assert(self->bhend > 0);
+  obh = self->bh + (self->bhend - 1);
+  nbh = obh + 1;
+  nbh->h = obh->h;
+  nbh->halfh = obh->halfh;
+  nbh->digest[0] = '\0';
+  nbh->halfdigest = '\0';
+  nbh->dlen = 0;
+  ++self->bhend;
+}
 
-  for ( i = 0 ; i < buffer_size ; ++i)
-  {
-
-    // 
-    // at each character we update the rolling hash and
-    // the normal hash. When the rolling hash hits the
-    // reset value then we emit the normal hash as a
-    // element of the signature and reset both hashes
-    // 
-    ctx->h  = roll_hash(buffer[i]);
-    ctx->h2 = sum_hash(buffer[i], ctx->h2);
-    ctx->h3 = sum_hash(buffer[i], ctx->h3);
-    
-    if (ctx->h % ctx->block_size == (ctx->block_size-1)) {
-      // we have hit a reset point. We now emit a
-      // hash which is based on all chacaters in the
-      // piece of the message between the last reset
-      // point and this one 
-      ctx->p[ctx->j] = b64[ctx->h2 % 64];
-      if (ctx->j < SPAMSUM_LENGTH-1) {
-	// we can have a problem with the tail
-	// overflowing. The easiest way to
-	// cope with this is to only reset the
-	// second hash if we have room for
-	// more characters in our
-	// signature. This has the effect of
-	// combining the last few pieces of
-	// the message into a single piece 
-
-	ctx->h2 = HASH_INIT;
-	(ctx->j)++;
-      }
-    }
-    
-    // this produces a second signature with a block size
-    // of block_size*2. By producing dual signatures in
-    // this way the effect of small changes in the message
-    // size near a block size boundary is greatly reduced. 
-    if (ctx->h % (ctx->block_size*2) == ((ctx->block_size*2)-1)) {
-      ctx->ret2[ctx->k] = b64[ctx->h3 % 64];
-      if (ctx->k < SPAMSUM_LENGTH/2-1) {
-	ctx->h3 = HASH_INIT;
-	(ctx->k)++;
-      }
-    }
-  }
+static void fuzzy_try_reduce_blockhash(struct fuzzy_state *self)
+{
+  assert(self->bhstart < self->bhend);
+  if (self->bhend - self->bhstart < 2)
+    /* Need at least two working hashes. */
+    return;
+  if ((size_t)SSDEEP_BS(self->bhstart) * SPAMSUM_LENGTH >=
+      self->total_size)
+    /* Initial blocksize estimate would select this or a smaller
+     * blocksize. */
+    return;
+  if (self->bh[self->bhstart + 1].dlen < SPAMSUM_LENGTH / 2)
+    /* Estimate adjustment would select this blocksize. */
+    return;
+  /* At this point we are clearly no longer interested in the
+   * start_blocksize. Get rid of it. */
+  ++self->bhstart;
 }
 
-static int ss_update(ss_context *ctx, FILE *handle)
+static const char *b64 =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static void fuzzy_engine_step(struct fuzzy_state *self, unsigned char c)
 {
-  uint32_t bytes_read;
-  unsigned char *buffer; 
-
-  if (NULL == ctx || NULL == handle)
-    return TRUE;
-
-  buffer = (unsigned char *)malloc(sizeof(unsigned char) * BUFFER_SIZE);
-  if (buffer == NULL)
-    return TRUE;
-
-  snprintf(ctx->ret, 12, "%u:", ctx->block_size);
-  ctx->p = ctx->ret + strlen(ctx->ret);
-  
-  memset(ctx->p, 0, SPAMSUM_LENGTH+1);
-  memset(ctx->ret2, 0, sizeof(ctx->ret2));
-  
-  ctx->k  = ctx->j  = 0;
-  ctx->h3 = ctx->h2 = HASH_INIT;
-  ctx->h  = roll_reset();
-
-  while ((bytes_read = fread(buffer,sizeof(unsigned char),BUFFER_SIZE,handle)) > 0)
+  size_t h;
+  unsigned int i;
+  /* At each character we update the rolling hash and the normal hashes.
+   * When the rolling hash hits a reset value then we emit a normal hash
+   * as a element of the signature and reset the normal hash. */
+  roll_hash(&self->roll, c);
+  h = roll_sum(&self->roll);
+
+  for (i = self->bhstart; i < self->bhend; ++i)
   {
-    ss_engine(ctx,buffer,bytes_read);
+    self->bh[i].h = sum_hash(c, self->bh[i].h);
+    self->bh[i].halfh = sum_hash(c, self->bh[i].halfh);
   }
 
-  if (ctx->h != 0) 
+  for (i = self->bhstart; i < self->bhend; ++i)
   {
-    ctx->p[ctx->j] = b64[ctx->h2 % 64];
-    ctx->ret2[ctx->k] = b64[ctx->h3 % 64];
+    /* With growing blocksize almost no runs fail the next test. */
+    if (likely(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1))
+      /* Once this condition is false for one bs, it is
+       * automatically false for all further bs. I.e. if
+       * h === -1 (mod 2*bs) then h === -1 (mod bs). */
+      break;
+    /* We have hit a reset point. We now emit hashes which are
+     * based on all characters in the piece of the message between
+     * the last reset point and this one */
+    if (unlikely(0 == self->bh[i].dlen)) {
+      /* Can only happen 30 times. */
+      /* First step for this blocksize. Clone next. */
+      fuzzy_try_fork_blockhash(self);
+    }
+    self->bh[i].digest[self->bh[i].dlen] =
+      b64[self->bh[i].h % 64];
+    self->bh[i].halfdigest = b64[self->bh[i].halfh % 64];
+    if (self->bh[i].dlen < SPAMSUM_LENGTH - 1) {
+      /* We can have a problem with the tail overflowing. The
+       * easiest way to cope with this is to only reset the
+       * normal hash if we have room for more characters in
+       * our signature. This has the effect of combining the
+       * last few pieces of the message into a single piece
+       * */
+      self->bh[i].digest[++(self->bh[i].dlen)] = '\0';
+      self->bh[i].h = HASH_INIT;
+      if (self->bh[i].dlen < SPAMSUM_LENGTH / 2) {
+	self->bh[i].halfh = HASH_INIT;
+	self->bh[i].halfdigest = '\0';
+      }
+    } else
+      fuzzy_try_reduce_blockhash(self);
   }
-  
-  strcat(ctx->p+ctx->j, ":");
-  strcat(ctx->p+ctx->j, ctx->ret2);
-
-  free(buffer);
-  return FALSE;
 }
 
+int fuzzy_update(struct fuzzy_state *self,
+		 const unsigned char *buffer,
+		 size_t buffer_size) {
+  self->total_size += buffer_size;
+  for ( ;buffer_size > 0; ++buffer, --buffer_size)
+    fuzzy_engine_step(self, *buffer);
+  return 0;
+}
 
-int fuzzy_hash_file(FILE *handle,
-		    char *result)
+static int memcpy_eliminate_sequences(char *dst,
+				      const char *src,
+				      int n)
 {
-  ss_context *ctx;  
-  uint64_t filepos;
-  int done = FALSE;
-  
-  if (NULL == handle || NULL == result)
-    return TRUE;
-  
-  ctx = (ss_context *)malloc(sizeof(ss_context));
-  if (ctx == NULL)
-    return TRUE;
-
-  filepos = ftello(handle);
-
-  ss_init(ctx, handle);
-
-  while (!done)
-  {
-    if (fseeko(handle,0,SEEK_SET))
-      return TRUE;
+  const char *srcend = src + n;
+  assert(n >= 0);
+  if (src < srcend) *dst++ = *src++;
+  if (src < srcend) *dst++ = *src++;
+  if (src < srcend) *dst++ = *src++;
+  while (src < srcend)
+    if (*src == dst[-1] && *src == dst[-2] && *src == dst[-3])
+    {
+      ++src;
+      --n;
+    } else
+      *dst++ = *src++;
+  return n;
+}
 
-    ss_update(ctx,handle);
+#ifdef S_SPLINT_S
+extern const int EOVERFLOW;
+#endif
 
-    // our blocksize guess may have been way off - repeat if necessary
-    if (ctx->block_size > MIN_BLOCKSIZE && ctx->j < SPAMSUM_LENGTH/2) 
-      ctx->block_size = ctx->block_size / 2;
-    else
-      done = TRUE;
+int fuzzy_digest(const struct fuzzy_state *self,
+		 /*@out@*/ char *result,
+		 unsigned int flags)
+{
+  unsigned int bi = self->bhstart;
+  uint32_t h = roll_sum(&self->roll);
+  int i, remain = FUZZY_MAX_RESULT - 1; /* Exclude terminating '\0'. */
+  /* Verify that our elimination was not overeager. */
+  assert(bi == 0 || (size_t)SSDEEP_BS(bi) / 2 * SPAMSUM_LENGTH <
+	 self->total_size);
+
+  /* Initial blocksize guess. */
+  while ((size_t)SSDEEP_BS(bi) * SPAMSUM_LENGTH < self->total_size) {
+    ++bi;
+    if (bi >= NUM_BLOCKHASHES) {
+      /* The input exceeds data types. */
+      errno = EOVERFLOW;
+      return -1;
+    }
   }
-
-  strncpy(result,ctx->ret,FUZZY_MAX_RESULT);
-
-  ss_destroy(ctx);
-  free(ctx);
-
-  if (fseeko(handle,filepos,SEEK_SET))
-    return TRUE;
-
-  return FALSE;
+  /* Adapt blocksize guess to actual digest length. */
+  while (bi >= self->bhend)
+    --bi;
+  while (bi > self->bhstart && self->bh[bi].dlen < SPAMSUM_LENGTH / 2)
+    --bi;
+  assert (!(bi > 0 && self->bh[bi].dlen < SPAMSUM_LENGTH / 2));
+
+  i = snprintf(result, (size_t)remain, "%u:", SSDEEP_BS(bi));
+  if (i <= 0)
+    /* Maybe snprintf has set errno here? */
+    return -1;
+  assert(i < remain);
+  remain -= i;
+  result += i;
+  i = (int)self->bh[bi].dlen;
+  assert(i <= remain);
+  if ((flags & FUZZY_FLAG_ELIMSEQ) != 0)
+    i = memcpy_eliminate_sequences(result, self->bh[bi].digest, i);
+  else
+    memcpy(result, self->bh[bi].digest, (size_t)i);
+  result += i;
+  remain -= i;
+  if (h != 0)
+  {
+    assert(remain > 0);
+    *result = b64[self->bh[bi].h % 64];
+    if((flags & FUZZY_FLAG_ELIMSEQ) == 0 || i < 3 ||
+       *result != result[-1] ||
+       *result != result[-2] ||
+       *result != result[-3]) {
+      ++result;
+      --remain;
+    }
+  } else if (self->bh[bi].digest[i] != '\0') {
+    assert(remain > 0);
+    *result = self->bh[bi].digest[i];
+    if((flags & FUZZY_FLAG_ELIMSEQ) == 0 || i < 3 ||
+       *result != result[-1] ||
+       *result != result[-2] ||
+       *result != result[-3]) {
+      ++result;
+      --remain;
+    }
+  }
+  assert(remain > 0);
+  *result++ = ':';
+  --remain;
+  if (bi < self->bhend - 1)
+  {
+    ++bi;
+    i = (int)self->bh[bi].dlen;
+    if ((flags & FUZZY_FLAG_NOTRUNC) == 0 &&
+	i > SPAMSUM_LENGTH / 2 - 1)
+      i = SPAMSUM_LENGTH / 2 - 1;
+    assert(i <= remain);
+    if ((flags & FUZZY_FLAG_ELIMSEQ) != 0)
+      i = memcpy_eliminate_sequences(result,
+				     self->bh[bi].digest, i);
+    else
+      memcpy(result, self->bh[bi].digest, (size_t)i);
+    result += i;
+    remain -= i;
+    if (h != 0) {
+      assert(remain > 0);
+      h = (flags & FUZZY_FLAG_NOTRUNC) != 0 ? self->bh[bi].h :
+	self->bh[bi].halfh;
+      *result = b64[h % 64];
+      if ((flags & FUZZY_FLAG_ELIMSEQ) == 0 || i < 3 ||
+	  *result != result[-1] ||
+	  *result != result[-2] ||
+	  *result != result[-3])
+      {
+	++result;
+	--remain;
+      }
+    } else {
+      i = (flags & FUZZY_FLAG_NOTRUNC) != 0 ?
+        self->bh[bi].digest[self->bh[bi].dlen] : self->bh[bi].halfdigest;
+      if (i != '\0') {
+	assert(remain > 0);
+	*result = i;
+	if ((flags & FUZZY_FLAG_ELIMSEQ) == 0 || i < 3 ||
+	    *result != result[-1] ||
+	    *result != result[-2] ||
+	    *result != result[-3])
+	{
+	  ++result;
+	  --remain;
+	}
+      }
+    }
+  } else if (h != 0)
+    {
+      assert(self->bh[bi].dlen == 0);
+      assert(remain > 0);
+      *result++ = b64[self->bh[bi].h % 64];
+      /* No need to bother with FUZZY_FLAG_ELIMSEQ, because this
+       * digest has length 1. */
+      --remain;
+    }
+  *result = '\0';
+  return 0;
 }
 
-
-extern int fuzzy_hash_filename(const char * filename,
-			       char * result)
+void fuzzy_free(/*@only@*/ struct fuzzy_state *self)
 {
-  int status;
-
-  if (NULL == filename || NULL == result)
-    return TRUE;
-
-  FILE * handle = fopen(filename,"rb");
-  if (NULL == handle)
-    return TRUE;
-
-  status = fuzzy_hash_file(handle,result);
-  
-  fclose(handle);
-
-  return status;
+  free(self);
 }
 
-
 int fuzzy_hash_buf(const unsigned char *buf,
-		   uint32_t      buf_len,
-		   char          *result)
+		   uint32_t buf_len,
+		   /*@out@*/ char *result)
 {
-  ss_context *ctx;
-  int done = FALSE;
-
-  if (NULL == buf || NULL == result)
-    return TRUE;
-
-  ctx = (ss_context *)malloc(sizeof(ss_context));  
-  if (ctx == NULL)
-    return TRUE;
-
-  ctx->total_chars = buf_len;
-  ss_init(ctx, NULL);
-
+  struct fuzzy_state *ctx;
+  int ret = -1;
+  if (NULL == (ctx = fuzzy_new()))
+    return -1;
+  if (fuzzy_update(ctx, buf, buf_len) < 0)
+    goto out;
+  if (fuzzy_digest(ctx, result, 0) < 0)
+    goto out;
+  ret = 0;
+ out:
+  fuzzy_free(ctx);
+  return ret;
+}
 
-  while (!done)
+int fuzzy_hash_stream(FILE *handle, /*@out@*/ char *result)
+{
+  struct fuzzy_state *ctx;
+  unsigned char buffer[4096];
+  size_t n;
+  int ret = -1;
+  if (NULL == (ctx = fuzzy_new()))
+    return -1;
+  for(;;)
   {
-    snprintf(ctx->ret, 12, "%u:", ctx->block_size);
-    ctx->p = ctx->ret + strlen(ctx->ret);
-    
-    memset(ctx->p, 0, SPAMSUM_LENGTH+1);
-    memset(ctx->ret2, 0, sizeof(ctx->ret2));
-    
-    ctx->k  = ctx->j  = 0;
-    ctx->h3 = ctx->h2 = HASH_INIT;
-    ctx->h  = roll_reset();
-
-    ss_engine(ctx,buf,buf_len);
-
-    // our blocksize guess may have been way off - repeat if necessary 
-    if (ctx->block_size > MIN_BLOCKSIZE && ctx->j < SPAMSUM_LENGTH/2) 
-      ctx->block_size = ctx->block_size / 2;
-    else
-      done = TRUE;
-
-    if (ctx->h != 0) 
-      {
-	ctx->p[ctx->j] = b64[ctx->h2 % 64];
-	ctx->ret2[ctx->k] = b64[ctx->h3 % 64];
-      }
-    
-    strcat(ctx->p+ctx->j, ":");
-    strcat(ctx->p+ctx->j, ctx->ret2);
+    n = fread(buffer, 1, 4096, handle);
+    if (0 == n)
+      break;
+    if (fuzzy_update(ctx, buffer, n) < 0)
+      goto out;
   }
-
-
-  strncpy(result,ctx->ret,FUZZY_MAX_RESULT);
-
-  ss_destroy(ctx);
-  free(ctx);
-  return FALSE;
+  if (ferror(handle) != 0)
+    goto out;
+  if (fuzzy_digest(ctx, result, 0) < 0)
+    goto out;
+  ret = 0;
+ out:
+  fuzzy_free(ctx);
+  return ret;
 }
 
+#ifdef S_SPLINT_S
+typedef size_t off_t;
+int fseeko(FILE *, off_t, int);
+off_t ftello(FILE *);
+#endif
 
+int fuzzy_hash_file(FILE *handle, /*@out@*/ char *result)
+{
+  off_t fpos;
+  int status;
+  fpos = ftello(handle);
+  if (fseek(handle, 0, SEEK_SET) < 0)
+    return -1;
+  status = fuzzy_hash_stream(handle, result);
+  if (status == 0)
+  {
+    if (fseeko(handle, fpos, SEEK_SET) < 0)
+      return -1;
+  }
+  return status;
+}
 
+int fuzzy_hash_filename(const char *filename, /*@out@*/ char *result)
+{
+  int status;
+  FILE *handle = fopen(filename, "rb");
+  if (NULL == handle)
+    return -1;
+  status = fuzzy_hash_stream(handle, result);
+  /* We cannot do anything about an fclose failure. */
+  (void)fclose(handle);
+  return status;
+}
 
 //
 // We only accept a match if we have at least one common substring in
@@ -385,48 +496,53 @@ static int has_common_substring(const char *s1, const char *s2)
   int i, j;
   int num_hashes;
   uint32_t hashes[SPAMSUM_LENGTH];
-  
+
   // there are many possible algorithms for common substring
   // detection. In this case I am re-using the rolling hash code
-  // to act as a filter for possible substring matches 
-  
-  roll_reset();
+  // to act as a filter for possible substring matches
+
   memset(hashes, 0, sizeof(hashes));
-  
+
   // first compute the windowed rolling hash at each offset in
-  // the first string 
-  for (i=0;s1[i];i++) 
+  // the first string
+  struct roll_state state;
+  roll_init (&state);
+
+  for (i=0;s1[i];i++)
   {
-    hashes[i] = roll_hash((unsigned char)s1[i]);
+    roll_hash(&state, (unsigned char)s1[i]);
+    hashes[i] = roll_sum(&state);
   }
   num_hashes = i;
-  
-  roll_reset();
-  
+
+  roll_init(&state);
+
   // now for each offset in the second string compute the
   // rolling hash and compare it to all of the rolling hashes
   // for the first string. If one matches then we have a
   // candidate substring match. We then confirm that match with
   // a direct string comparison */
-  for (i=0;s2[i];i++) {
-    uint32_t h = roll_hash((unsigned char)s2[i]);
+  for (i=0;s2[i];i++)
+  {
+    roll_hash(&state, (unsigned char)s2[i]);
+    uint32_t h = roll_sum(&state);
     if (i < ROLLING_WINDOW-1) continue;
-    for (j=ROLLING_WINDOW-1;j<num_hashes;j++) 
+    for (j=ROLLING_WINDOW-1;j<num_hashes;j++)
     {
-      if (hashes[j] != 0 && hashes[j] == h) 
+      if (hashes[j] != 0 && hashes[j] == h)
       {
-	// we have a potential match - confirm it 
-	if (strlen(s2+i-(ROLLING_WINDOW-1)) >= ROLLING_WINDOW && 
-	    strncmp(s2+i-(ROLLING_WINDOW-1), 
-		    s1+j-(ROLLING_WINDOW-1), 
-		    ROLLING_WINDOW) == 0) 
+	// we have a potential match - confirm it
+	if (strlen(s2+i-(ROLLING_WINDOW-1)) >= ROLLING_WINDOW &&
+	    strncmp(s2+i-(ROLLING_WINDOW-1),
+		    s1+j-(ROLLING_WINDOW-1),
+		    ROLLING_WINDOW) == 0)
 	{
 	  return 1;
 	}
       }
     }
   }
-  
+
   return 0;
 }
 
@@ -438,25 +554,27 @@ static char *eliminate_sequences(const char *str)
 {
   char *ret;
   size_t i, j, len;
-  
+
   ret = strdup(str);
-  if (!ret) 
+  if (!ret)
     return NULL;
-  
+
   len = strlen(str);
-  
-  for (i=j=3 ; i<len ; i++) 
+  if (len < 3)
+    return ret;
+
+  for (i=j=3 ; i<len ; i++)
   {
     if (str[i] != str[i-1] ||
 	str[i] != str[i-2] ||
-	str[i] != str[i-3]) 
+	str[i] != str[i-3])
     {
       ret[j++] = str[i];
     }
   }
-  
+
   ret[j] = 0;
-  
+
   return ret;
 }
 
@@ -466,66 +584,67 @@ static char *eliminate_sequences(const char *str)
 // 100 is a great match. The block_size is used to cope with very small
 // messages.
 //
-static uint32_t score_strings(const char *s1, 
-			      const char *s2, 
+static uint32_t score_strings(const char *s1,
+			      const char *s2,
 			      unsigned int block_size)
 {
   uint32_t score;
   size_t len1, len2;
   int edit_distn(const char *from, int from_len, const char *to, int to_len);
-  
+
   len1 = strlen(s1);
   len2 = strlen(s2);
-  
+
   if (len1 > SPAMSUM_LENGTH || len2 > SPAMSUM_LENGTH) {
-    // not a real spamsum signature? 
+    // not a real spamsum signature?
     return 0;
   }
-  
+
   // the two strings must have a common substring of length
-  // ROLLING_WINDOW to be candidates 
+  // ROLLING_WINDOW to be candidates
   if (has_common_substring(s1, s2) == 0) {
     return 0;
   }
-  
+
   // compute the edit distance between the two strings. The edit distance gives
-  // us a pretty good idea of how closely related the two strings are 
+  // us a pretty good idea of how closely related the two strings are
   score = edit_distn(s1, len1, s2, len2);
- 
+
   // scale the edit distance by the lengths of the two
   // strings. This changes the score to be a measure of the
   // proportion of the message that has changed rather than an
   // absolute quantity. It also copes with the variability of
-  // the string lengths. 
+  // the string lengths.
   score = (score * SPAMSUM_LENGTH) / (len1 + len2);
-  
+
   // at this stage the score occurs roughly on a 0-64 scale,
   // with 0 being a good match and 64 being a complete
   // mismatch
-  
-  // rescale to a 0-100 scale (friendlier to humans) 
+
+  // rescale to a 0-100 scale (friendlier to humans)
   score = (100 * score) / 64;
-  
+
   // it is possible to get a score above 100 here, but it is a
-  // really terrible match 
-  if (score >= 100) 
+  // really terrible match
+  if (score >= 100)
     return 0;
-  
+
   // now re-scale on a 0-100 scale with 0 being a poor match and
   // 100 being a excellent match.
   score = 100 - score;
 
   //  printf ("len1: %"PRIu32"  len2: %"PRIu32"\n", len1, len2);
-  
-  // when the blocksize is small we don't want to exaggerate the match size 
-  if (score > block_size/MIN_BLOCKSIZE * MIN(len1, len2)) {
+
+  // when the blocksize is small we don't want to exaggerate the match size
+  if (score > block_size/MIN_BLOCKSIZE * MIN(len1, len2))
+  {
     score = block_size/MIN_BLOCKSIZE * MIN(len1, len2);
   }
   return score;
 }
 
 //
-// Given two spamsum strings return a value indicating the degree 
+// Given two spamsum strings return a value indicating the degree
 // to which they match.
 //
 int fuzzy_compare(const char *str1, const char *str2)
@@ -535,7 +654,7 @@ int fuzzy_compare(const char *str1, const char *str2)
   char *s1, *s2;
   char *s1_1, *s1_2, *s1_3;
   char *s2_1, *s2_2, *s2_3;
-  
+
   if (NULL == str1 || NULL == str2)
     return -1;
 
@@ -544,45 +663,49 @@ int fuzzy_compare(const char *str1, const char *str2)
       sscanf(str2, "%u:", &block_size2) != 1) {
     return -1;
   }
-  
+
   // if the blocksizes don't match then we are comparing
   // apples to oranges. This isn't an 'error' per se. We could
-  // have two valid signatures, but they can't be compared. 
-  if (block_size1 != block_size2 && 
+  // have two valid signatures, but they can't be compared.
+  if (block_size1 != block_size2 &&
       block_size1 != block_size2*2 &&
       block_size2 != block_size1*2) {
     return 0;
   }
-  
+
   // move past the prefix
   str1 = strchr(str1, ':');
   str2 = strchr(str2, ':');
-  
+
   if (!str1 || !str2) {
-    // badly formed ... 
+    // badly formed ...
     return -1;
   }
-  
+
   // there is very little information content is sequences of
   // the same character like 'LLLLL'. Eliminate any sequences
   // longer than 3. This is especially important when combined
-  // with the has_common_substring() test below. 
+  // with the has_common_substring() test below.
   // NOTE: This function duplciates str1 and str2
   s1 = eliminate_sequences(str1+1);
+  if (!s1)
+    return 0;
   s2 = eliminate_sequences(str2+1);
-  
-  if (!s1 || !s2) 
+  if (!s2)
+  {
+    free(s1);
     return 0;
-  
-  // now break them into the two pieces 
+  }
+
+  // now break them into the two pieces
   s1_1 = s1;
   s2_1 = s2;
-  
+
   s1_2 = strchr(s1, ':');
   s2_2 = strchr(s2, ':');
 
   if (!s1_2 || !s2_2) {
-    // a signature is malformed - it doesn't have 2 parts 
+    // a signature is malformed - it doesn't have 2 parts
     free(s1); free(s2);
     return -1;
   }
@@ -606,28 +729,35 @@ int fuzzy_compare(const char *str1, const char *str2)
     *s1_3 = 0;
   if (s2_3 != NULL)
     *s2_3 = 0;
-  
+
+  // Now that we know the strings are both well formed, are they
+  // identical? We could save ourselves some work here
+  if (strlen(s1) == strlen(s2)) {
+    if (!strncmp(s1, s2, strlen(s1))) {
+      free (s1);
+      free (s2);
+      return 100;
+    }
+  }
+
   // each signature has a string for two block sizes. We now
   // choose how to combine the two block sizes. We checked above
-  // that they have at least one block size in common 
-  if (block_size1 == block_size2) 
-  {
+  // that they have at least one block size in common
+  if (block_size1 == block_size2) {
     uint32_t score1, score2;
     score1 = score_strings(s1_1, s2_1, block_size1);
-    score2 = score_strings(s1_2, s2_2, block_size2);
+    score2 = score_strings(s1_2, s2_2, block_size1*2);
     score = MAX(score1, score2);
-  } 
-  else if (block_size1 == block_size2*2) 
-  {
+  }
+  else if (block_size1 == block_size2*2) {
     score = score_strings(s1_1, s2_2, block_size1);
-  } 
-  else 
-  {
+  }
+  else {
     score = score_strings(s1_2, s2_1, block_size2);
   }
-  
+
   free(s1);
   free(s2);
-  
+
   return (int)score;
 }
diff --git a/fuzzy.h b/fuzzy.h
index 9068fb5..cd387d3 100644
--- a/fuzzy.h
+++ b/fuzzy.h
@@ -1,117 +1,212 @@
-#ifndef __FUZZY_H
-# define __FUZZY_H
-
-// Fuzzy Hashing by Jesse Kornblum
-// Copyright (C) Kyrus 2012
-//
-// $Id: fuzzy.h 147 2012-05-25 12:14:50Z jessekornblum $ 
-
-/// @mainpage
+#ifndef FUZZY_H
+#define FUZZY_H
+
+/*
+ * Copyright (C) ManTech International Corporation 2010
+ * Copyright (C) Kyrus 2012
+ * Copyright (C) 2013 Helmut Grohne <helmut at subdivi.de>
+ *
+ * $Id: fuzzy.h 202 2013-11-07 20:15:06Z jessekornblum $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Earlier versions of this code can be found at:
+ *     http://ssdeep.sf.net/
+ */
+
+/// \mainpage
 /// This is the documentation for the fuzzy hashing API from ssdeep.
 ///
 /// There is a complete function reference in fuzzy.h.
 ///
 /// The most recent version of this documentation can be found
-/// at http://ssdeep.sourceforge.net/. 
+/// at http://ssdeep.sourceforge.net/.
 ///
-/// @copydoc fuzzy.h
+/// \copydoc fuzzy.h
 ///
-/// @version 2.8
-/// @date 25 May 2012
+/// \version 3.0
 ///
-/// @author Jesse Kornblum, research at jessekornblum.com. 
+/// \author Jesse Kornblum, research at jessekornblum.com
+/// \author Helmut Grohne, helmut at subdivi.de
 
-/// @file fuzzy.h
-/// @brief
+/// \file fuzzy.h
+/// \brief
 /// These functions allow a programmer to compute the fuzzy hashes
-/// (also called the context-triggered piecewise hashes) of 
-/// @link fuzzy_hash_buf() a buffer
-/// of text @endlink, 
-/// @link fuzzy_hash_filename() the contents of a file on the disk @endlink, 
-/// and 
+/// (also called the context-triggered piecewise hashes) of
+/// \link fuzzy_hash_buf() a buffer
+/// of text @endlink,
+/// \link fuzzy_hash_filename() the contents of a file on the disk @endlink,
+/// and
 /// @link fuzzy_hash_file() the contents of
-/// an open file handle @endlink . 
-/// There is also a function to 
+/// an open file handle @endlink .
+/// There is also a function to
 /// @link fuzzy_compare() compute the
 /// similarity between any two fuzzy signatures @endlink.
 
+
+#include <stdint.h>
+#include <stdio.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifndef _INTTYPES_H_
-# include <inttypes.h>
-#endif
-
-
-
-/// @brief Compute the fuzzy hash of a buffer
-///
-/// The computes the fuzzy hash of the first buf_len bytes of the buffer.
-/// It is the caller's responsibility to append the filename,
-/// if any, to result after computation. 
-/// @param buf The data to be fuzzy hashed
-/// @param buf_len The length of the data being hashed
-/// @param result Where the fuzzy hash of buf is stored. This variable
-/// must be allocated to hold at least FUZZY_MAX_RESULT bytes.
-/// @return Returns zero on success, non-zero on error.
+/**
+ * @brief fuzzy_digest flag indicating to eliminate sequences of more than
+ *        three identical characters
+ */
+#define FUZZY_FLAG_ELIMSEQ 0x1u
+/**
+ * @brief fuzzy_digest flag indicating not to truncate the second part to
+ *        SPAMSUM_LENGTH/2 characters.
+ */
+#define FUZZY_FLAG_NOTRUNC 0x2u
+
+struct fuzzy_state;
+
+/**
+ * @brief Construct a fuzzy_state object and return it.
+ *
+ * To use it call fuzzy_update and fuzzy_digest on it. It must be disposed
+ * with fuzzy_free.
+ * @return the constructed fuzzy_state or NULL on failure
+ */
+extern /*@only@*/ /*@null@*/ struct fuzzy_state *fuzzy_new(void);
+
+/**
+ * @brief Create a copy of a fuzzy_state object and return it.
+ *
+ * It can be used with fuzzy_update and fuzzy_digest independently of
+ * the original. It must be disposed with fuzzy_free like the original
+ * has to be cleared in this way.
+ * @return the cloned fuzzy_state or NULL on failure
+ */
+extern /*@only@*/ /*@null@*/ struct fuzzy_state *fuzzy_clone(const struct fuzzy_state *state);
+
+/**
+ * @brief Feed the data contained in the given buffer to the state.
+ *
+ * When an error occurs, the state is undefined. In that case it must not be
+ * passed to any function besides fuzzy_free.
+ * @param buffer The data to be hashes
+ * @param buffer_size The length of the given buffer
+ * @return zero on success, non-zero on error
+ */
+extern int fuzzy_update(struct fuzzy_state *state,
+			const unsigned char *buffer,
+			size_t buffer_size);
+
+/**
+ * @brief Obtain the fuzzy hash from the state.
+ *
+ * This operation does not change the state at all. It reports the hash for the
+ * concatenation of the data previously fed using fuzzy_update.
+ * @param result Where the fuzzy hash is stored. This variable
+ * must be allocated to hold at least FUZZY_MAX_RESULT bytes.
+ * @param flags is a bitwise or of FUZZY_FLAG_* macros. The absence of flags is
+ * represented by a zero.
+ * @return zero on success, non-zero on error
+ */
+extern int fuzzy_digest(const struct fuzzy_state *state,
+			/*@out@*/ char *result,
+			unsigned int flags);
+
+/**
+ * @brief Dispose a fuzzy state.
+ */
+extern void fuzzy_free(/*@only@*/ struct fuzzy_state *state);
+
+/**
+ * @brief Compute the fuzzy hash of a buffer
+ *
+ * The computes the fuzzy hash of the first buf_len bytes of the buffer.
+ * It is the caller's responsibility to append the filename,
+ * if any, to result after computation.
+ * @param buf The data to be fuzzy hashed
+ * @param buf_len The length of the data being hashed
+ * @param result Where the fuzzy hash of buf is stored. This variable
+ * must be allocated to hold at least FUZZY_MAX_RESULT bytes.
+ * @return Returns zero on success, non-zero on error.
+ */
 extern int fuzzy_hash_buf(const unsigned char *buf,
-			  uint32_t      buf_len,
-			  char          *result);
-
-
-/// @brief Compute the fuzzy hash of a file using an open handle
-///
-/// Computes the fuzzy hash of the contents of the open file, starting
-/// at the beginning of the file. When finished, the file pointer is
-/// returned to its original position. If an error occurs, the file 
-/// pointer's value is undefined.
-/// It is the callers's responsibility to append the filename
-/// to the result after computation.
-/// @param handle Open handle to the file to be hashed
-/// @param result Where the fuzzy hash of the file is stored. This 
-/// variable must be allocated to hold at least FUZZY_MAX_RESULT bytes.
-/// @return Returns zero on success, non-zero on error
-extern int fuzzy_hash_file(FILE *handle,
-			   char *result);
-
-
-/// @brief Compute the fuzzy hash of a file
-///
-/// Opens, reads, and hashes the contents of the file 'filename' 
-/// The result must be allocated to hold FUZZY_MAX_RESULT characters. 
-/// It is the caller's responsibility to append the filename
-/// to the result after computation. 
-/// @param filename The file to be hashed
-/// @param result Where the fuzzy hash of the file is stored. This 
-/// variable must be allocated to hold at least FUZZY_MAX_RESULT bytes.
-/// @return Returns zero on success, non-zero on error. 
-extern int fuzzy_hash_filename(const char * filename,
-			       char * result);
-
-
+			  uint32_t buf_len,
+			  /*@out@*/ char *result);
+
+/**
+ * @brief Compute the fuzzy hash of a file using an open handle
+ *
+ * Computes the fuzzy hash of the contents of the open file, starting
+ * at the beginning of the file. When finished, the file pointer is
+ * returned to its original position. If an error occurs, the file
+ * pointer's value is undefined.
+ * It is the callers's responsibility to append the filename
+ * to the result after computation.
+ * @param handle Open handle to the file to be hashed
+ * @param result Where the fuzzy hash of the file is stored. This
+ * variable must be allocated to hold at least FUZZY_MAX_RESULT bytes.
+ * @return Returns zero on success, non-zero on error
+ */
+extern int fuzzy_hash_file(FILE *handle, /*@out@*/ char *result);
+
+/**
+ * @brief Compute the fuzzy hash of a stream using an open handle
+ *
+ * Computes the fuzzy hash of the contents of the open stream, starting at the
+ * current file position until reaching EOF. Unlike fuzzy_hash_file the stream
+ * is never seeked. If an error occurs, the result as well as the file position
+ * are undefined.
+ * It is the callers's responsibility to append the filename
+ * to the result after computation.
+ * @param handle Open handle to the stream to be hashed
+ * @param result Where the fuzzy hash of the file is stored. This
+ * variable must be allocated to hold at least FUZZY_MAX_RESULT bytes.
+ * @return Returns zero on success, non-zero on error
+ */
+extern int fuzzy_hash_stream(FILE *handle, /*@out@*/ char *result);
+
+/**
+ * @brief Compute the fuzzy hash of a file
+ *
+ * Opens, reads, and hashes the contents of the file 'filename'
+ * The result must be allocated to hold FUZZY_MAX_RESULT characters.
+ * It is the caller's responsibility to append the filename
+ * to the result after computation.
+ * @param filename The file to be hashed
+ * @param result Where the fuzzy hash of the file is stored. This
+ * variable must be allocated to hold at least FUZZY_MAX_RESULT bytes.
+ * @return Returns zero on success, non-zero on error.
+ */
+extern int fuzzy_hash_filename(const char *filename, /*@out@*/ char * result);
 
 /// Computes the match score between two fuzzy hash signatures.
 /// @return Returns a value from zero to 100 indicating the
-/// match score of the 
+/// match score of the
 /// two signatures. A match score of zero indicates the sigantures
 /// did not match. When an error occurs, such as if one of the
 /// inputs is NULL, returns -1.
 extern int fuzzy_compare(const char *sig1, const char *sig2);
 
-
-
-/// The longest possible length for a fuzzy hash signature (without the filename)
-#define FUZZY_MAX_RESULT    (SPAMSUM_LENGTH + (SPAMSUM_LENGTH/2 + 20))
-
-/// Length of an individual fuzzy hash signature component
+/** Length of an individual fuzzy hash signature component. */
 #define SPAMSUM_LENGTH 64
 
+/** The longest possible length for a fuzzy hash signature
+ * (without the filename) */
+#define FUZZY_MAX_RESULT (2 * SPAMSUM_LENGTH + 20)
 
-// To end our 'extern "C" {'
 #ifdef __cplusplus
-} 
+}
 #endif
 
-
-#endif   // ifndef __FUZZY_H
+#endif
diff --git a/helpers.cpp b/helpers.cpp
index 7f469a0..00ab518 100644
--- a/helpers.cpp
+++ b/helpers.cpp
@@ -2,7 +2,7 @@
 // Copyright (C) 2012 Kyrus
 // Copyright (C) 2006 ManTech International Corporation
 //
-// $Id: helpers.cpp 144 2012-04-24 14:59:33Z jessekornblum $
+// $Id: helpers.cpp 184 2013-07-10 05:24:26Z jessekornblum $
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -27,6 +27,14 @@ void try_msg(void)
 }
 
 
+bool expanded_path(TCHAR *p)
+{
+  if (_tcsncmp(p,_TEXT("\\\\?\\"),4))
+    return false;
+  return true;
+}
+
+
 void sanity_check(state *s, int condition, const char *msg)
 {
   if (NULL == s)
diff --git a/main.cpp b/main.cpp
index db3f109..3ad57f6 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,8 +1,9 @@
 // Fuzzy Hashing by Jesse Kornblum
+// Copyright (C) 2013 Facebook
 // Copyright (C) 2012 Kyrus
 // Copyright (C) 2010 ManTech International Corporation
 //
-// $Id: main.cpp 165 2012-07-23 16:18:18Z jessekornblum $
+// $Id: main.cpp 210 2014-05-08 23:04:56Z jessekornblum $
 //
 // This program is licensed under version 2 of the GNU Public License.
 // See the file COPYING for details. 
@@ -39,7 +40,7 @@ static bool initialize_state(state *s)
 static void usage(void)
 {
   print_status ("%s version %s by Jesse Kornblum", __progname, VERSION);
-  print_status ("Copyright (C) 2012 Kyrus");
+  print_status ("Copyright (C) 2014 Facebook");
   print_status ("");
   print_status ("Usage: %s [-m file] [-k file] [-dpgvrsblcxa] [-t val] [-h|-V] [FILES]", 
 	  __progname);
@@ -207,45 +208,42 @@ static int prepare_windows_command_line(state *s)
 #endif
 
 
-
 static int is_absolute_path(TCHAR *fn)
 {
   if (NULL == fn)
     internal_error("Unknown error in is_absolute_path");
   
 #ifdef _WIN32
-  return FALSE;
-#endif
-
+  return (isalpha(fn[0]) and _TEXT(':') == fn[1]);
+# else
   return (DIR_SEPARATOR == fn[0]);
+#endif
 }
 
 
-
 static void generate_filename(state *s, TCHAR *fn, TCHAR *cwd, TCHAR *input)
 {
   if (NULL == fn || NULL == input)
     internal_error("Error calling generate_filename");
 
   if ((s->mode & mode_relative) || is_absolute_path(input))
-    _tcsncpy(fn,input,PATH_MAX);
-  else
-    {
-      // Windows systems don't have symbolic links, so we don't
-      // have to worry about carefully preserving the paths
-      // they follow. Just use the system command to resolve the paths
+    _tcsncpy(fn, input, SSDEEP_PATH_MAX);
+  else {
+    // Windows systems don't have symbolic links, so we don't
+    // have to worry about carefully preserving the paths
+    // they follow. Just use the system command to resolve the paths
 #ifdef _WIN32
-      _wfullpath(fn,input,PATH_MAX);
+    _wfullpath(fn, input, SSDEEP_PATH_MAX);
 #else     
-      if (NULL == cwd)
-	// If we can't get the current working directory, we're not
-	// going to be able to build the relative path to this file anyway.
-	// So we just call realpath and make the best of things
-	realpath(input,fn);
-      else
-	snprintf(fn,PATH_MAX,"%s%c%s",cwd,DIR_SEPARATOR,input);
+    if (NULL == cwd)
+      // If we can't get the current working directory, we're not
+      // going to be able to build the relative path to this file anyway.
+      // So we just call realpath and make the best of things
+      realpath(input, fn);
+    else
+      snprintf(fn, SSDEEP_PATH_MAX, "%s%c%s", cwd, DIR_SEPARATOR, input);
 #endif
-    }
+  }
 }
 
 
@@ -276,16 +274,14 @@ int main(int argc, char **argv)
   // Anything left on the command line at this point is a file
   // or directory we're supposed to process. If there's nothing
   // specified, we should tackle standard input 
-  if (optind == argc)
-  {
+  if (optind == argc) {
     status = process_stdin(s);
   }
-  else
-  {
-    MD5DEEP_ALLOC(TCHAR,fn,PATH_MAX);
-    MD5DEEP_ALLOC(TCHAR,cwd,PATH_MAX);
+  else {
+    MD5DEEP_ALLOC(TCHAR, fn, SSDEEP_PATH_MAX);
+    MD5DEEP_ALLOC(TCHAR, cwd, SSDEEP_PATH_MAX);
     
-    cwd = _tgetcwd(cwd,PATH_MAX);
+    cwd = _tgetcwd(cwd, SSDEEP_PATH_MAX);
     if (NULL == cwd)
       fatal_error("%s: %s", __progname, strerror(errno));
   
@@ -296,8 +292,7 @@ int main(int argc, char **argv)
     // on it on Win32 (i.e. where it matters). The setting of 'goal'
     // to the original argc occured at the start of main(), so we just
     // need to update it if we're *not* in signature compare mode.
-    if (not (s->mode & mode_sigcompare))
-    {
+    if (not (s->mode & mode_sigcompare)) {
       goal = s->argc;
     }
     
@@ -307,14 +302,13 @@ int main(int argc, char **argv)
 	match_load(s,argv[count]);
       else if (MODE(mode_compare_unknown))
 	match_compare_unknown(s,argv[count]);
-      else
-      {
-	generate_filename(s,fn,cwd,s->argv[count]);
-
+      else {
+	generate_filename(s, fn, cwd, s->argv[count]);
+	
 #ifdef _WIN32
-	status = process_win32(s,fn);
+	status = process_win32(s, fn);
 #else
-	status = process_normal(s,fn);
+	status = process_normal(s, fn);
 #endif
       }
       
diff --git a/main.h b/main.h
index 8182854..19b75d2 100644
--- a/main.h
+++ b/main.h
@@ -1,7 +1,7 @@
 // ssdeep
 // Copyright (C) 2012 Kyrus
 //
-// $Id: main.h 144 2012-04-24 14:59:33Z jessekornblum $
+// $Id: main.h 210 2014-05-08 23:04:56Z jessekornblum $
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -87,12 +87,6 @@
 #endif
 
 
-#ifndef HAVE_FSEEKO
-# define fseeko fseek
-# define ftello ftell
-#endif
-
-
 #define FALSE  0
 #define TRUE   1
 
diff --git a/match.cpp b/match.cpp
index 6946643..3d2d474 100644
--- a/match.cpp
+++ b/match.cpp
@@ -1,7 +1,7 @@
 // ssdeep
 // (C) Copyright 2012 Kyrus
 //
-// $Id: match.cpp 164 2012-07-23 16:12:36Z jessekornblum $
+// $Id: match.cpp 211 2014-05-14 18:20:23Z jessekornblum $
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -353,8 +353,7 @@ bool find_matches_in_known(state *s)
 }
 
 
-bool match_add(state *s, Filedata * f)
-{
+bool match_add(state *s, Filedata * f) {
   if (NULL == s)
     return true;
 
@@ -364,27 +363,23 @@ bool match_add(state *s, Filedata * f)
 }
 
 
-bool match_load(state *s, const char *fn)
-{
+bool match_load(state *s, const char *fn) {
   if (NULL == s or NULL == fn)
     return true;
-
+  
   if (sig_file_open(s,fn))
     return true;
 
   bool status;
 
-  do 
-  {
+  do {
     Filedata * f; 
     status = sig_file_next(s,&f);
-    if (not status)
-    {
-      if (match_add(s,f))
-      {
+    if (not status) {
+      if (match_add(s,f)) {
 	// One bad hash doesn't mean this load was a failure.
 	// We don't change the return status because match_add failed.
-	print_error(s,"%s: unable to insert hash", fn);
+	print_error(s, "%s: unable to insert hash", fn);
 	break;
       }
     }
diff --git a/missing b/missing
index 1c8ff70..cdea514 100644
--- a/missing
+++ b/missing
@@ -1,11 +1,10 @@
 #! /bin/sh
-# Common stub for a few missing GNU programs while installing.
+# Common wrapper for a few potentially missing GNU programs.
 
-scriptversion=2006-05-10.23
+scriptversion=2012-06-26.16; # UTC
 
-# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
-#   Free Software Foundation, Inc.
-# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -18,9 +17,7 @@ scriptversion=2006-05-10.23
 # GNU General Public License for more details.
 
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -28,66 +25,40 @@ scriptversion=2006-05-10.23
 # the same distribution terms that you use for the rest of that program.
 
 if test $# -eq 0; then
-  echo 1>&2 "Try \`$0 --help' for more information"
+  echo 1>&2 "Try '$0 --help' for more information"
   exit 1
 fi
 
-run=:
-sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
-sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
-
-# In the cases where this matters, `missing' is being run in the
-# srcdir already.
-if test -f configure.ac; then
-  configure_ac=configure.ac
-else
-  configure_ac=configure.in
-fi
+case $1 in
 
-msg="missing on your system"
+  --is-lightweight)
+    # Used by our autoconf macros to check whether the available missing
+    # script is modern enough.
+    exit 0
+    ;;
 
-case $1 in
---run)
-  # Try to run requested program, and just exit if it succeeds.
-  run=
-  shift
-  "$@" && exit 0
-  # Exit code 63 means version mismatch.  This often happens
-  # when the user try to use an ancient version of a tool on
-  # a file that requires a minimum version.  In this case we
-  # we should proceed has if the program had been absent, or
-  # if --run hadn't been passed.
-  if test $? = 63; then
-    run=:
-    msg="probably too old"
-  fi
-  ;;
+  --run)
+    # Back-compat with the calling convention used by older automake.
+    shift
+    ;;
 
   -h|--h|--he|--hel|--help)
     echo "\
 $0 [OPTION]... PROGRAM [ARGUMENT]...
 
-Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
-error status if there is no known handling for PROGRAM.
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
 
 Options:
   -h, --help      display this help and exit
   -v, --version   output version information and exit
-  --run           try to run the given command, and emulate it if it fails
 
 Supported PROGRAM values:
-  aclocal      touch file \`aclocal.m4'
-  autoconf     touch file \`configure'
-  autoheader   touch file \`config.h.in'
-  autom4te     touch the output file, or create a stub one
-  automake     touch all \`Makefile.in' files
-  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
-  flex         create \`lex.yy.c', if possible, from existing .c
-  help2man     touch the output file
-  lex          create \`lex.yy.c', if possible, from existing .c
-  makeinfo     touch the output file
-  tar          try tar, gnutar, gtar, then tar without non-portable flags
-  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
+  bison     yacc      flex         lex       help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
 
 Send bug reports to <bug-automake at gnu.org>."
     exit $?
@@ -99,269 +70,146 @@ Send bug reports to <bug-automake at gnu.org>."
     ;;
 
   -*)
-    echo 1>&2 "$0: Unknown \`$1' option"
-    echo 1>&2 "Try \`$0 --help' for more information"
+    echo 1>&2 "$0: unknown '$1' option"
+    echo 1>&2 "Try '$0 --help' for more information"
     exit 1
     ;;
 
 esac
 
-# Now exit if we have it, but it failed.  Also exit now if we
-# don't have it and --version was passed (most likely to detect
-# the program).
-case $1 in
-  lex|yacc)
-    # Not GNU programs, they don't have --version.
-    ;;
-
-  tar)
-    if test -n "$run"; then
-       echo 1>&2 "ERROR: \`tar' requires --run"
-       exit 1
-    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
-       exit 1
-    fi
-    ;;
-
-  *)
-    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
-       # We have it, but it failed.
-       exit 1
-    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
-       # Could not run --version or --help.  This is probably someone
-       # running `$TOOL --version' or `$TOOL --help' to check whether
-       # $TOOL exists and not knowing $TOOL uses missing.
-       exit 1
-    fi
-    ;;
-esac
-
-# If it does not exist, or fails to run (possibly an outdated version),
-# try to emulate it.
-case $1 in
-  aclocal*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
-         to install the \`Automake' and \`Perl' packages.  Grab them from
-         any GNU archive site."
-    touch aclocal.m4
-    ;;
-
-  autoconf)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`${configure_ac}'.  You might want to install the
-         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
-         archive site."
-    touch configure
-    ;;
-
-  autoheader)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
-         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
-         from any GNU archive site."
-    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
-    test -z "$files" && files="config.h"
-    touch_files=
-    for f in $files; do
-      case $f in
-      *:*) touch_files="$touch_files "`echo "$f" |
-				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
-      *) touch_files="$touch_files $f.in";;
-      esac
-    done
-    touch $touch_files
-    ;;
-
-  automake*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
-         You might want to install the \`Automake' and \`Perl' packages.
-         Grab them from any GNU archive site."
-    find . -type f -name Makefile.am -print |
-	   sed 's/\.am$/.in/' |
-	   while read f; do touch "$f"; done
-    ;;
-
-  autom4te)
-    echo 1>&2 "\
-WARNING: \`$1' is needed, but is $msg.
-         You might have modified some files without having the
-         proper tools for further handling them.
-         You can get \`$1' as part of \`Autoconf' from any GNU
-         archive site."
-
-    file=`echo "$*" | sed -n "$sed_output"`
-    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
-    if test -f "$file"; then
-	touch $file
-    else
-	test -z "$file" || exec >$file
-	echo "#! /bin/sh"
-	echo "# Created by GNU Automake missing as a replacement of"
-	echo "#  $ $@"
-	echo "exit 0"
-	chmod +x $file
-	exit 1
-    fi
-    ;;
-
-  bison|yacc)
-    echo 1>&2 "\
-WARNING: \`$1' $msg.  You should only need it if
-         you modified a \`.y' file.  You may need the \`Bison' package
-         in order for those modifications to take effect.  You can get
-         \`Bison' from any GNU archive site."
-    rm -f y.tab.c y.tab.h
-    if test $# -ne 1; then
-        eval LASTARG="\${$#}"
-	case $LASTARG in
-	*.y)
-	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
-	    if test -f "$SRCFILE"; then
-	         cp "$SRCFILE" y.tab.c
-	    fi
-	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
-	    if test -f "$SRCFILE"; then
-	         cp "$SRCFILE" y.tab.h
-	    fi
-	  ;;
-	esac
-    fi
-    if test ! -f y.tab.h; then
-	echo >y.tab.h
-    fi
-    if test ! -f y.tab.c; then
-	echo 'main() { return 0; }' >y.tab.c
-    fi
-    ;;
-
-  lex|flex)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified a \`.l' file.  You may need the \`Flex' package
-         in order for those modifications to take effect.  You can get
-         \`Flex' from any GNU archive site."
-    rm -f lex.yy.c
-    if test $# -ne 1; then
-        eval LASTARG="\${$#}"
-	case $LASTARG in
-	*.l)
-	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
-	    if test -f "$SRCFILE"; then
-	         cp "$SRCFILE" lex.yy.c
-	    fi
-	  ;;
-	esac
-    fi
-    if test ! -f lex.yy.c; then
-	echo 'main() { return 0; }' >lex.yy.c
-    fi
-    ;;
-
-  help2man)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-	 you modified a dependency of a manual page.  You may need the
-	 \`Help2man' package in order for those modifications to take
-	 effect.  You can get \`Help2man' from any GNU archive site."
-
-    file=`echo "$*" | sed -n "$sed_output"`
-    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
-    if test -f "$file"; then
-	touch $file
-    else
-	test -z "$file" || exec >$file
-	echo ".ab help2man is required to generate this page"
-	exit 1
-    fi
-    ;;
-
-  makeinfo)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified a \`.texi' or \`.texinfo' file, or any other file
-         indirectly affecting the aspect of the manual.  The spurious
-         call might also be the consequence of using a buggy \`make' (AIX,
-         DU, IRIX).  You might want to install the \`Texinfo' package or
-         the \`GNU make' package.  Grab either from any GNU archive site."
-    # The file to touch is that specified with -o ...
-    file=`echo "$*" | sed -n "$sed_output"`
-    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
-    if test -z "$file"; then
-      # ... or it is the one specified with @setfilename ...
-      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
-      file=`sed -n '
-	/^@setfilename/{
-	  s/.* \([^ ]*\) *$/\1/
-	  p
-	  q
-	}' $infile`
-      # ... or it is derived from the source name (dir/f.texi becomes f.info)
-      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
-    fi
-    # If the file does not exist, the user really needs makeinfo;
-    # let's fail without touching anything.
-    test -f $file || exit 1
-    touch $file
-    ;;
-
-  tar)
-    shift
-
-    # We have already tried tar in the generic part.
-    # Look for gnutar/gtar before invocation to avoid ugly error
-    # messages.
-    if (gnutar --version > /dev/null 2>&1); then
-       gnutar "$@" && exit 0
-    fi
-    if (gtar --version > /dev/null 2>&1); then
-       gtar "$@" && exit 0
-    fi
-    firstarg="$1"
-    if shift; then
-	case $firstarg in
-	*o*)
-	    firstarg=`echo "$firstarg" | sed s/o//`
-	    tar "$firstarg" "$@" && exit 0
-	    ;;
-	esac
-	case $firstarg in
-	*h*)
-	    firstarg=`echo "$firstarg" | sed s/h//`
-	    tar "$firstarg" "$@" && exit 0
-	    ;;
-	esac
-    fi
-
-    echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
-         You may want to install GNU tar or Free paxutils, or check the
-         command line arguments."
-    exit 1
-    ;;
-
-  *)
-    echo 1>&2 "\
-WARNING: \`$1' is needed, and is $msg.
-         You might have modified some files without having the
-         proper tools for further handling them.  Check the \`README' file,
-         it often tells you about the needed prerequisites for installing
-         this package.  You may also peek at any GNU archive site, in case
-         some other package would contain this missing \`$1' program."
-    exit 1
-    ;;
-esac
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch.  This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+  msg="probably too old"
+elif test $st -eq 127; then
+  # Program was missing.
+  msg="missing on your system"
+else
+  # Program was found and executed, but failed.  Give up.
+  exit $st
+fi
 
-exit 0
+perl_URL=http://www.perl.org/
+flex_URL=http://flex.sourceforge.net/
+gnu_software_URL=http://www.gnu.org/software
+
+program_details ()
+{
+  case $1 in
+    aclocal|automake)
+      echo "The '$1' program is part of the GNU Automake package:"
+      echo "<$gnu_software_URL/automake>"
+      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/autoconf>"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+    autoconf|autom4te|autoheader)
+      echo "The '$1' program is part of the GNU Autoconf package:"
+      echo "<$gnu_software_URL/autoconf/>"
+      echo "It also requires GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+  esac
+}
+
+give_advice ()
+{
+  # Normalize program name to check for.
+  normalized_program=`echo "$1" | sed '
+    s/^gnu-//; t
+    s/^gnu//; t
+    s/^g//; t'`
+
+  printf '%s\n' "'$1' is $msg."
+
+  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+  case $normalized_program in
+    autoconf*)
+      echo "You should only need it if you modified 'configure.ac',"
+      echo "or m4 files included by it."
+      program_details 'autoconf'
+      ;;
+    autoheader*)
+      echo "You should only need it if you modified 'acconfig.h' or"
+      echo "$configure_deps."
+      program_details 'autoheader'
+      ;;
+    automake*)
+      echo "You should only need it if you modified 'Makefile.am' or"
+      echo "$configure_deps."
+      program_details 'automake'
+      ;;
+    aclocal*)
+      echo "You should only need it if you modified 'acinclude.m4' or"
+      echo "$configure_deps."
+      program_details 'aclocal'
+      ;;
+   autom4te*)
+      echo "You might have modified some maintainer files that require"
+      echo "the 'automa4te' program to be rebuilt."
+      program_details 'autom4te'
+      ;;
+    bison*|yacc*)
+      echo "You should only need it if you modified a '.y' file."
+      echo "You may want to install the GNU Bison package:"
+      echo "<$gnu_software_URL/bison/>"
+      ;;
+    lex*|flex*)
+      echo "You should only need it if you modified a '.l' file."
+      echo "You may want to install the Fast Lexical Analyzer package:"
+      echo "<$flex_URL>"
+      ;;
+    help2man*)
+      echo "You should only need it if you modified a dependency" \
+           "of a man page."
+      echo "You may want to install the GNU Help2man package:"
+      echo "<$gnu_software_URL/help2man/>"
+    ;;
+    makeinfo*)
+      echo "You should only need it if you modified a '.texi' file, or"
+      echo "any other file indirectly affecting the aspect of the manual."
+      echo "You might want to install the Texinfo package:"
+      echo "<$gnu_software_URL/texinfo/>"
+      echo "The spurious makeinfo call might also be the consequence of"
+      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+      echo "want to install GNU make:"
+      echo "<$gnu_software_URL/make/>"
+      ;;
+    *)
+      echo "You might have modified some files without having the proper"
+      echo "tools for further handling them.  Check the 'README' file, it"
+      echo "often tells you about the needed prerequisites for installing"
+      echo "this package.  You may also peek at any GNU archive site, in"
+      echo "case some other package contains this missing '$1' program."
+      ;;
+  esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+                       -e '2,$s/^/         /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
 
 # Local variables:
 # eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "scriptversion="
 # time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
 # End:
diff --git a/sample.c b/sample.c
index 1d385c7..59a6046 100644
--- a/sample.c
+++ b/sample.c
@@ -6,7 +6,7 @@
    
    To compile the program using gcc:
 
-   $ gcc -Wall -I/usr/local/include -L/usr/local/lib sample.c -Lfuzzy
+   $ gcc -Wall -I/usr/local/include -L/usr/local/lib sample.c -lfuzzy
 
    Using mingw:
 
@@ -34,7 +34,7 @@
    SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
    HIGH RISK ACTIVITIES.   */
 
-// $Id: sample.c 97 2010-03-19 15:10:06Z jessekornblum $
+// $Id: sample.c 212 2014-07-24 00:05:35Z jessekornblum $
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/ssdeep.1 b/ssdeep.1
index aa467ca..62bc1a9 100644
--- a/ssdeep.1
+++ b/ssdeep.1
@@ -1,4 +1,4 @@
-.TH SSDEEP "1" "Version 2.9 \- 23 Jul 2012" "Kyrus" "Kyrus"
+.TH SSDEEP "1" "Version 2.11 \- 11 Sep 2014" "Facebook" "Facebook"
 
 .SH NAME
 ssdeep - Computes context triggered piecewise hashes (fuzzy hashes)
@@ -6,15 +6,15 @@ ssdeep - Computes context triggered piecewise hashes (fuzzy hashes)
 .SH SYNOPSIS
 .B ssdeep [-m <file>] [-k <file>] [-vdprgsblcxa] [-t val] [FILES]
 .br
-.B ssdeep [-V|h] 
+.B ssdeep [-V|h]
 
 .SH DESCRIPTION
 .PP
 Computes a signature based on context triggered piecewise hashes
 for each input file, also called a fuzzy hash.
 If requested, the program matches those signatures against
-a file of known signatures and reports any possible matches. 
-It can also examine one or more files of signatures and find any 
+a file of known signatures and reports any possible matches.
+It can also examine one or more files of signatures and find any
 matches in those files.
 Output is written to standard out and errors to standard error.
 The program only accepts the first 100MB of data presented
@@ -24,8 +24,8 @@ via standard input.
 \fB\-m <file>\fR
 Loads the specified file of known hashes to be used for matching. This file must
 be a previous output of the program. The program
-then hashes each entry in FILES and compares these signatures to the known signatures. 
-Any matches which score above the threshold are displayed. 
+then hashes each entry in FILES and compares these signatures to the known signatures.
+Any matches which score above the threshold are displayed.
 This flag may be used multiple times to load more known signatures.
 This flag may not be used with the \-k or \-x flags.
 
@@ -34,9 +34,9 @@ This flag may not be used with the \-k or \-x flags.
 Load the specified file of known hashes to be used for matching. This file must
 be a previous output of the program. The program
 then treats each entry in FILES as a set of known hashes as well. The hashes in these
-FILES are compared to the known hashes from this file. Matches which score 
+FILES are compared to the known hashes from this file. Matches which score
 above the threshold are displayed. Both the file specified here and the
-input FILES should contain fuzzy hashes. 
+input FILES should contain fuzzy hashes.
 This flag may be used multiple times to load more known signatures.
 This flag may not be used with the \-m, \-d, or \-p flags.
 
@@ -47,7 +47,7 @@ as it is being hashed.
 
 .TP
 \fB\-d\fR
-Computes a signature for each entry in the FILES and compares it to the set 
+Computes a signature for each entry in the FILES and compares it to the set
 of known signatures. Matches which score above the threshold are displayed. The
 computed signature is then added to the set of known signatures.
 This flag may not be used with the \-k or \-x flags.
@@ -56,7 +56,7 @@ This flag may not be used with the \-k or \-x flags.
 \fB\-p\fR
 Works like the \-d flag, but displays all matches for each file. That is,
 for two files A and B which match score above the threshold, displays
-"A matches B" and "B matches A". 
+"A matches B" and "B matches A".
 This flag may not be used with the \-k or \-x flags.
 
 .TP
@@ -64,7 +64,7 @@ This flag may not be used with the \-k or \-x flags.
 Enables recursive mode. All subdirectories are traversed.
 Please note that recursive mode cannot be used to examine all
 files of a given file extension. For example, invoking the program with
-\fB\-r *.txt\fR will examine all files in directories that end in .txt. 
+\fB\-r *.txt\fR will examine all files in directories that end in .txt.
 If you want to process all files in a directory tree with the .txt suffix,
 try using the \fBfind(1)\fR command.
 
@@ -72,7 +72,7 @@ try using the \fBfind(1)\fR command.
 \fB\-g\fR
 Similar files are grouped together into clusters. This can be handy
 for finding more similar files. That is, if you are searching for file
-A, which matches B, anything which matches B will also be included in 
+A, which matches B, anything which matches B will also be included in
 the cluster.
 
 .TP
@@ -81,14 +81,14 @@ Silent mode. All error messages are suppressed.
 
 .TP
 \fB\-b\fR
-Enables bare mode. Strips any leading directory information from 
-displayed filenames. 
+Enables bare mode. Strips any leading directory information from
+displayed filenames.
 This flag may not be used in conjunction with the \fB\-l\fR flag.
 
 .TP
 \fB\-l\fR
 Enables relative file paths. Instead of printing the absolute path for
-each file, displays the relative file path as indicated on the command 
+each file, displays the relative file path as indicated on the command
 line. This flag may not be used in conjunction with the \fB\-b\fR flag.
 
 .TP
@@ -103,7 +103,7 @@ Signature file matching.
 Each entry in FILES must contain signatures generated by a previous output
 of the program. Each signature is loaded and compared against the set of
 known hashes. Match scores above the threshold are displayed. Each signature
-is then added to the set of knowns. 
+is then added to the set of knowns.
 This flag may not be used with the \-m, \-d, or \-p flags.
 
 .TP
@@ -133,13 +133,13 @@ things like being unable to load the matching file, specifying
 both bare and relative paths, etc.
 
 .SH AUTHOR
-ssdeep was written by Jesse Kornblum of Kyrus,
+ssdeep was written by Jesse Kornblum of Facebook,
 .br
 research at jessekornblum.com
 
 .PP
 .SH COPYRIGHT
-This program is Copyright (C) 2012 Kyrus and is licensed under the terms 
+This program is Copyright (C) 2014 Facebook and is licensed under the terms
 of the General Public License. See the file COPYING for details.
 
 .SH SEE ALSO
diff --git a/ssdeep.h b/ssdeep.h
index 8ad1323..5632abd 100644
--- a/ssdeep.h
+++ b/ssdeep.h
@@ -2,10 +2,11 @@
 #define __SSDEEP_H
 
 // Fuzzy Hashing by Jesse Kornblum
+// Copyright (C) 2013 Facebook
 // Copyright (C) 2012 Kyrus
 // Copyright (C) 2008 ManTech International Corporation
 //
-// $Id: ssdeep.h 163 2012-07-17 19:59:54Z jessekornblum $ 
+// $Id: ssdeep.h 190 2013-07-11 00:40:22Z jessekornblum $
 //
 
 #include "main.h"
@@ -29,6 +30,10 @@
 // We print a warning for files smaller than this size
 #define SSDEEP_MIN_FILE_SIZE   4096
 
+// The default 'PATH_MAX' on Windows is about 255 bytes. We can expand
+// this limit to 32,767 characters by prepending filenames with "\\?\"
+#define SSDEEP_PATH_MAX 32767
+
 #define MD5DEEP_ALLOC(TYPE,VAR,SIZE)     \
 VAR = (TYPE *)malloc(sizeof(TYPE) * SIZE);  \
 if (NULL == VAR)  \
@@ -51,10 +56,10 @@ memset(VAR,0,SIZE * sizeof(TYPE));
 typedef struct _filedata_t
 {
   uint64_t id;
- 
+
   /// Original signature in the form [blocksize]:[sig1]:[sig2]
   std::string signature;
-  
+
   uint64_t blocksize;
 
   /// Holds signature equal to blocksize
@@ -110,7 +115,7 @@ typedef struct {
 #ifdef _WIN32
 
 // We create macros for the Windows equivalent UNIX functions.
-// No worries about lstat to stat; Windows doesn't have symbolic links 
+// No worries about lstat to stat; Windows doesn't have symbolic links
 #define lstat(A,B)      stat(A,B)
 #define realpath(A,B)   _fullpath(B,A,PATH_MAX)
 #define snprintf        _snprintf
@@ -142,7 +147,7 @@ int getopt(int argc, char *const argv[], const char *optstring);
 #define mode_match        1<<1
 #define mode_barename     1<<2
 #define mode_relative     1<<3
-#define mode_silent       1<<4 
+#define mode_silent       1<<4
 #define mode_directory    1<<5
 #define mode_match_pretty 1<<6
 #define mode_verbose      1<<7
@@ -168,7 +173,7 @@ int done_processing_dir(TCHAR *fn);
 int processing_dir(TCHAR *fn);
 int have_processed_dir(TCHAR *fn);
 
-int process_win32(state *s, TCHAR *fn);
+bool process_win32(state *s, TCHAR *fn);
 int process_normal(state *s, TCHAR *fn);
 int process_stdin(state *s);
 
@@ -184,18 +189,21 @@ bool display_result(state *s, const TCHAR * fn, const char * sum);
 // Helper functions
 // *********************************************************************
 void try_msg(void);
+
+bool expanded_path(TCHAR *p);
+
 void sanity_check(state *s, int condition, const char *msg);
 
 // The basename function kept misbehaving on OS X, so I rewrote it.
 // This function isn't perfect, nor is it designed to be. Because
 // we're guarenteed to be working with a filename here, there's no way
 // that s will end with a DIR_SEPARATOR (e.g. /foo/bar/). This function
-// will not work properly for a string that ends in a DIR_SEPARATOR 
+// will not work properly for a string that ends in a DIR_SEPARATOR
 int my_basename(TCHAR *s);
 int my_dirname(TCHAR *s);
 
 // Remove the newlines, if any, from the string. Works with both
-// \r and \r\n style newlines 
+// \r and \r\n style newlines
 void chop_line_tchar(TCHAR *s);
 void chop_line(char *s);
 
diff --git a/tchar-local.h b/tchar-local.h
index c9f9e2c..154ea6d 100644
--- a/tchar-local.h
+++ b/tchar-local.h
@@ -1,5 +1,5 @@
 
-/* $Id: tchar-local.h 61 2008-02-22 23:18:59Z jessekornblum $ */
+/* $Id: tchar-local.h 210 2014-05-08 23:04:56Z jessekornblum $ */
 
 #ifndef __TCHAR_LOCAL_H
 #define __TCHAR_LOCAL_H
@@ -8,9 +8,6 @@
 /* Unicode support */
 #ifdef _WIN32
 
-// This says that we require Windows NT 4.0 to run
-#define _WIN32_WINNT 0x0400
-
 # include <windows.h>
 # include <wchar.h>
 # include <tchar.h>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/ssdeep.git



More information about the forensics-changes mailing list