[Forensics-changes] [SCM] debian-forensics/afflib branch, debian, updated. debian/3.5.2+dfsg-1-2-g4024d02

Christophe Monniez christophe.monniez at fccu.be
Thu Dec 17 08:50:37 UTC 2009


The following commit has been merged in the debian branch:
commit 6aac684c17a768ea9bb3bee141202dcd8b12b319
Author: Christophe Monniez <christophe.monniez at fccu.be>
Date:   Thu Dec 17 09:19:32 2009 +0100

    Merging upstream version 3.5.4+dfsg.

diff --git a/ChangeLog b/ChangeLog
index 5c824d8..5464a70 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,78 @@
+2009-12-13  Simson L. Garfinkel  <simsong at Silver-SSD.local>
+
+	* tools/afverify.cpp (main): added OpenSSL_add_all_digests().
+	(usage): added debug to print if SHA256 isn't working.
+
+2009-12-13  Simson Garfinkel  <simsong at Silver-Surfer.local>
+
+	* tools/test_recovery.sh (PATH): now stores tempfiles in /tmp
+
+	* tools/test_afsegment.sh (echo): now stores tempfiles in /tmp/
+
+	* tools/test_passphrase.sh: now stores tempfiles in /tmp, rather
+	than in the current directory.
+
+	* tools/afconvert.cpp (convert): fixed utimes() so that it is
+	applied to the af_output_filename.
+
+	* tools/afcrypto.cpp (main): added option -j to print total number
+	of encrypted segments and -J to print total number of unencrypted segments.
+
+2009-12-05  Simson Garfinkel  <simsong at 23.sub-75-210-229.myvzw.com>
+
+	* lib/vnode_aff.cpp (aff_close): forgot to close aff_toc_free,
+	causing memory leak. Fixed.
+
+2009-12-05  Simson Garfinkel  <simsong at Silver-Surfer.local>
+
+	* lib/vnode_ewf.cpp (ewf_get_seg): same bug as below
+
+	* lib/vnode_qemu.cpp (qemu_get_seg): bug in qemu_get_seg should
+	have set *datalen to 8 when called with *datalen=0. Fixed.
+
+	* tools/afcompare.cpp (compare_aff_aff): fixed handling when
+	images have different pagesize but same sectorsize.
+
+	* lib/vnode_raw.cpp (raw_get_seg): added check for seek beyond end
+	of file
+
+2009-11-26  Simson Garfinkel  <simsong at t>
+
+	* MASSIVE UPDATE: fixed many compiler warnings from signness and
+	bad printf formats.
+
+	* lib/afflib.h: af_read now returns ssize_t
+
+2009-11-26  Simson Garfinkel  <simsong at Silver-Surfer.local>
+
+	* tools/afcrypto.cpp: now reports the number of encrypted pages
+
+	* lib/vnode_aff.cpp (aff_vstat): now calculates the number of
+	encrypted pages.
+
+	* lib/afflib.cpp (af_seek): reworked so that there would be no
+	sign problems
+
+	* configure.ac (AFFUSE_BIN): turned on -Wall. enabled
+	_FORTIFY_SOURCE=2 in the Makefiles. What happened to that?
+
+2009-11-25  Simson Garfinkel  <simsong at 205.2.242.10.in-addr.arpa>
+
+	* configure.ac: updated to version 3.5.3
+
+2009-11-25  Simson Garfinkel  <simsong at Silver-Surfer.local>
+
+	* lib/crypto.cpp (af_get_affkey_using_keyfile): fixed swapped
+	memset arguments.
+
+	* lib/vnode_s3.cpp (s3_get_next_seg): fixed swapped memset arguments.
+
+	* lib/s3_glue.cpp (encode): fixed swapped memset arguments.
+
+2009-11-01  Simson L. Garfinkel  <simsong at imac2.local>
+
+	* configure.ac: also checks ${prefix} for installed libraries
+
 2009-10-22  Simson Garfinkel  <simsong at 142.sub-75-226-173.myvzw.com>
 
 	* configure.ac: updated to version 3.5.2
diff --git a/afflib.spec b/afflib.spec
index c59979e..b194c53 100644
--- a/afflib.spec
+++ b/afflib.spec
@@ -1,5 +1,5 @@
 Name: afflib
-Version: 3.5.2
+Version: 3.5.4
 Release: 1
 Summary: Library to support the Advanced Forensic Format
 Group: System Environment/Libraries
diff --git a/configure b/configure
index 6f150b9..65295ba 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.61 for AFFLIB 3.5.2.
+# Generated by GNU Autoconf 2.61 for AFFLIB 3.5.4.
 #
 # Report bugs to <bugs at afflib.org>.
 #
@@ -723,8 +723,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='AFFLIB'
 PACKAGE_TARNAME='afflib'
-PACKAGE_VERSION='3.5.2'
-PACKAGE_STRING='AFFLIB 3.5.2'
+PACKAGE_VERSION='3.5.4'
+PACKAGE_STRING='AFFLIB 3.5.4'
 PACKAGE_BUGREPORT='bugs at afflib.org'
 
 # Factoring default headers for most tests.
@@ -1427,7 +1427,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 AFFLIB 3.5.2 to adapt to many kinds of systems.
+\`configure' configures AFFLIB 3.5.4 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1497,7 +1497,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of AFFLIB 3.5.2:";;
+     short | recursive ) echo "Configuration of AFFLIB 3.5.4:";;
    esac
   cat <<\_ACEOF
 
@@ -1616,7 +1616,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-AFFLIB configure 3.5.2
+AFFLIB configure 3.5.4
 generated by GNU Autoconf 2.61
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1630,7 +1630,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 AFFLIB $as_me 3.5.2, which was
+It was created by AFFLIB $as_me 3.5.4, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   $ $0 $@
@@ -2320,7 +2320,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='afflib'
- VERSION='3.5.2'
+ VERSION='3.5.4'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -11405,7 +11405,6 @@ CC="$lt_save_CC"
 
 
 
-
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -11836,7 +11835,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 # AC_PROG_RANLIB not needed if you are using AC_PROG_LIBTOOL
 # AC_PROG_RANLIB
-ac_config_files="$ac_config_files Makefile lib/Makefile tools/Makefile lzma443/Makefile win32/Makefile tests/Makefile doc/Makefile pyaff/Makefile man/Makefile"
+ac_config_files="$ac_config_files Makefile lib/Makefile tools/Makefile lzma443/Makefile win32/Makefile tests/Makefile doc/Makefile pyaff/Makefile man/Makefile lib/version.h"
 
 ac_config_files="$ac_config_files debian/changelog"
 
@@ -11849,7 +11848,7 @@ ac_config_headers="$ac_config_headers affconfig.h"
 
 # Bring additional directories where things might be found into our
 # search path. I don't know why autoconf doesn't do this by default
-for spfx in /usr/local /opt/local /sw ; do
+for spfx in /usr/local /opt/local /sw ${prefix} ; do
     echo checking ${spfx}/include
     if test -d ${spfx}/include; then
         CPPFLAGS="-I${spfx}/include $CPPFLAGS"
@@ -17342,11 +17341,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17345: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17344: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17349: \$? = $ac_status" >&5
+   echo "$as_me:17348: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -17441,11 +17440,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17444: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17443: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17448: \$? = $ac_status" >&5
+   echo "$as_me:17447: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -17493,11 +17492,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17496: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17495: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17500: \$? = $ac_status" >&5
+   echo "$as_me:17499: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -22084,6 +22083,11 @@ if test "${with_noopt}" = "yes" ; then
   CXXFLAGS=`echo "$CXXFLAGS" | sed s/-O[0-9]//`
 fi
 
+# I am a glutten for punishment and this is security-critical software
+CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -Wall"
+CXXFLAGS="$CXXFLAGS -D_FORTIFY_SOURCE=2 -Wall"
+
+
 ################ drop threading if requested ################
 # Check whether --enable-threading was given.
 if test "${enable_threading+set}" = set; then
@@ -22134,12 +22138,12 @@ echo "$as_me: FUSE:               ${enable_fuse}" >&6;}
 echo "$as_me: LIBEXPAT:           ${have_expat} (needed for AFF signatures)" >&6;}
 { echo "$as_me:$LINENO: " >&5
 echo "$as_me: " >&6;}
+{ echo "$as_me:$LINENO: CFLAGS:     ${CFLAGS}" >&5
+echo "$as_me: CFLAGS:     ${CFLAGS}" >&6;}
 { echo "$as_me:$LINENO: CPPFLAGS:   ${CPPFLAGS}" >&5
 echo "$as_me: CPPFLAGS:   ${CPPFLAGS}" >&6;}
 { echo "$as_me:$LINENO: CXXFLAGS:   ${CXXFLAGS}" >&5
 echo "$as_me: CXXFLAGS:   ${CXXFLAGS}" >&6;}
-{ echo "$as_me:$LINENO: CFLAGS:     ${CFLAGS}" >&5
-echo "$as_me: CFLAGS:     ${CFLAGS}" >&6;}
 { echo "$as_me:$LINENO: LIBS:       ${LIBS}" >&5
 echo "$as_me: LIBS:       ${LIBS}" >&6;}
 { echo "$as_me:$LINENO: LDFLAGS:    ${LDFLAGS}" >&5
@@ -22609,7 +22613,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by AFFLIB $as_me 3.5.2, which was
+This file was extended by AFFLIB $as_me 3.5.4, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -22662,7 +22666,7 @@ Report bugs to <bug-autoconf at gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-AFFLIB config.status 3.5.2
+AFFLIB config.status 3.5.4
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -23136,6 +23140,7 @@ do
     "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
     "pyaff/Makefile") CONFIG_FILES="$CONFIG_FILES pyaff/Makefile" ;;
     "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
+    "lib/version.h") CONFIG_FILES="$CONFIG_FILES lib/version.h" ;;
     "debian/changelog") CONFIG_FILES="$CONFIG_FILES debian/changelog" ;;
     "debian/shlibs.local.ex") CONFIG_FILES="$CONFIG_FILES debian/shlibs.local.ex" ;;
     "afflib.spec") CONFIG_FILES="$CONFIG_FILES afflib.spec" ;;
diff --git a/configure.ac b/configure.ac
index 112ecd6..9893a94 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@
 # and http://www.openismus.com/documents/linux/automake/automake.shtml
 
 
-AC_INIT([AFFLIB],[3.5.2],[bugs at afflib.org])
+AC_INIT([AFFLIB],[3.5.4],[bugs at afflib.org])
 AM_INIT_AUTOMAKE
 AM_MAINTAINER_MODE
 
@@ -25,14 +25,13 @@ AC_CONFIG_MACRO_DIR([m4])
 # We are now threading
 m4_include([acx_pthread.m4])
 m4_include([acinclude.m4])
-
 ACX_PTHREAD()
 
 
 # AC_PROG_RANLIB not needed if you are using AC_PROG_LIBTOOL
 # AC_PROG_RANLIB
 AC_CONFIG_FILES([Makefile lib/Makefile tools/Makefile lzma443/Makefile win32/Makefile 
-			  tests/Makefile doc/Makefile pyaff/Makefile man/Makefile])
+			  tests/Makefile doc/Makefile pyaff/Makefile man/Makefile lib/version.h])
 dnl Have configure make distribution specific files
 AC_CONFIG_FILES([debian/changelog])
 AC_CONFIG_FILES([debian/shlibs.local.ex])
@@ -42,7 +41,7 @@ AM_CONFIG_HEADER([affconfig.h])
 
 # Bring additional directories where things might be found into our
 # search path. I don't know why autoconf doesn't do this by default
-for spfx in /usr/local /opt/local /sw ; do
+for spfx in /usr/local /opt/local /sw ${prefix} ; do
     echo checking ${spfx}/include
     if test -d ${spfx}/include; then
         CPPFLAGS="-I${spfx}/include $CPPFLAGS"
@@ -347,6 +346,11 @@ if test "${with_noopt}" = "yes" ; then
   CXXFLAGS=`echo "$CXXFLAGS" | sed s/-O[[0-9]]//`
 fi
 
+# I am a glutten for punishment and this is security-critical software
+CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -Wall"
+CXXFLAGS="$CXXFLAGS -D_FORTIFY_SOURCE=2 -Wall"
+
+
 ################ drop threading if requested ################
 AC_ARG_ENABLE(threading,
   [  --disable-threading    builds library without threading
@@ -373,9 +377,9 @@ AC_MSG_NOTICE([QEMU Image Drivers: ${enable_qemu}])
 AC_MSG_NOTICE([FUSE:               ${enable_fuse}])
 AC_MSG_NOTICE([LIBEXPAT:           ${have_expat} (needed for AFF signatures)])
 AC_MSG_NOTICE([])
+AC_MSG_NOTICE([CFLAGS:     ${CFLAGS}])
 AC_MSG_NOTICE([CPPFLAGS:   ${CPPFLAGS}])
 AC_MSG_NOTICE([CXXFLAGS:   ${CXXFLAGS}])
-AC_MSG_NOTICE([CFLAGS:     ${CFLAGS}])
 AC_MSG_NOTICE([LIBS:       ${LIBS}])
 AC_MSG_NOTICE([LDFLAGS:    ${LDFLAGS}])
 AC_MSG_NOTICE([*****************************************])
diff --git a/lib/Makefile.in b/lib/Makefile.in
index e507e69..a222177 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -39,7 +39,8 @@ TESTS = aftest$(EXEEXT)
 @MAYBE_S3_TRUE at am__append_2 = s3
 @MAYBE_S3_TRUE at am__append_3 = vnode_s3.cpp vnode_s3.h s3_glue.cpp 
 subdir = lib
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(srcdir)/version.h.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
 	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@@ -50,7 +51,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = $(top_builddir)/affconfig.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = version.h
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -419,6 +420,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
 	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+version.h: $(top_builddir)/config.status $(srcdir)/version.h.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
 	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
diff --git a/lib/aff_toc.cpp b/lib/aff_toc.cpp
index f6897e0..5ea4b0d 100644
--- a/lib/aff_toc.cpp
+++ b/lib/aff_toc.cpp
@@ -32,6 +32,7 @@ void	aff_toc_print(AFFILE *af)
     }
 }
 
+#if 0
 static int toc_sort(const void *a_,const void *b_)
 {
     const aff_toc_mem *a = (const aff_toc_mem *)a_;
@@ -40,6 +41,7 @@ static int toc_sort(const void *a_,const void *b_)
     if(a->offset > b->offset) return 1;
     return 0;
 }
+#endif
 
 static int aff_toc_append(AFFILE *af,const char *segname,uint64_t offset,uint64_t datalen)
 {
diff --git a/lib/afflib.cpp b/lib/afflib.cpp
index 8e6d220..613bb8a 100644
--- a/lib/afflib.cpp
+++ b/lib/afflib.cpp
@@ -488,19 +488,20 @@ uint64_t af_seek(AFFILE *af,int64_t pos,int whence)
 {
     AF_WRLOCK(af);
     if(af_trace) fprintf(af_trace,"af_seek(%p,%"I64d",%d)\n",af,pos,whence);
-    int64_t new_pos=0;
+    uint64_t new_pos=0;
     switch(whence){
     case SEEK_SET:
 	new_pos = pos;
 	break;
     case SEEK_CUR:
-	new_pos = af->pos + pos;
+	if(pos<0 && ((uint64_t)(-pos)) > af->pos) new_pos=0;
+	else new_pos = af->pos + pos;
 	break;
     case SEEK_END:
-	new_pos = af->image_size - pos;
+	if((uint64_t)pos > af->image_size) new_pos=0;
+	else new_pos = af->image_size - pos;
 	break;
     }
-    if(new_pos < 0) new_pos = 0;	// can't be less than 0
 
     /* Note if the direction has changed */
     int direction = (new_pos > af->pos)  ? 1 : ((new_pos < af->pos) ? -1 : 0);
diff --git a/lib/afflib.h b/lib/afflib.h
index f55431f..537a73e 100644
--- a/lib/afflib.h
+++ b/lib/afflib.h
@@ -97,6 +97,7 @@ struct af_vnode_info {
     u_int page_count_total;
     u_int segment_count_signed;
     u_int segment_count_encrypted;
+    u_int page_count_encrypted;
 };					// 
 
 
@@ -168,7 +169,7 @@ int	af_set_option(AFFILE *af,int option,int value);
 #define AF_HALF_OPEN      (1<<29)       // return af before calling af->v->open; 
 
 /* navigating within the data segments as if they were a single file */
-int	af_read(AFFILE *af,unsigned char *buf,size_t count);
+ssize_t	af_read(AFFILE *af,unsigned char *buf,ssize_t count);
 uint64_t  af_seek(AFFILE *af,int64_t pos,int whence); // returns new position
 uint64_t  af_tell(AFFILE *af);
 int	af_eof(AFFILE *af);		// is the virtual file at the end?
diff --git a/lib/afflib_i.h b/lib/afflib_i.h
index 2aaa00d..a2ed2c1 100644
--- a/lib/afflib_i.h
+++ b/lib/afflib_i.h
@@ -300,9 +300,9 @@ struct _AFFILE {
     /* Implement a stream abstraction */
     uint64_t      image_size;		// last mappable byte of disk image
     uint64_t      image_size_in_file;	// see if it was changed...
-    unsigned long image_pagesize;	// the size of image data segments in this file
-    unsigned long image_sectorsize;
-    uint64_t	  pos;			// location in stream
+    u_long image_pagesize;	// the size of image data segments in this file
+    u_long image_sectorsize;
+    uint64_t	  pos;			// location in stream; should be signed because of comparisons
 
     /* Page buffer cache */
     struct aff_pagebuf *pb;		// the current page buffer
@@ -582,7 +582,7 @@ int	af_get_seg(AFFILE *af,const char *name,unsigned long *arg,
  * the vnode driver. 
  */
 void	af_read_sizes(AFFILE *af);	// sets up values if we can get them.
-int	af_set_pagesize(AFFILE *af,long pagesize); // sets the pagesize; fails with -1 if imagesize >=0
+int	af_set_pagesize(AFFILE *af,u_long pagesize); // sets the pagesize; fails with -1 if imagesize >=0
 int	af_set_sectorsize(AFFILE *AF,int sectorsize); // fails with -1 if imagesize>=0
 int	af_get_sectorsize(AFFILE *AF);	// returns sector size
 int	af_has_pages(AFFILE *af);	// does the underlying system support pages?
diff --git a/lib/afflib_pages.cpp b/lib/afflib_pages.cpp
index cef8cbb..af315c5 100644
--- a/lib/afflib_pages.cpp
+++ b/lib/afflib_pages.cpp
@@ -119,7 +119,7 @@ int	af_get_sectorsize(AFFILE *af)	// returns sector size
  * af_set_pagesize:
  * Sets the pagesize. Fails with -1 if it can't be changed.
  */
-int af_set_pagesize(AFFILE *af,long pagesize)
+int af_set_pagesize(AFFILE *af,u_long pagesize)
 {
     /* Allow the pagesize to be changed if it hasn't been set yet
      * and if this format doesn't support metadata updating (which is the raw formats)
@@ -535,7 +535,7 @@ int af_cache_flush(AFFILE *af)
 		ret = -1;		// got an error; keep going, though
 	    }
 	    p->pagebuf_dirty = 0;
-	    if(af_trace) fprintf(af_trace,"af_cache_flush: slot %d page %qd flushed.\n",i,p->pagenum);
+	    if(af_trace) fprintf(af_trace,"af_cache_flush: slot %d page %"PRIu64" flushed.\n",i,p->pagenum);
 	}
     }
     return ret;				// now return the error that I might have gotten
diff --git a/lib/afflib_stream.cpp b/lib/afflib_stream.cpp
index e8562b3..a313086 100644
--- a/lib/afflib_stream.cpp
+++ b/lib/afflib_stream.cpp
@@ -101,7 +101,7 @@ int af_purge(AFFILE *af)
     return ret;
 }
 
-int af_read(AFFILE *af,unsigned char *buf,size_t count)
+ssize_t af_read(AFFILE *af,unsigned char *buf,ssize_t count)
 {
     int total = 0;
 
@@ -230,7 +230,7 @@ int af_write(AFFILE *af,unsigned char *buf,size_t count)
 	}
     }
 
-    uint64_t offset = af->pos;		// where to start
+    int64_t offset = af->pos;		// where to start
 
     /* If the correct segment is not loaded, purge the current segment */
     int64_t write_page = offset / af->image_pagesize;
@@ -319,7 +319,7 @@ int af_write(AFFILE *af,unsigned char *buf,size_t count)
 	}
 
 	/* If we have written more than the image size, update the image size */
-	if(offset > af->image_size) af->image_size = offset;
+	if((uint64_t)offset > af->image_size) af->image_size = offset;
     }
     /* We have copied all of the user's requested data, so return */
     AF_UNLOCK(af);
diff --git a/lib/afflib_util.cpp b/lib/afflib_util.cpp
index 7513b3b..a50f3a5 100644
--- a/lib/afflib_util.cpp
+++ b/lib/afflib_util.cpp
@@ -209,15 +209,16 @@ int64_t	af_segname_page_number(const char *name)
 
 int64_t	af_segname_hash_page_number(const char *name,char *hash,int hashlen)
 {
-  const char *cc = strchr((char *)name,'_');
+    char copy[AF_MAX_NAME_LEN];
+    const char *cc = strchr((char *)name,'_');
     if(!cc) return -1;			// not possibly correct
-    char *copy = strdup(name);		// get a local copy
+    strlcpy(copy,name,sizeof(copy));
     char *dd = strchr(copy,'_');
-    if(!dd){free(copy);return -1;}	// really weird; shouldn't happen
+    if(!dd) return -1;		        // really weird; shouldn't happen
     *dd++ = '\000';			// terminate at _
-    if(strcmp(dd,"md5")!=0){free(copy);return -1;} // not a valid hash
+    if(strcmp(dd,"md5")!=0) return -1;	// not a valid hash
     int64_t page = af_segname_page_number(copy);
-    if(page<0){free(copy);return -1;}	// wasn't what we wanted
+    if(page<0) return -1;		// wasn't what we wanted
     strlcpy(hash,dd,hashlen);
     return page;
 }
diff --git a/lib/aftest.cpp b/lib/aftest.cpp
index 464e761..b292253 100644
--- a/lib/aftest.cpp
+++ b/lib/aftest.cpp
@@ -68,7 +68,6 @@ AFFILE *open_testfile(const char *base,int wipe)
 int sequential_test()
 {
     char buf[1024];
-    char fn[1024];
     const char *fmt = "this is line %d\n";
 
     printf("Sequential test...\n");
@@ -102,7 +101,7 @@ int sequential_test()
 	}
 	rbuf[len] = 0;			// terminate the string
 	if(strcmp(buf,rbuf)!=0){
-	    err(1,"Attempt to verify entry %d failed.\nExpected: (len=%d) '%s'\nGot: (len=%d) '%s'\n",
+	    err(1,"Attempt to verify entry %d failed.\nExpected: (len=%zd) '%s'\nGot: (len=%zd) '%s'\n",
 		i,strlen(buf),buf,strlen(rbuf),rbuf);
 	}
     }
@@ -116,12 +115,9 @@ int reverse_test()
 {
     char wbuf[1024];
     char rbuf[1024];
-    char fn[1024];
-    int pass = 0;
 
     printf("Reverse write test...\n");
     for(int pass=1;pass<=2;pass++){
-	int mode = (pass==1) ? O_CREAT|O_RDWR|O_TRUNC : O_RDONLY;
 
 	AFFILE *af = open_testfile("test_reverse",pass==1);
 	for(int i=MAX_FMTS-1;i>=0;i--){
@@ -153,7 +149,6 @@ int reverse_test()
 
 int random_write_test()
 {
-    char fn[1024];
     char buf[1024];
     char *tally = (char *)calloc(MAX_FMTS,1);
     int i;
@@ -229,7 +224,6 @@ int random_read_test(int total_bytes,int data_page_size)
 		     O_CREAT|O_RDWR|O_TRUNC|O_BINARY,0666);
     if(fd<0) err(1,"fopen");
 
-    char fn[1024];
     AFFILE *af = open_testfile("test_random_contents",1);
 
     /* Just write it out as one big write */
@@ -401,11 +395,11 @@ void sparse_test()
     /* Now seek to somewhere that no data has been written and see if we get 0s. */
     memset(buf,'g',sizeof(buf));
     af_seek(af,mult/2,SEEK_SET);
-    int r = af_read(af,(unsigned char *)buf,sizeof(buf));
+    ssize_t r = af_read(af,(unsigned char *)buf,sizeof(buf));
     if(r!=sizeof(buf)){
-	err(1,"Tried to read %d bytes at mult/2; got %d bytes\n",sizeof(buf),r);
+	err(1,"Tried to read %zd bytes at mult/2; got %zd bytes\n",sizeof(buf),r);
     }
-    for(int i=0;i<sizeof(buf);i++){
+    for(u_int i=0;i<sizeof(buf);i++){
 	if(buf[i]!=0) err(1,"data error; buf[%d]=%d\n",i,buf[i]);
     }
 
@@ -414,7 +408,7 @@ void sparse_test()
     af_seek(af,9*mult,SEEK_SET);
     r = af_read(af,big_buf,sizeof(big_buf));
     if(r!=sizeof(buf)){
-	errx(1,"Tried to read %d bytes at the end of the file; got %d bytes (should get %d)",
+	errx(1,"Tried to read %zd bytes at the end of the file; got %zd bytes (should get %zd)",
 	    sizeof(big_buf),r,sizeof(buf));
     }
 			  
@@ -422,7 +416,7 @@ void sparse_test()
     /* Now see if we can read past the end of the file */
     af_seek(af,11*mult,SEEK_SET);
     r = af_read(af,(unsigned char *)buf,sizeof(buf));
-    if(r!=0) errx(1,"Tried to read past end of file; got %d bytes (should get 0)",r);
+    if(r!=0) errx(1,"Tried to read past end of file; got %zd bytes (should get 0)",r);
 
     af_close(af);
     printf("\nSprase test passes.\n");
@@ -535,7 +529,7 @@ int aestest()
     u_char test[1024],buf[1024],rbuf[1024];
     size_t  buflen = sizeof(buf);
     make_test_seg(test,0);
-    for(int len=0;len<=strlen((const char *)test);len++){
+    for(u_int len=0;len<=strlen((const char *)test);len++){
 	if(af_update_seg(af,"page0",0,test,len)) err(1,"af_update_seg len=%d",len);
 	
 	/* Now try to read the segment */
@@ -589,7 +583,7 @@ int aestest()
     /* Try to read a segment that doesn't eixst */
     buflen = 0;
     if(af_get_seg(af,"encrypted2",0,0,&buflen)==0){
-	errx(1,"Error: Attempt to get size of non-existant segment 'encrypted2' got %d\n",buflen);
+	errx(1,"Error: Attempt to get size of non-existant segment 'encrypted2' got %zd\n",buflen);
     }
     af_close(af);
 
@@ -683,7 +677,7 @@ void readfile_test(const char *fname)
 	err(1,"af_open(%s)",fname);
     }
     printf("using '%s'\n",af->v->name);
-    printf("af_get_imagesize()=%qd errno=%d\n",af_get_imagesize(af),errno);
+    printf("af_get_imagesize()=%"PRId64" errno=%d\n",af_get_imagesize(af),errno);
 
     int r = af_read(af,buf,sizeof(buf));
     printf("af_read(af,buf,1024)=%d  errno=%d\n",r,errno);
@@ -696,7 +690,7 @@ void zap(const char *fn)
 {
     unsigned char buf[1024*1024];
     AFFILE *af = af_open(fn,O_RDWR,0666);
-    if(!af) err(1,"af_open(%s)");
+    if(!af) err(1,"af_open(%s)",fn);
     memset(buf,0,sizeof(buf));
     if(af_write(af,buf,sizeof(buf))!=sizeof(buf)){
 	err(1,"af_write()");
@@ -731,11 +725,11 @@ void time_test()
 	buf1[0]= count;
 	for(threaded=0;threaded<2;threaded++){
 	    aftimer t;
-	    threaded_hash h_md5("md5",threaded);
-	    threaded_hash h_sha1("sha1",threaded);
-	    threaded_hash h_sha2("sha1",threaded);
-	    threaded_hash h_sha3("sha1",threaded);
-	    threaded_hash h_sha256("sha256",threaded);
+	    threaded_hash h_md5(EVP_get_digestbyname("md5"),threaded);
+	    threaded_hash h_sha1(EVP_get_digestbyname("sha1"),threaded);
+	    threaded_hash h_sha2(EVP_get_digestbyname("sha1"),threaded);
+	    threaded_hash h_sha3(EVP_get_digestbyname("sha1"),threaded);
+	    threaded_hash h_sha256(EVP_get_digestbyname("sha256"),threaded);
 
 	    
 	    printf("Threaded: %d size: %d\n",threaded,size);
@@ -799,7 +793,7 @@ void rsatest()
     PEM_read_bio_X509(bp,&x,0,0);
     EVP_PKEY *pubkey = X509_get_pubkey(x);
     
-    printf("pubkey=%x\n",pubkey);
+    printf("pubkey=%p\n",pubkey);
 	
     EVP_VerifyInit(&md,sha256);
     EVP_VerifyUpdate(&md,ptext,sizeof(ptext));
@@ -843,7 +837,7 @@ void xmltest(const char *fn)
 {
     BIO *bp = BIO_new(BIO_s_mem());
     AFFILE *af = af_open(fn,O_RDONLY,0);
-    if(!af) err(1,fn);
+    if(!af) err(1,"%s",fn);
     char segname[AF_MAX_NAME_LEN];
     while(af_get_next_seg(af,segname,sizeof(segname),0,0,0)==0){
 	xmlseg(bp,af,segname);
diff --git a/lib/crypto.cpp b/lib/crypto.cpp
index 9381c10..2f5d19a 100644
--- a/lib/crypto.cpp
+++ b/lib/crypto.cpp
@@ -99,10 +99,6 @@ static const char *aff_cannot_sign = "AFFLIB: OpenSSL does not have SHA256! "\
     "AFF segments cannot be signed. "\
     "See http://www.afflib.org/requirements.php for additional information.";
 
-static const char *aff_cannot_verify = "AFFLIB: OpenSSL does not have SHA256! "\
-    "Signed AFF segments cannot be verified. "\
-    "See http://www.afflib.org/requirements.php for additional information.";
-
 void af_crypto_allocate(AFFILE *af)
 {
     af->crypto = (struct af_crypto *)calloc(sizeof(struct af_crypto),1); // give space
@@ -286,7 +282,7 @@ int  af_get_aes_key_from_passphrase(AFFILE *af,const char *passphrase,
     AES_decrypt(affkey_seg.zeros_aes256,affkey_seg.zeros_aes256,&dkey);
 
     /* See if its zero? */
-    for(int i=0;i<sizeof(affkey_seg.zeros_aes256);i++){
+    for(u_int i=0;i<sizeof(affkey_seg.zeros_aes256);i++){
 	if(affkey_seg.zeros_aes256[i]) return AF_ERROR_WRONG_PASSPHRASE;
     }
 
@@ -796,6 +792,7 @@ int  af_set_seal_certificates(AFFILE *af,const char *certfiles[],int numcertfile
     if(r!=1) return AF_ERROR_RNG_FAIL; // pretty bad...
     
     af_seal_affkey_using_certificates(af, certfiles, numcertfiles, affkey);
+    return 0;
 }
 
 /**
@@ -921,7 +918,6 @@ int af_get_affkey_using_keyfile(AFFILE *af, const char *private_keyfile,u_char a
     int ret = -1;			// return code; set to 0 when successful
     while(i<1000 && ret!=0){ // hopefully there aren't more than 1000 keys...
 	char segname[AF_MAX_NAME_LEN];
-	int done = 0;
 
 	sprintf(segname,AF_AFFKEY_EVP,i++);
 	size_t buflen=0;
@@ -939,9 +935,9 @@ int af_get_affkey_using_keyfile(AFFILE *af, const char *private_keyfile,u_char a
 	unsigned char *decrypted = 0;	// 
 	if (*(u_int *)buf == htonl(1)){	// check to see if the encrypted EVP is rev 1
 	    /* Handle rev 1 */
-	    const int int1 = sizeof(int)*1; // offset #1 
-	    const int int2 = sizeof(int)*2; // offset #2
-	    const int int3 = sizeof(int)*3; // offset #3
+	    const u_int int1 = sizeof(int)*1; // offset #1 
+	    const u_int int2 = sizeof(int)*2; // offset #2
+	    const u_int int3 = sizeof(int)*3; // offset #3
 	    int ek_size               = ntohl(*(u_int *)(buf+int1));
 	    int total_encrypted_bytes = ntohl(*(u_int *)(buf+int2));
 	    if(int3+EVP_MAX_IV_LENGTH+ek_size+total_encrypted_bytes != buflen){
@@ -950,7 +946,6 @@ int af_get_affkey_using_keyfile(AFFILE *af, const char *private_keyfile,u_char a
 	    unsigned char *iv = buf+int3;
 	    unsigned char *ek = buf+int3+EVP_MAX_IV_LENGTH;
 	    unsigned char *encrypted_affkey = buf+int3+EVP_MAX_IV_LENGTH+ek_size;
-	    bool okay=false;
 		
 	    /* Now let's see if we can decode it*/
 	    EVP_CIPHER_CTX cipher_ctx;
@@ -972,7 +967,7 @@ int af_get_affkey_using_keyfile(AFFILE *af, const char *private_keyfile,u_char a
 			ret = 0;		// successful return
 		    }
 		}
-		memset(decrypted,total_encrypted_bytes,0); // overwrite our temp buffer
+		memset(decrypted,0,total_encrypted_bytes); // overwrite our temp buffer
 		free(decrypted);
 	    }
 	}
diff --git a/lib/qemu/block-raw-posix.c b/lib/qemu/block-raw-posix.c
index 02017bb..b3a07f0 100644
--- a/lib/qemu/block-raw-posix.c
+++ b/lib/qemu/block-raw-posix.c
@@ -21,6 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include <signal.h>
+
 #include "qemu-common.h"
 #ifndef QEMU_IMG
 #include "qemu-timer.h"
diff --git a/lib/s3_glue.cpp b/lib/s3_glue.cpp
index 4b59327..617627f 100644
--- a/lib/s3_glue.cpp
+++ b/lib/s3_glue.cpp
@@ -300,7 +300,7 @@ static string encode(const char *aws_secret_access_key,string str)
 	 md,&md_len);
     /* Now encode this to base64 */
     char b64str[64];
-    memset(b64str,sizeof(b64str),0);
+    memset(b64str,0,sizeof(b64str));
     b64_ntop(md,md_len,b64str,sizeof(b64str));
     return string(b64str);
 }
diff --git a/lib/threaded_hash.h b/lib/threaded_hash.h
index a5f1575..3a3c3df 100644
--- a/lib/threaded_hash.h
+++ b/lib/threaded_hash.h
@@ -1,87 +1,263 @@
 /*
  * Threaded hash object.
+ * Note that this just has a second thread for hashing one block, then it blocks. 
+ * We could chain the blocks together, but we don't.
  */
 
+#ifndef THREADED_HASH_H
+#define THREADED_HASH_H
 #include <openssl/evp.h>
 #ifdef HAVE_ERR_H
 #include <err.h>
 #endif
 
+#include <signal.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+#ifndef MIN
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#include <string>
+#include <queue>
+
+/* Currently this doesn't thread. */
 /* threaded EVP hash object */
 class threaded_hash {
+    static const u_int MAX_BYTES_IN_WORKLIST = 1024*1024*16; // don't use more than 16MB
 private:;
 #ifdef HAVE_PTHREAD
-    pthread_mutex_t mutex;
+    class buffer {
+	u_int flags;
+    public:
+	static const int SHOULD_MALLOC = 0x0001;
+	static const int SHOULD_FREE = 0x0002;
+	buffer():flags(0),buf(0),bufsize(0){ }
+	buffer(const u_char *buf,size_t bufsize,int flags){
+	    if(flags & SHOULD_MALLOC){
+		this->buf = (u_char *)malloc(bufsize);
+		memcpy(this->buf,buf,bufsize);
+	    }
+	    else {
+		this->buf = (u_char *)buf;
+	    }
+	    this->bufsize = bufsize;
+	    this->flags   = flags;
+	}
+	void done(){
+	    if(this->flags & SHOULD_FREE) free(buf);
+	}
+	u_char *buf;
+	size_t bufsize;
+	bool   should_free;
+    };
+    /* These variables are all protected by the mutex */
+    std::queue<buffer> worklist;
+    size_t   bytes_in_worklist;	// how many do we have
+public:
+    uint64_t max_bytes_in_worklist;	// how big did it get?
+private:
+    pthread_t worker_id;			// the worker that is hashing, or 0
+    pthread_mutex_t mutex;			// protects worklist and working
+    pthread_cond_t wakeup_worker;
+    pthread_cond_t wakeup_producer;	// if worklist gets to big, the producer must sleep
+    bool be_threaded;
+    /* END OF MUTEX AREA */
 #endif
-    size_t size;
-    EVP_MD_CTX ctx;
-    u_char *buf;
-    static void *update_worker(void *arg){
-	threaded_hash *t = (threaded_hash *)arg;
-	EVP_DigestUpdate(&t->ctx,t->buf,t->size);
-	free(t->buf);
+    const EVP_MD *md;			// null means hash object is not valid
+    EVP_MD_CTX ctx;			// hash context
+    mutable u_char *hashbuf;		// null if needs to be calculated
+    mutable char *hexbuf;		// mull if needs to be calculated
+public:
+    std::string name(){return std::string(EVP_MD_name(md));}
+
+    /** The worker thread needs to be a static function because it is run in its own thread.
+     * It does the work on the worklist when there is work to do.
+     * If we are not multi-threaded then the update is simply called.
+     */
+
 #ifdef HAVE_PTHREAD
-	pthread_mutex_unlock(&t->mutex);
-#endif
+    static void *worker(void *arg){
+	threaded_hash *t = (threaded_hash *)arg;
+	while (1){
+	    /* Wait until there is no work to do */
+	    pthread_mutex_lock(&t->mutex);
+	    while(t->worklist.size()==0){
+		pthread_cond_signal(&t->wakeup_producer); // make sure the producer is awake
+		pthread_cond_wait(&t->wakeup_worker,&t->mutex); // and wait for more data
+	    }
+	    class buffer b = t->worklist.front();  /* get the next bit of work */
+	    t->worklist.pop();
+	    t->bytes_in_worklist -= b.bufsize;
+	    t->hashed_bytes += b.bufsize;
+	    pthread_mutex_unlock(&t->mutex);
+	    if(b.bufsize==0){		// we are done
+		break;
+	    }
+	    EVP_DigestUpdate(&t->ctx,b.buf,b.bufsize);
+	    b.done();			// done with this buffer
+	}
+	return 0;
     }
-    unsigned int be_threaded:1;
-    unsigned int valid:1;
-    void init(const EVP_MD *md,int be_threaded){
-	if(!md){
-	    this->valid = 0;
-	    return;
+#endif
+
+public:;
+    u_int  hash_size;			// MD5 is 16
+    size_t hashed_bytes;		// number of bytes that have been hashed
+    threaded_hash(const EVP_MD *md,bool be_threaded){
+	this->md          = md;
+	this->hashed_bytes= 0;
+	this->hashbuf     = 0;
+	this->hexbuf      = 0;
+	this->hash_size   = 0;
+	if(md==0){
+	    if(EVP_get_digestbyname("md5")==0){
+		fprintf(stderr,"fatal: Call OpenSSL_add_all_digests() prior to calling EVP_get_digestbyname()\n");
+		exit(1);
+	    }
+	    return;		// invalid MD
 	}
+	EVP_DigestInit(&ctx,md);
+	this->hash_size  = EVP_MD_size(md);
 #ifdef HAVE_PTHREAD
-	if(pthread_mutex_init(&mutex,0)) err(1,"pthread_mutex");
+	this->worker_id   = 0;
+	this->bytes_in_worklist = 0;
+	this->max_bytes_in_worklist = 0;
+	this->be_threaded = be_threaded;
+	pthread_mutex_init(&this->mutex,0);
+	pthread_cond_init(&this->wakeup_worker,0);
+	pthread_cond_init(&this->wakeup_producer,0);
+	if(be_threaded) launch();	// create another one
 #endif
-	EVP_DigestInit(&ctx,md);
-	this->be_threaded = be_threaded ? 1 : 0;
-	this->valid = 1;
     }
-
-public:;
-    threaded_hash(const EVP_MD *md,int be_threaded){
-	init(md,be_threaded);
+#ifdef HAVE_PTHREAD
+    void launch(){
+	pthread_create(&worker_id,NULL,worker,(void *)this);
+	assert(worker_id!=0);
     }
-    threaded_hash(const EVP_MD * (*func)(),int be_threaded){
-	init(func(),be_threaded);
+    void push(class buffer &b) {
+	pthread_mutex_lock(&mutex);
+	bytes_in_worklist += b.bufsize;
+	if(bytes_in_worklist > max_bytes_in_worklist) max_bytes_in_worklist = bytes_in_worklist;
+	worklist.push(b);
+	pthread_cond_signal(&wakeup_worker);
+	pthread_mutex_unlock(&mutex);
     }
-    threaded_hash(const char *hash_name,int be_threaded){
-	init(EVP_get_digestbyname(hash_name),be_threaded);
+#endif
+    static class threaded_hash *new_threaded_hash(const char *name,bool be_threaded){
+	return new threaded_hash(EVP_get_digestbyname(name),be_threaded);
     }
+    
     ~threaded_hash(){
 #ifdef HAVE_PTHREAD
+	if(worker_id){			// thread is still present; just kill it
+	    class buffer b;		// send through a finish
+	    push(b);
+	    pthread_join(worker_id,0);	// wait for the thread to finish
+	    worker_id = 0;
+	}
 	pthread_mutex_destroy(&mutex);
+	pthread_cond_destroy(&wakeup_worker);
+	pthread_cond_destroy(&wakeup_producer);
+#endif
+	if(md) EVP_MD_CTX_cleanup(&ctx);
+	if(hashbuf) free(hashbuf);
+	if(hexbuf)  free(hexbuf);
+    }
+    /** Return if this hash object is usable */
+    bool valid(){
+	return this->md!=0;
+    }
+
+    /** reset the hash object */
+    void clear(){
+	if(this->md==0) return;
+	final();			// make sure that the hashing is done
+	EVP_MD_CTX_cleanup(&ctx);
+	EVP_DigestInit(&ctx,md);
+	this->hashed_bytes = 0;
+	if(hashbuf){ free(hashbuf);hashbuf=0;}
+	if(hexbuf){ free(hexbuf);hexbuf=0;}
+#ifdef HAVE_PTHREAD
+	if(be_threaded) launch();
 #endif
     }
-	
 
-    void update(const u_char *buf,size_t size){
-	if(!valid) return;
-	this->buf = (u_char *)malloc(size);
-	this->size = size;
-	memcpy(this->buf,buf,size);
+    void update(const u_char *buf,size_t bufsize){
+	if(this->md==0) return;		// no MD set
+	if(bufsize==0)  return;		// nothing to do
 
+	/** For the multi-threaded application, copy over the data to be hashed.
+	 * Then lock the mutex and start a worker
+	 * thread that will do the actual hash. The mutex will unlock when done.
+	 * A more efficient implementation would use a thread pool and not constantly
+	 * create and destroy the mutexes.
+	 */
 #ifdef HAVE_PTHREAD
-	pthread_t thread;
-	pthread_mutex_lock(&mutex);
-	if(be_threaded){
-	    pthread_create(&thread,NULL,update_worker,(void *)this);
+	if(worker_id){
+	    pthread_mutex_lock(&mutex);
+	    if(bytes_in_worklist > MAX_BYTES_IN_WORKLIST){
+		/* If too much in the worklist, wait until it clears before we allocate more */
+		pthread_cond_wait(&wakeup_producer,&mutex);
+	    }
+	    pthread_mutex_unlock(&mutex);
+	    class buffer b(buf,bufsize,buffer::SHOULD_FREE|buffer::SHOULD_MALLOC);
+	    push(b);
 	    return;
 	}
 #endif
-	update_worker((void *)this);
+	EVP_DigestUpdate(&ctx,buf,bufsize);
+	hashed_bytes += bufsize;
     }
-    void final(u_char *mdbuf,unsigned int md_len){
-	if(!valid) return;
-#ifdef HAVE_PTHREAD
-	pthread_mutex_lock(&mutex);
-#endif
-	EVP_DigestFinal(&ctx,mdbuf,&md_len);
+    /* Perform the final and return a pointer to the buffer. */
+    u_char *final(){
+	if(this->md==0) return 0;
+	if(this->hashbuf==0){
 #ifdef HAVE_PTHREAD
-	pthread_mutex_unlock(&mutex);
+	    if(worker_id!=0){		// make sure the other thread has stopped.
+		class buffer b;		// send through a finish
+		push(b);
+		pthread_join(worker_id,0); // wait for the worker to be done
+		worker_id = 0;		   // the thread is gone
+	    }
 #endif
+	    this->hashbuf     = (u_char *)calloc(hash_size,1);
+	    EVP_DigestFinal(&ctx,this->hashbuf,&hash_size);
+	}
+	return this->hashbuf;
     }
-};
 
+    void final(u_char *mdbuf,unsigned int md_len){
+	if(this->md==0) return;
+	memcpy(mdbuf,this->hashbuf,MIN(md_len,hash_size));
+    }
+    /** Return the hash buffer */
+    u_char *hash(){
+	return final();
+    }
+    /** Return the hex of the hash buffer, null terminated */
+    const char *hexhash(){
+	if(hexbuf==0){
+	    this->hexbuf      = (char *)calloc(hash_size*2+1,1);
+	    u_char *hashbuf = final();
+	    for(u_int i=0;i<hash_size;i++){
+		sprintf(hexbuf+i*2,"%02x",hashbuf[i]);
+	    }
+	}
+	return hexbuf;
+    }
+    bool operator<( threaded_hash &s2) {
+	if(this->md==0 || s2.md==0) return false;
+	if(this->hash_size != s2.hash_size) return false;
+	return memcmp(hash(),s2.hash(),hash_size) < 0;
+    }
+    bool operator==( threaded_hash &s2) {
+	if(this->md==0 || s2.md==0) return false;
+	if(this->hash_size != s2.hash_size) return false;
+	return memcmp(hash(),s2.hash(),s2.hash_size) == 0;
+    }
 
+};
+#endif
diff --git a/lib/utils.h b/lib/utils.h
index 896f71c..ff2ef63 100644
--- a/lib/utils.h
+++ b/lib/utils.h
@@ -52,6 +52,7 @@ namespace aff {
 	std::string name;
 	size_t len;
 	u_long arg;
+	/** pagenumber returns <0 for invalid pages, >= for a page */
 	int64_t pagenumber() const {return af_segname_page_number(name.c_str());}
 	bool inline operator==(const class seginfo &b) const {
 	    return name == b.name;
diff --git a/lib/version.h.in b/lib/version.h.in
new file mode 100644
index 0000000..02aa75f
--- /dev/null
+++ b/lib/version.h.in
@@ -0,0 +1,3 @@
+ at SET_MAKE@
+#define AFFLIB_VERSION "@PACKAGE_VERSION@"
+
diff --git a/lib/vnode_aff.cpp b/lib/vnode_aff.cpp
index 776a942..ae86c88 100644
--- a/lib/vnode_aff.cpp
+++ b/lib/vnode_aff.cpp
@@ -131,7 +131,7 @@ int aff_write_seg(AFFILE *af, const char *segname,unsigned long arg,const u_char
     aff_toc_update(af,segname,ftello(af->aseg),datalen);
 
     
-    if(af_trace) fprintf(af_trace,"aff_write_seg: putting segment %s (datalen=%zd) offset=%qd\n",
+    if(af_trace) fprintf(af_trace,"aff_write_seg: putting segment %s (datalen=%zd) offset=%"PRId64"\n",
 			 segname,datalen,ftello(af->aseg));
 
     if(fwrite(&segh,sizeof(segh),1,af->aseg)!=1) return -10;
@@ -157,8 +157,6 @@ static int aff_get_seg(AFFILE *af,const char *name,
     if(af_trace) fprintf(af_trace,"aff_get_seg(%p,%s,arg=%p,data=%p,datalen=%p)\n",af,name,arg,data,datalen);
 
     char next[AF_MAX_NAME_LEN];
-    int first = 1;
-    size_t segsize = 0;
 
     /* If the segment is in the directory, then seek the file to that location.
      * Otherwise, we'll probe the next segment, and if it is not there,
@@ -244,8 +242,6 @@ static int aff_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned
 	+ strlen(segname)
 	+ data_len + sizeof(struct af_segment_tail);
 
-    off_t newpos = ftello(af->aseg);
-
     if(strcmp(segt.magic,AF_SEGTAIL)!=0){
 	snprintf(af->error_str,sizeof(af->error_str),"af_get_next_segv: AF file is truncated (AF_ERROR_TAIL).");
 	fseeko(af->aseg,start,SEEK_SET); // go back to last good position
@@ -601,6 +597,7 @@ static int aff_open(AFFILE *af)
  */
 static int aff_close(AFFILE *af)
 {
+    aff_toc_free(af);
     fclose(af->aseg);
     return 0;
 }
@@ -619,12 +616,15 @@ static int aff_vstat(AFFILE *af,struct af_vnode_info *vni)
     if(af->toc){
 	for(int i=0;i<af->toc_count;i++){
 	    if(af->toc[i].name){
+		bool is_page = false;
 		vni->segment_count_total++;
 		if(af_segname_page_number(af->toc[i].name)>=0){
 		    vni->page_count_total++;
+		    is_page = true;
 		}
 		if(af_is_encrypted_segment(af->toc[i].name)){
 		    vni->segment_count_encrypted++;
+		    if(is_page) vni->page_count_encrypted++;
 		}
 		if(af_is_signature_segment(af->toc[i].name)){
 		    vni->segment_count_signed++;
diff --git a/lib/vnode_ewf.cpp b/lib/vnode_ewf.cpp
index c4e48ba..5f1aaa4 100644
--- a/lib/vnode_ewf.cpp
+++ b/lib/vnode_ewf.cpp
@@ -219,7 +219,7 @@ static int ewf_get_seg(AFFILE *af,const char *name, unsigned long *arg,
 #endif
 
     /* Is the user asking for a page? */
-    int64_t segnum = af_segname_page_number(name);
+    uint64_t segnum = af_segname_page_number(name);
     if(segnum>=0){
 	/* Get the segment number */
 	if(data==0){
@@ -229,7 +229,7 @@ static int ewf_get_seg(AFFILE *af,const char *name, unsigned long *arg,
 	    return 0;
 	}
 	size_t r = libewf_read_random(handle,data,*datalen,segnum * chunksize);
-	return 0;				// should probably put in some error checking
+	return r>0 ? 0 : -1;				// should probably put in some error checking
     }
 
     /* See if it is a page name we understand */
@@ -239,7 +239,11 @@ static int ewf_get_seg(AFFILE *af,const char *name, unsigned long *arg,
     }
     if(strcmp(name,AF_IMAGESIZE)==0){
 	if(arg) *arg = 0;
-	if(datalen==0 || *datalen==0) return 0;
+	if(datalen==0) return 0;
+        if(*datalen==0){
+	    *datalen = 8;  // the structure is 8 bytes long 
+	    return 0;
+	}
 	if(*datalen<8) return -2;
 	
 	struct aff_quad  q;
@@ -255,7 +259,6 @@ static int ewf_get_seg(AFFILE *af,const char *name, unsigned long *arg,
     }
     if(strcmp(name,AF_DEVICE_SECTORS)==0){
 	/* Is this in flag or a quad word? */
-	size64_t sz = 0;
 	uint32_t bps = ewf_bytes_per_sector(handle);
 	if(arg && bps>0) *arg = af->image_size / bps;
 	if(datalen) *datalen = 0;
diff --git a/lib/vnode_qemu.cpp b/lib/vnode_qemu.cpp
index 4ee184e..e9b794d 100644
--- a/lib/vnode_qemu.cpp
+++ b/lib/vnode_qemu.cpp
@@ -83,15 +83,6 @@ static int qemu_rewind_seg(AFFILE *af)
 }
 
 
-/* return the length of a string up to a max */
-static int strlenp(const unsigned char *data,int max)
-{
-    for(int i=0;i<max;i++){
-	if(data[i]==0) return i;
-    }
-    return max;
-}
-
 static int qemu_get_seg(AFFILE *af,const char *name, unsigned long *arg,
 		       unsigned char *data,size_t *datalen)
 {
@@ -106,7 +97,7 @@ static int qemu_get_seg(AFFILE *af,const char *name, unsigned long *arg,
 	    return 0;
 	}
 	int64_t sector_start = segnum * af->image_pagesize / 512;
-	int     sector_count = af->image_pagesize/512;
+	u_int   sector_count = af->image_pagesize/512;
 	if(datalen==0) return -1;
 	if(sector_count*512 > *datalen) return -1; // no room
 	return bdrv_read(QEMU_HANDLE(af),sector_start,data,sector_count);
@@ -119,7 +110,11 @@ static int qemu_get_seg(AFFILE *af,const char *name, unsigned long *arg,
     }
     if(strcmp(name,AF_IMAGESIZE)==0){
 	if(arg) *arg = 0;
-	if(datalen==0 || *datalen==0) return 0;
+	if(datalen==0) return 0;
+	if(*datalen==0){
+	    *datalen = 8;	// the structure is 8 bytes long
+	    return 0;
+	}
 	if(*datalen<8) return -2;
 	
 	struct aff_quad  q;
diff --git a/lib/vnode_raw.cpp b/lib/vnode_raw.cpp
index 5be97dd..94a61e3 100644
--- a/lib/vnode_raw.cpp
+++ b/lib/vnode_raw.cpp
@@ -136,6 +136,8 @@ static int raw_get_seg(AFFILE *af,const char *name,
     int64_t pos = (int64_t)segnum * af->image_pagesize; // where we are to start reading
     int64_t bytes_left = af->image_size - pos;	// how many bytes left in the file
 
+    if(bytes_left<0) bytes_left = 0;
+
     int bytes_to_read = af->image_pagesize; // copy this many bytes, unless
     if(bytes_to_read > bytes_left) bytes_to_read = bytes_left; // only this much is left
     
diff --git a/lib/vnode_s3.cpp b/lib/vnode_s3.cpp
index 0d21051..b4bd78d 100644
--- a/lib/vnode_s3.cpp
+++ b/lib/vnode_s3.cpp
@@ -202,7 +202,7 @@ static int s3_get_seg(AFFILE *af,const char *name,unsigned long *arg,unsigned ch
 static int s3_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg,
 			unsigned char *data,size_t *datalen)
 {
-    memset(segname,segname_len,0);
+    memset(segname,0,segname_len);
 
     struct s3_private *sp =S3_PRIVATE(af);
 
diff --git a/lib/vnode_split_raw.cpp b/lib/vnode_split_raw.cpp
index 8a27ad0..b8890ef 100644
--- a/lib/vnode_split_raw.cpp
+++ b/lib/vnode_split_raw.cpp
@@ -575,7 +575,7 @@ static int split_raw_update_seg(AFFILE *af, const char *name,
 	
     uint64_t pos = page_num * af->image_pagesize; // where we are to start reading
     int written = split_raw_write(af, (unsigned char *)value, pos,vallen);
-    if(written==vallen) return 0;	// success
+    if(written==(int)vallen) return 0;	// success
     return -1;
 }
 
diff --git a/lzma443/C/7zip/Compress/LZMA/LZMADecoder.cpp b/lzma443/C/7zip/Compress/LZMA/LZMADecoder.cpp
index 9640d7b..1deae6a 100755
--- a/lzma443/C/7zip/Compress/LZMA/LZMADecoder.cpp
+++ b/lzma443/C/7zip/Compress/LZMA/LZMADecoder.cpp
@@ -309,11 +309,11 @@ STDMETHODIMP CDecoder::ReleaseInStream()
 
 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
 {
-  if (_outSizeDefined = (outSize != NULL))
-    _outSize = *outSize;
-  _remainLen = kLenIdNeedInit;
-  _outWindowStream.Init();
-  return S_OK;
+    if ((_outSizeDefined = (outSize != NULL)))
+	_outSize = *outSize;
+    _remainLen = kLenIdNeedInit;
+    _outWindowStream.Init();
+    return S_OK;
 }
 
 #ifdef _ST_MODE
diff --git a/lzma443/C/7zip/Compress/LZMA/LZMAEncoder.cpp b/lzma443/C/7zip/Compress/LZMA/LZMAEncoder.cpp
index 1b064db..2ac676f 100755
--- a/lzma443/C/7zip/Compress/LZMA/LZMAEncoder.cpp
+++ b/lzma443/C/7zip/Compress/LZMA/LZMAEncoder.cpp
@@ -1204,8 +1204,8 @@ HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRe
   if (repLens[repMaxIndex] >= 2)
   {
     if (repLens[repMaxIndex] + 1 >= lenMain || 
-        repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ||
-        repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))
+        (repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9))) ||
+        (repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))))
     {
       backRes = repMaxIndex;
       lenRes = repLens[repMaxIndex];
@@ -1219,10 +1219,10 @@ HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRe
     if (_longestMatchLength >= 2)
     {
       UInt32 newDistance = matchDistances[_numDistancePairs - 1];
-      if (_longestMatchLength >= lenMain && newDistance < backMain || 
-          _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ||
+      if ((_longestMatchLength >= lenMain && newDistance < backMain) || 
+          (_longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance)) ||
           _longestMatchLength > lenMain + 1 ||
-          _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))
+          (_longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)))
       {
         _longestMatchWasFound = true;
         backRes = UInt32(-1);
diff --git a/missing b/missing
index 1c8ff70..894e786 100755
--- a/missing
+++ b/missing
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Common stub for a few missing GNU programs while installing.
 
-scriptversion=2006-05-10.23
+scriptversion=2005-06-08.21
 
-# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
 #   Free Software Foundation, Inc.
 # Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
 
@@ -33,8 +33,6 @@ if test $# -eq 0; then
 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.
@@ -46,7 +44,7 @@ fi
 
 msg="missing on your system"
 
-case $1 in
+case "$1" in
 --run)
   # Try to run requested program, and just exit if it succeeds.
   run=
@@ -79,7 +77,6 @@ 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
@@ -109,7 +106,7 @@ 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
+case "$1" in
   lex|yacc)
     # Not GNU programs, they don't have --version.
     ;;
@@ -138,7 +135,7 @@ esac
 
 # If it does not exist, or fails to run (possibly an outdated version),
 # try to emulate it.
-case $1 in
+case "$1" in
   aclocal*)
     echo 1>&2 "\
 WARNING: \`$1' is $msg.  You should only need it if
@@ -167,7 +164,7 @@ WARNING: \`$1' is $msg.  You should only need it if
     test -z "$files" && files="config.h"
     touch_files=
     for f in $files; do
-      case $f in
+      case "$f" in
       *:*) touch_files="$touch_files "`echo "$f" |
 				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
       *) touch_files="$touch_files $f.in";;
@@ -195,8 +192,8 @@ WARNING: \`$1' is needed, but is $msg.
          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"`
+    file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
+    test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
     if test -f "$file"; then
 	touch $file
     else
@@ -217,25 +214,25 @@ WARNING: \`$1' $msg.  You should only need it if
          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
+    if [ $# -ne 1 ]; then
         eval LASTARG="\${$#}"
-	case $LASTARG in
+	case "$LASTARG" in
 	*.y)
 	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
-	    if test -f "$SRCFILE"; then
+	    if [ -f "$SRCFILE" ]; then
 	         cp "$SRCFILE" y.tab.c
 	    fi
 	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
-	    if test -f "$SRCFILE"; then
+	    if [ -f "$SRCFILE" ]; then
 	         cp "$SRCFILE" y.tab.h
 	    fi
 	  ;;
 	esac
     fi
-    if test ! -f y.tab.h; then
+    if [ ! -f y.tab.h ]; then
 	echo >y.tab.h
     fi
-    if test ! -f y.tab.c; then
+    if [ ! -f y.tab.c ]; then
 	echo 'main() { return 0; }' >y.tab.c
     fi
     ;;
@@ -247,18 +244,18 @@ WARNING: \`$1' is $msg.  You should only need it if
          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
+    if [ $# -ne 1 ]; then
         eval LASTARG="\${$#}"
-	case $LASTARG in
+	case "$LASTARG" in
 	*.l)
 	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
-	    if test -f "$SRCFILE"; then
+	    if [ -f "$SRCFILE" ]; then
 	         cp "$SRCFILE" lex.yy.c
 	    fi
 	  ;;
 	esac
     fi
-    if test ! -f lex.yy.c; then
+    if [ ! -f lex.yy.c ]; then
 	echo 'main() { return 0; }' >lex.yy.c
     fi
     ;;
@@ -270,9 +267,11 @@ WARNING: \`$1' is $msg.  You should only need it if
 	 \`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
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+	file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+    fi
+    if [ -f "$file" ]; then
 	touch $file
     else
 	test -z "$file" || exec >$file
@@ -290,17 +289,11 @@ WARNING: \`$1' is $msg.  You should only need it if
          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"`
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
     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`
+      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
@@ -324,13 +317,13 @@ WARNING: \`$1' is $msg.  You should only need it if
     fi
     firstarg="$1"
     if shift; then
-	case $firstarg in
+	case "$firstarg" in
 	*o*)
 	    firstarg=`echo "$firstarg" | sed s/o//`
 	    tar "$firstarg" "$@" && exit 0
 	    ;;
 	esac
-	case $firstarg in
+	case "$firstarg" in
 	*h*)
 	    firstarg=`echo "$firstarg" | sed s/h//`
 	    tar "$firstarg" "$@" && exit 0
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 3cfe4ce..2bc6add 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -4,16 +4,12 @@ bin_PROGRAMS = afcat afcompare afconvert afcopy afcrypto affix afinfo afsegment
 EXTRA_DIST = test_make_random_iso.sh test_crypto.sh test_signing.sh test_recovery.sh \
 	test_passphrase.sh test_afsegment.sh 
 
-EXTRA_PROGRAMS = test_fix_perms 
-
-TESTS = test_fix_perms test_signing.sh test_recovery.sh test_passphrase.sh test_afsegment.sh test_crypto.sh
+TESTS = test_signing.sh test_recovery.sh test_passphrase.sh test_afsegment.sh test_crypto.sh
 
 # See http://www.gnu.org/software/libtool/manual.html		# Using-Automake
 
 AM_LDFLAGS = -static		# staticly link our tools (easier debugging)
 
-test_fix_perms_SOURCES = test_fix_perms.c
-
 afcat_SOURCES = afcat.cpp 
 
 afcrypto_SOURCES = afcrypto.cpp
@@ -39,4 +35,4 @@ affuse_LDADD = @top_builddir@/lib/libafflib.la @FUSE_LIBS@
 affuse_LINK = $(CXXLINK)
 
 CLEANFILES = deskclerk.pem test_password.sh blank.iso archives.pem password_signed.aff signed.aff \
-	random.iso agent.pem r3.iso random*.aff blank.aff blanke.aff words r3.iso evidence1.aff test_fix_perms
+	random.iso agent.pem r3.iso random*.aff blank.aff blanke.aff words r3.iso evidence1.aff
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 85a44eb..4f949f2 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -37,9 +37,6 @@ bin_PROGRAMS = afcat$(EXEEXT) afcompare$(EXEEXT) afconvert$(EXEEXT) \
 	afinfo$(EXEEXT) afsegment$(EXEEXT) afstats$(EXEEXT) \
 	afverify$(EXEEXT) afxml$(EXEEXT) affuse$(EXEEXT) \
 	afrecover$(EXEEXT) afsign$(EXEEXT) afdiskprint$(EXEEXT)
-EXTRA_PROGRAMS = test_fix_perms$(EXEEXT)
-TESTS = test_fix_perms$(EXEEXT) test_signing.sh test_recovery.sh \
-	test_passphrase.sh test_afsegment.sh test_crypto.sh
 subdir = tools
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -115,10 +112,6 @@ am_afxml_OBJECTS = afxml.$(OBJEXT)
 afxml_OBJECTS = $(am_afxml_OBJECTS)
 afxml_LDADD = $(LDADD)
 afxml_DEPENDENCIES = @top_builddir@/lib/libafflib.la
-am_test_fix_perms_OBJECTS = test_fix_perms.$(OBJEXT)
-test_fix_perms_OBJECTS = $(am_test_fix_perms_OBJECTS)
-test_fix_perms_LDADD = $(LDADD)
-test_fix_perms_DEPENDENCIES = @top_builddir@/lib/libafflib.la
 DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -144,14 +137,13 @@ SOURCES = $(afcat_SOURCES) $(afcompare_SOURCES) $(afconvert_SOURCES) \
 	$(afcopy_SOURCES) $(afcrypto_SOURCES) $(afdiskprint_SOURCES) \
 	$(affix_SOURCES) $(affuse_SOURCES) $(afinfo_SOURCES) \
 	$(afrecover_SOURCES) $(afsegment_SOURCES) $(afsign_SOURCES) \
-	$(afstats_SOURCES) $(afverify_SOURCES) $(afxml_SOURCES) \
-	$(test_fix_perms_SOURCES)
+	$(afstats_SOURCES) $(afverify_SOURCES) $(afxml_SOURCES)
 DIST_SOURCES = $(afcat_SOURCES) $(afcompare_SOURCES) \
 	$(afconvert_SOURCES) $(afcopy_SOURCES) $(afcrypto_SOURCES) \
 	$(afdiskprint_SOURCES) $(affix_SOURCES) $(affuse_SOURCES) \
 	$(afinfo_SOURCES) $(afrecover_SOURCES) $(afsegment_SOURCES) \
 	$(afsign_SOURCES) $(afstats_SOURCES) $(afverify_SOURCES) \
-	$(afxml_SOURCES) $(test_fix_perms_SOURCES)
+	$(afxml_SOURCES)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -297,10 +289,10 @@ top_srcdir = @top_srcdir@
 EXTRA_DIST = test_make_random_iso.sh test_crypto.sh test_signing.sh test_recovery.sh \
 	test_passphrase.sh test_afsegment.sh 
 
+TESTS = test_signing.sh test_recovery.sh test_passphrase.sh test_afsegment.sh test_crypto.sh
 
 # See http://www.gnu.org/software/libtool/manual.html		# Using-Automake
 AM_LDFLAGS = -static		# staticly link our tools (easier debugging)
-test_fix_perms_SOURCES = test_fix_perms.c
 afcat_SOURCES = afcat.cpp 
 afcrypto_SOURCES = afcrypto.cpp
 afcompare_SOURCES = afcompare.cpp  unix4win32.h
@@ -322,7 +314,7 @@ affuse_CFLAGS = @FUSE_CFLAGS@
 affuse_LDADD = @top_builddir@/lib/libafflib.la @FUSE_LIBS@ 
 affuse_LINK = $(CXXLINK)
 CLEANFILES = deskclerk.pem test_password.sh blank.iso archives.pem password_signed.aff signed.aff \
-	random.iso agent.pem r3.iso random*.aff blank.aff blanke.aff words r3.iso evidence1.aff test_fix_perms
+	random.iso agent.pem r3.iso random*.aff blank.aff blanke.aff words r3.iso evidence1.aff
 
 all: all-am
 
@@ -430,9 +422,6 @@ afverify$(EXEEXT): $(afverify_OBJECTS) $(afverify_DEPENDENCIES)
 afxml$(EXEEXT): $(afxml_OBJECTS) $(afxml_DEPENDENCIES) 
 	@rm -f afxml$(EXEEXT)
 	$(CXXLINK) $(afxml_OBJECTS) $(afxml_LDADD) $(LIBS)
-test_fix_perms$(EXEEXT): $(test_fix_perms_OBJECTS) $(test_fix_perms_DEPENDENCIES) 
-	@rm -f test_fix_perms$(EXEEXT)
-	$(LINK) $(test_fix_perms_OBJECTS) $(test_fix_perms_LDADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -456,7 +445,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/afstats.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/afverify.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/afxml.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/test_fix_perms.Po at am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/tools/afcat.cpp b/tools/afcat.cpp
index 2a397cb..0e8a003 100644
--- a/tools/afcat.cpp
+++ b/tools/afcat.cpp
@@ -100,7 +100,7 @@ void sig_info(int arg)
 {
     fprintf(stderr,"afcat ");
     if(current_fname) fprintf(stderr,"%s: ",current_fname);
-    if(current_page>=0) fprintf(stderr,"[%qd] ",current_page);
+    if(current_page>=0) fprintf(stderr,"[%"PRId64"] ",current_page);
     fflush(stderr);
 }
 
diff --git a/tools/afcompare.cpp b/tools/afcompare.cpp
index 78115a1..e38383a 100644
--- a/tools/afcompare.cpp
+++ b/tools/afcompare.cpp
@@ -328,10 +328,10 @@ int  compare_aff_data_segments(char *title,AFFILE *af1,AFFILE *af2,int64_t pagen
     uint64_t start_sector_number = (pagenum * data1_len) / af1->image_sectorsize;
 
     if(af_get_page(af1,pagenum,data1,&data1_len)<0)
-	err(1,"Cannot read page %"I64d" from %s\n",pagenum,af_filename(af1));
+	err(1,"Cannot read page %"I64d" from %s",pagenum,af_filename(af1));
 
     if(af_get_page(af2,pagenum,data2,&data2_len)<0)
-	err(1,"Cannot read page %"I64d" from %s\n",pagenum,af_filename(af2));
+	err(1,"Cannot read page %"I64d" from %s",pagenum,af_filename(af2));
 
     /* Now look at the pages sector-by-sector. */
     int af1_bad=0;
@@ -529,7 +529,7 @@ int compare_aff_aff(const char *file1,const char *file2)
 	no_data_segments = true;
     }
 
-    if(af1->image_pagesize != af2->image_pagesize){
+    if(af1->image_sectorsize != af2->image_sectorsize){
 	fprintf(stderr,"Currently, %s requires that both images have the "
 		"same image sectorsize.\n"
 		"sectorsize(%s)=%ld\n"
@@ -657,20 +657,22 @@ int compare_aff_aff(const char *file1,const char *file2)
 	}
     }
 
-    if(opt_all) puts("Inspecting data...");
-    for(int mode=1;mode<=3;mode++){
-	char mode_title[1024];
-	switch(mode){
-	case 1: snprintf(mode_title,sizeof(mode_title),
-			 "  Pages only in %s:\n", af_filename(af1));break;
-	case 2: snprintf(mode_title,sizeof(mode_title),
-			 "  Pages only in %s:\n", af_filename(af2));break;
-	case 3: snprintf(mode_title,sizeof(mode_title),"  Pages in both files:\n");break;
-	}
+    if(no_data_segments==false){
+	if(opt_all) puts("Inspecting data...");
+	for(int mode=1;mode<=3;mode++){
+	    char mode_title[1024];
+	    switch(mode){
+	    case 1: snprintf(mode_title,sizeof(mode_title),
+			     "  Pages only in %s:\n", af_filename(af1));break;
+	    case 2: snprintf(mode_title,sizeof(mode_title),
+			     "  Pages only in %s:\n", af_filename(af2));break;
+	    case 3: snprintf(mode_title,sizeof(mode_title),"  Pages in both files:\n");break;
+	    }
 	    
-	for(int i=lowest_page;i<=highest_page;i++){
-	    int r = compare_aff_data_segments(mode_title,af1,af2,i,mode);
-	    if(r!=0) ret = r;
+	    for(int i=lowest_page;i<=highest_page;i++){
+		int r = compare_aff_data_segments(mode_title,af1,af2,i,mode);
+		if(r!=0) ret = r;
+	    }
 	}
     }
     current_source = 0;
diff --git a/tools/afconvert.cpp b/tools/afconvert.cpp
index fb4155b..81d459c 100644
--- a/tools/afconvert.cpp
+++ b/tools/afconvert.cpp
@@ -553,6 +553,12 @@ int convert(const char *infile,char *outfile)
 	af_set_acquisition_date(a_out,si.st_mtime);
     }
 
+    /* Make a copy of the a_out filename if we can get it */
+    char *a_out_fn=0;			 // output filename, to remember for utimes
+    const char *a_ = af_filename(a_out); // remember the output filename
+    if(a_){
+	a_out_fn = strdup(a_);	// make a copy of it
+    }
     if(af_close(a_out)) err(1,"af_close(a_out)");
 
     if(!opt_quiet){
@@ -571,7 +577,11 @@ int convert(const char *infile,char *outfile)
     times[0].tv_sec = si.st_atime;
     times[1].tv_sec = si.st_mtime;
 #ifdef HAVE_UTIMES
-    if(utimes(outfile,times)) warn("utimes(%s):",outfile);
+    if(a_out_fn){
+	if(utimes(a_out_fn,times)) warn("utimes(%s):",outfile);
+	free(a_out_fn);
+	a_out_fn = 0;
+    }
 #endif    
     return(0);
 }
diff --git a/tools/afcopy.cpp b/tools/afcopy.cpp
index 974a6ce..6b4280c 100644
--- a/tools/afcopy.cpp
+++ b/tools/afcopy.cpp
@@ -379,7 +379,7 @@ int afcopy(char *infile,vector<string> &outfiles)
     for(outlist::iterator aout = afouts.begin(); aout != afouts.end(); aout++){
 	if(opt_sign_key_file && segments.has_signed_segments()==false){
 	    if(af_set_sign_files(aout->af,opt_sign_key_file,opt_sign_cert_file)){
-		err(1,opt_sign_key_file);
+		err(1,"%s",opt_sign_key_file);
 	    }
 	    af_sign_all_unsigned_segments(aout->af);
 	    opt_sign = true;
@@ -613,13 +613,13 @@ int main(int argc,char **argv)
 	case 'm': opt_missing++;break;
 	case 'n': opt_note++;break;
 	case 'k':
-	    if(access(optarg,R_OK)) err(1,optarg);
+	    if(access(optarg,R_OK)) err(1,"%s",optarg);
 	    opt_sign_key_file = optarg;
 	    if(opt_sign_cert_file==0) opt_sign_cert_file=optarg;
 	    opt_sign = true;
 	    break;
 	case 'c':
-	    if(access(optarg,R_OK)) err(1,optarg);
+	    if(access(optarg,R_OK)) err(1,"%s",optarg);
 	    opt_sign_cert_file = optarg;
 	    break;
 	case 'V':
diff --git a/tools/afcrypto.cpp b/tools/afcrypto.cpp
index 6b59ca0..ac76eba 100644
--- a/tools/afcrypto.cpp
+++ b/tools/afcrypto.cpp
@@ -54,6 +54,8 @@ const char *progname = "afcrypto";
 #define DEFAULT_PASSPHRASE_FILE ".affpassphrase"
 int opt_debug = 0;
 int opt_verbose = 0;
+int opt_just_print_encrypted_count = 0;
+int opt_just_print_unencrypted_count = 0;
 char *opt_unsealing_private_key_file= 0;
 
 void change_passphrase(const char *fn,const char *old_passphrase,const char *new_passphrase)
@@ -113,6 +115,8 @@ void usage()
     printf("                    (requires a private key and a specified passphrase).\n");
     printf("    -A      --- add asymmetric encryption to a AFFILE encrypted with a passphrase\n");
     printf("                    (requires a certificate file spcified with the -C option\n");
+    printf("    -j      --- Just print the number of encrypted segments\n");
+    printf("    -J      --- Just print the number of unencrypted segments\n");
     
 
     printf("\nPassword Cracking Options:\n");
@@ -139,7 +143,6 @@ char  *check_file(AFFILE *af,const char *passphrase_file)
     char *ret = 0;
     FILE *f = fopen(passphrase_file,"r");
     if(!f) return 0;
-    int t=0;
 
     char buf[1024];
     memset(buf,0,sizeof(buf));
@@ -180,7 +183,7 @@ int af_encrypt_unencrypted_unsigned_segments(AFFILE *af)
 	    /* Get the segment and put it, which will force the encryption to take place */
 	    if(opt_debug) printf("  encrypting segment %s\n",si->name.c_str());
 	    u_char *buf = (u_char *)malloc(si->len);
-	    if(!buf) warn("Cannot encrypt segment '%s' --- too large (%d bytes) --- malloc failed",
+	    if(!buf) warn("Cannot encrypt segment '%s' --- too large (%zd bytes) --- malloc failed",
 			  si->name.c_str(),si->len);
 	    else {
 		unsigned long arg;
@@ -242,7 +245,7 @@ int main(int argc,char **argv)
     bflag = 0;
     int opt_change = 0;
     const char *home = getenv("HOME");
-    while ((ch = getopt(argc, argv, "reC:SAO:N:p:f:kdh?VK:vl")) != -1) {
+    while ((ch = getopt(argc, argv, "reC:SAO:N:p:f:kdh?VK:vljJ")) != -1) {
 	switch (ch) {
 
 	    /* These options make the mode read-write */
@@ -261,6 +264,8 @@ int main(int argc,char **argv)
 	case 'N': new_passphrase = optarg;break;
 	case 'p': check_passphrase = optarg;break;
 	case 'f': passphrase_file = optarg;break;
+	case 'j': opt_just_print_encrypted_count =1;break;
+	case 'J': opt_just_print_unencrypted_count =1;break;
 	case 'k': 
 	    if(!home) home = "/";
 	    passphrase_file = (char *)malloc(strlen(home)+strlen(DEFAULT_PASSPHRASE_FILE)+2);
@@ -287,6 +292,10 @@ int main(int argc,char **argv)
 	usage();
     }
 
+    if(opt_just_print_encrypted_count && opt_just_print_unencrypted_count){
+	errx(1,"Options -j and -J conflict\n");
+    }
+
     if(num_certificates>0 && (opt_encrypt==0 && opt_add_public_key_to_passphrase==0)){
 	errx(1,"Encryption certificates specified by -e option not set. "
 	     "What do you want me to do with these certificates? ");
@@ -376,6 +385,18 @@ int main(int argc,char **argv)
 	if(af_vstat(af,&vni)) err(1,"%s: af_vstat failed: ",fname);
 	const char *the_passphrase = 0;	// the correct passphrase
 
+	if(opt_just_print_encrypted_count){
+	    printf("%d\n",vni.segment_count_encrypted);
+	    af_close(af);
+	    continue;
+	}
+
+	if(opt_just_print_unencrypted_count){
+	    printf("%d\n",vni.segment_count_total-vni.segment_count_encrypted);
+	    af_close(af);
+	    continue;
+	}
+
 
 	/* were we supposed to try a check_passphrase? */
 	if(check_passphrase){
@@ -393,8 +414,9 @@ int main(int argc,char **argv)
 	    }
 	}
 	
-	printf("%s: %5d segments; %5d signed; %5d encrypted; ",
-	       fname,vni.segment_count_total,vni.segment_count_signed,vni.segment_count_encrypted);
+	printf("%s: %5d segments; %5d signed; %5d encrypted; %5d pages; %5d encrypted pages",
+	       fname,vni.segment_count_total,vni.segment_count_signed,vni.segment_count_encrypted,
+	       vni.page_count_total,vni.page_count_encrypted );
 
 	if(the_passphrase) printf("passphrase correct (\"%s\")",the_passphrase);
 	putchar('\n');
diff --git a/tools/aff_bom.cpp b/tools/aff_bom.cpp
index 7c28dfb..8cc1af0 100644
--- a/tools/aff_bom.cpp
+++ b/tools/aff_bom.cpp
@@ -165,11 +165,11 @@ void aff_bom::add(const char *segname,int sigmode,const u_char *seghash,size_t s
 {
     BIO_printf(xml,"<%s segname='%s' sigmode='%d' alg='sha256'>\n",
 	       AF_XML_SEGMENT_HASH,segname,sigmode);
-    BIO_flush(xml);
+    if(BIO_flush(xml)!=1) return;	// something is wrong
     BIO *b64 = BIO_new(BIO_f_base64());
     xml = BIO_push(b64,xml);
     BIO_write(xml,seghash,seghash_len);
-    BIO_flush(xml);
+    if(BIO_flush(xml)!=1) return;	// another error...
     xml = BIO_pop(b64);
     BIO_printf(xml,"</%s>\n",AF_XML_SEGMENT_HASH);
 }
@@ -180,6 +180,7 @@ void aff_bom::close()
     BIO_printf(xml,"</affsegments>\n");
     BIO_printf(xml,"</%s>\n",AF_XML_AFFBOM);
 
+    OpenSSL_add_all_digests();
     const EVP_MD *sha256 = EVP_get_digestbyname("SHA256");
 
     if(sha256){
@@ -198,7 +199,7 @@ void aff_bom::close()
 	BIO *b64 = BIO_new(BIO_f_base64());
 	xml = BIO_push(b64,xml);
 	BIO_write(xml,sig,siglen);
-	BIO_flush(xml);
+	if(BIO_flush(xml)!=1) return;	// something wrong
 	
 	/* Remove the base64 bio */
 	xml = BIO_pop(b64);
@@ -216,6 +217,7 @@ int  aff_bom::write(AFFILE *af,aff::seglist &segments)
 void aff_bom::make_hash(u_char seghash[32], unsigned long arg,const char *segname,
 			const u_char *segbuf, unsigned long segsize)
 {
+    OpenSSL_add_all_digests();		// probably a good idea
     const EVP_MD *sha256 = EVP_get_digestbyname("SHA256");
 
     if(sha256){
diff --git a/tools/aff_bom.h b/tools/aff_bom.h
index 5163691..c0b68f5 100644
--- a/tools/aff_bom.h
+++ b/tools/aff_bom.h
@@ -69,7 +69,7 @@ public:
 		     const u_char *pagebuf, unsigned long pagesize);
     bool opt_note;
     BIO *xml;
-    aff_bom(bool flag):xml(0),cert(0),privkey(0),notes(0),opt_note(flag) { }
+    aff_bom(bool flag):cert(0),privkey(0),notes(0),opt_note(flag),xml(0) { }
     ~aff_bom(){
 	if(notes) free(notes);
 	if(xml) BIO_free(xml);
diff --git a/tools/affix.cpp b/tools/affix.cpp
index e034d24..515a9a5 100644
--- a/tools/affix.cpp
+++ b/tools/affix.cpp
@@ -120,15 +120,15 @@ int fix(const char *infile)
     if(read(fd,buf,strlen(AF_HEADER)+1)!=strlen(AF_HEADER)+1)
 	err(1,"can't read AFF file header. Stop.");
     if(strcmp(buf,AF_HEADER)!=0)
-	err(1,"%s does not begin with an AF_HEADER. Stop.");
+	err(1,"%s does not begin with an AF_HEADER. Stop.",infile);
     if(read(fd,buf,strlen(AF_SEGHEAD)+1)!=strlen(AF_SEGHEAD)+1)
 	err(1,"Can't read AF_SEGHEAD after AF_HEADER. Stop.");
     if(strcmp(buf,AF_SEGHEAD)!=0)
-	err(1,"%s does not have an AF_SEGHEAD after AF_SEGEADER. Stop.");
+	err(1,"%s does not have an AF_SEGHEAD after AF_SEGEADER. Stop.",infile);
 
     /* Figure out length */
     off_t len = lseek(fd,0,SEEK_END);
-    if(len<0) err(1,"Can't seek to end of %s. Stop.");
+    if(len<0) err(1,"Can't seek to end of %s. Stop.",infile);
     close(fd);
     
     AFFILE *af = af_open_with(infile,AF_HALF_OPEN|flags,0,&vnode_aff);
diff --git a/tools/afinfo.cpp b/tools/afinfo.cpp
index ad136d2..97ca5ff 100644
--- a/tools/afinfo.cpp
+++ b/tools/afinfo.cpp
@@ -425,7 +425,7 @@ void print_info(AFFILE *af,const char *segname)
     memset(output_line,0,sizeof(output_line));
 
     /* Now append the arg and the data len */
-    sprintf(output_line,"%-24s %8ld   %8ld   ",segname,arg,(long)data_len);
+    sprintf(output_line,"%-24s %8ld   %8zd   ",segname,arg,data_len);
 
     if(opt_no_preview){
 	printf("%s\n",output_line);
@@ -434,7 +434,7 @@ void print_info(AFFILE *af,const char *segname)
 
     data = (unsigned char *)malloc(data_len);
     if(af_get_seg(af,segname,0,data,&data_len)){
-	warn("af_get_seg_2 failed: segname=%s data_len=%d",segname,data_len);
+	warn("af_get_seg_2 failed: segname=%s data_len=%zd",segname,data_len);
 	goto done;
     }
 
diff --git a/tools/afrecover.cpp b/tools/afrecover.cpp
index c6d6eac..45561b5 100644
--- a/tools/afrecover.cpp
+++ b/tools/afrecover.cpp
@@ -136,7 +136,7 @@ int recover(const char *fname)
 	    if(af_get_page(af,seg->pagenumber(),pagebuf,&pagesize)){
 		err(1,"cannot read %s\n",seg->name.c_str());
 	    }
-	    for(int i=0;i<pagesize;i++){
+	    for(u_int i=0;i<pagesize;i++){
 		my_parity_buf[i] ^= pagebuf[i];
 	    }
 	    break;
@@ -151,7 +151,7 @@ int recover(const char *fname)
     printf("Attempting to repair %s\n",bad_sigs[0].name.c_str());
 	    
     /* Calculate the page buf */
-    for(int i=0;i<pagesize;i++){
+    for(u_int i=0;i<pagesize;i++){
 	new_pagebuf[i] = parity_buf[i] ^ my_parity_buf[i];
     }
 
@@ -177,11 +177,8 @@ int recover(const char *fname)
 
 int main(int argc,char **argv)
 {
-    int bflag, ch;
-    const char *infile;
-
     setvbuf(stdout,0,_IONBF,0);		// turn off buffering
-
+    int ch;
     while ((ch = getopt(argc, argv, "bh?v")) != -1) {
 	switch (ch) {
 	case 'h':
diff --git a/tools/afsegment.cpp b/tools/afsegment.cpp
index 3c261e8..19ad0fe 100644
--- a/tools/afsegment.cpp
+++ b/tools/afsegment.cpp
@@ -240,7 +240,7 @@ void process(const char *fn)
 	    }
 	    
 	    if(p){
-		for(int i=0;i<len;i++){
+		for(u_int i=0;i<len;i++){
 		    putchar(buf[i]);
 		}
 	    }
diff --git a/tools/afsign.cpp b/tools/afsign.cpp
index 00e7e15..704d994 100644
--- a/tools/afsign.cpp
+++ b/tools/afsign.cpp
@@ -197,7 +197,7 @@ int afsign(const char *fn)
 	    }
 	    /* Add to parity buf if we are making a parity page*/
 	    if(compute_parity){
-		for(int i=0;i<this_pagesize;i++){
+		for(u_int i=0;i<this_pagesize;i++){
 		    parity_buf[i] ^= pagebuf[i];
 		}
 	    }
diff --git a/tools/afverify.cpp b/tools/afverify.cpp
index f874037..1a75d42 100644
--- a/tools/afverify.cpp
+++ b/tools/afverify.cpp
@@ -77,6 +77,14 @@ void usage()
     printf("    -a      --- print all segments\n");
     printf("    -V      --- Just print the version number and exit.\n");
     printf("    -v      --- verbose\n");
+
+    OpenSSL_add_all_digests();
+    const EVP_MD *sha256 = EVP_get_digestbyname("sha256");
+    if(sha256){
+	printf("  SHA256 is operational\n");
+    } else {
+	printf("Warning: EVP_get_digestbyname(\"sha256\") fails\n");
+    }
     exit(0);
 }
 
@@ -237,7 +245,8 @@ string get_xml_field(const char *buf,const char *field)
 /* verify the chain signature; return 0 if successful, -1 if failed */
 int  verify_bom_signature(AFFILE *af,const char *buf)
 {
-    const EVP_MD *sha256 = EVP_get_digestbyname("SHA256");
+    OpenSSL_add_all_digests();
+    const EVP_MD *sha256 = EVP_get_digestbyname("sha256");
 
     if(!sha256){
 	fprintf(stderr,"OpenSSL does not have SHA256; signatures cannot be verified.\n");
@@ -254,7 +263,10 @@ int  verify_bom_signature(AFFILE *af,const char *buf)
     const char *sig_start = chain_end + strlen(cce);
 
     BIO *seg = BIO_new_mem_buf((void *)buf,strlen(buf));
-    BIO_seek(seg,0);
+    if(BIO_seek(seg,0)!=0){
+	printf("Cannot seek to beginning of BIO mem?");
+	return -1;
+    }
     X509 *cert = 0;
     PEM_read_bio_X509(seg,&cert,0,0);	// get the contained x509 cert
     BIO_free(seg);
@@ -288,7 +300,7 @@ int  verify_bom_signature(AFFILE *af,const char *buf)
     segmenthash sh;
     sh.af = af;
     if (!sh.parse(buffer_without_signature, strlen(buffer_without_signature))){
-	fprintf(stderr, "%s at line %d\n",
+	fprintf(stderr, "expat error: %s at line %d\n",
 		XML_ErrorString(XML_GetErrorCode(sh.parser)),
 		(int)XML_GetCurrentLineNumber(sh.parser));
     }
@@ -470,5 +482,6 @@ int main(int argc,char **argv)
 	usage();
     }
 
+    OpenSSL_add_all_digests();
     return process(argv[0]);
 }
diff --git a/tools/afxml.cpp b/tools/afxml.cpp
index e50c5ae..fba284a 100644
--- a/tools/afxml.cpp
+++ b/tools/afxml.cpp
@@ -160,7 +160,6 @@ int xml_info(const char *infile)
     af_rewind_seg(af);			// start at the beginning
 
     char segname[AF_MAX_NAME_LEN];
-    char segname2[AF_MAX_NAME_LEN];
     int  pages = 0;
     vector<string> seglist;		// list of segments we will get
     vector<int64_t> pagelist;		// list of segments we will get
@@ -195,7 +194,7 @@ int xml_info(const char *infile)
 	    size_t pagesize = af_page_size(af);
 	    size_t sectorsize = af_get_sectorsize(af);
 	    if(af_get_page(af,*it,data,&pagesize)){
-		err(1,"Can't read page "I64d,*it);
+		err(1,"Can't read page %"PRId64,*it);
 	    }
 	    psb.pages++;
 	    bool allblank = true;
@@ -239,7 +238,7 @@ int xml_info(const char *infile)
 	}
 
 	unsigned char *data= (unsigned char *)malloc(datalen);
-	if(data==0) err(1,"Can't allocate %d bytes for data",datalen);
+	if(data==0) err(1,"Can't allocate %zd bytes for data",datalen);
 	if(af_get_seg(af,segname,&arg,data,&datalen)!=0){
 	    err(1,"Can't read data for segment '%s'",segname);
 	}
@@ -308,6 +307,7 @@ int xml_info(const char *infile)
 	int  b64size = datalen*2+2;
 	char *b64buf = (char *)calloc(b64size,1);
 	int  b64size_real = b64_ntop(data,datalen,b64buf,b64size);
+	data[b64size_real] = 0;		// be sure it is null terminated
 
 	printf(" coding='base64'>");
 	fputs(b64buf,stdout);
diff --git a/tools/test_afsegment.sh b/tools/test_afsegment.sh
old mode 100644
new mode 100755
index 1a76b54..a984b3c
--- a/tools/test_afsegment.sh
+++ b/tools/test_afsegment.sh
@@ -1,16 +1,19 @@
 #!/bin/sh
 # Test the afsegment command
 
+W=/tmp
 unset AFFLIB_PASSPHRASE
 
 echo === Putting a new metadata segment into blank.aff  ===
-/bin/rm -f blank.aff
-./afcopy /dev/null blank.aff
-./afsegment -ssegname=testseg1 blank.aff
-if [ x"testseg1" = x`./afsegment -p segname blank.aff` ] ; then 
+
+/bin/rm -f $W/blank.aff
+./afcopy /dev/null $W/blank.aff
+./afsegment -ssegname=testseg1 $W/blank.aff
+if [ x"testseg1" = x`./afsegment -p segname $W/blank.aff` ] ; then 
   echo afsegment worked!
 else
   echo afsegment does not work properly
   exit 1
 fi
+/bin/rm -f $W/blank.aff
 
diff --git a/tools/test_crypto.sh b/tools/test_crypto.sh
index 2839b80..9764e53 100755
--- a/tools/test_crypto.sh
+++ b/tools/test_crypto.sh
@@ -1,15 +1,22 @@
 #!/bin/sh
 # 
-# test to make sure we haven't broken encryption...
+# test to make sure that the encrypted aff that is distributed with
+# the AFFLIB can be decrypted using a known passphrase.
+#
 
 unset AFFLIB_PASSPHRASE
 
-if [ x${srcdir} == "x" ] ; 
+if [ x${srcdir} = "x" ] ; 
   then 
      TDIR="../tests/"
   else 
      TDIR=$srcdir/../tests/
 fi
 
+if [ ! -r $TDIR/encrypted.aff ]; then
+  echo CANNOT FIND encrypted.aff in $TDIR.
+  exit 0
+fi  
+
 if ! ./afcompare $TDIR/encrypted.iso file://:password@/$TDIR/encrypted.aff ; then exit 1 ; fi
 exit 0
diff --git a/tools/test_fix_perms.c b/tools/test_fix_perms.c
deleted file mode 100644
index 4cef47f..0000000
--- a/tools/test_fix_perms.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-int main(int argc,char **argv)
-{
-    printf("Making sure all scripts are executable\n");
-    system("chmod +x *.sh");
-    exit(0);
-}
diff --git a/tools/test_make_random_iso.sh b/tools/test_make_random_iso.sh
old mode 100644
new mode 100755
index 22cd069..7cf7236
--- a/tools/test_make_random_iso.sh
+++ b/tools/test_make_random_iso.sh
@@ -5,7 +5,7 @@
 
 unset AFFLIB_PASSPHRASE
 
-if [ x"" == x$1 ] ; 
+if [ x"" = x$1 ] ; 
   then echo usage: $0 filename
   exit 1
 fi
diff --git a/tools/test_passphrase.sh b/tools/test_passphrase.sh
index d87356a..c896c73 100755
--- a/tools/test_passphrase.sh
+++ b/tools/test_passphrase.sh
@@ -4,43 +4,60 @@
 
 echo === MAKING THE TEST FILES ==
 unset AFFLIB_PASSPHRASE
-rm -f blank.iso blank.aff blanke.aff
 
-PATH=$PATH:../tools:../../tools:.
-sh test_make_random_iso.sh blank.iso
+W=/tmp
+
+rm -f $W/blank.iso $W/blank.aff $W/blanke.aff $W/words
+
+PATH=$PATH:../tools:../../tools:.:$srcdir
+test_make_random_iso.sh $W/blank.iso || (echo Cannot run test_make_random_iso.sh && exit -1)
+
+if [ ! -r $W/blank.iso ]; then
+  echo CANNOT CREATE $W/blank.iso
+  echo Permission error prevents test from continuing. 
+  exit 0
+fi
+
+./afconvert -o $W/blank.aff $W/blank.iso
+./afconvert -o file://:passphrase@/$W/blanke.aff $W/blank.iso
+
+if [ ! -r $W/blanke.aff ]; then
+  echo CANNOT CREATE $W/blanke.aff 
+  echo Permission error prevents test from continuing. 
+  exit 0
+fi
 
-./afconvert -o blank.aff blank.iso
-./afconvert -o file://:passphrase@/blanke.aff blank.iso
 
 # Make sure afcrypto reports properly for with and with no encrypted segments
-if (./afcrypto blank.aff | grep " 0 encrypted" > /dev/null ) ; then 
-  echo blanke.aff properly created
+if (./afcrypto $W/blank.aff | grep " 0 encrypted" > /dev/null ) ; then 
+  echo $W/blanke.aff properly created
 else  
-   echo ENCRYPTED SEGMENTS IN BLANKE.AFF --- STOP
+   echo ENCRYPTED SEGMENTS IN $W/blanke.aff --- STOP
    exit 1 
 fi 
 
 # Now test afcrypto
-if (./afcrypto blanke.aff | grep -v " 0 encrypted" > /dev/null) ; then 
-  echo blanke.aff properly created
-else 
-  echo NO ENCRYPTED SEGMENTS IN BLANKE.AFF --- STOP
+echo Encrypted segment count: `./afcrypto -j $W/blanke.aff`
+if [ `./afcrypto -j $W/blanke.aff` = "0" ]; then 
+  echo NO ENCRYPTED SEGMENTS IN $W/blanke.aff --- STOP
   exit 1 
+else
+  echo $W/blanke.aff properly created
 fi
 
-echo "sleepy" > words
-echo "dopey" >> words
-echo "doc" >> words
-echo "passphrase" >> words
-echo "foobar" >> words
-if [ "`./afcrypto -k -f words blanke.aff|grep correct|grep passphrase`"x == x ] ; then
+echo "sleepy" > $W/words
+echo "dopey" >> $W/words
+echo "doc" >> $W/words
+echo "passphrase" >> $W/words
+echo "foobar" >> $W/words
+if [ "`./afcrypto -k -f $W/words $W/blanke.aff|grep correct|grep passphrase`"x = x ] ; then
   echo afcrypto did not find the right passphrase
   exit 1
 else 
    echo afcrypto found the correct pasphrase 
 fi
 
-rm blank.iso blank.aff blanke.aff words
+rm $W/blank.iso $W/blank.aff $W/blanke.aff $W/words
 
 echo ALL TESTS PASS
 exit 0
diff --git a/tools/test_recovery.sh b/tools/test_recovery.sh
index e1f86bb..591dc7a 100755
--- a/tools/test_recovery.sh
+++ b/tools/test_recovery.sh
@@ -1,8 +1,11 @@
 #!/bin/sh
 # 
 # test the signing tools
+#
 
-/bin/rm -f recovery.key recovery.bak recovery.iso recovery.afm
+W=/tmp
+
+/bin/rm -f $W/recovery.key $W/recovery.bak $W/recovery.iso $W/recovery.afm
 
 unset AFFLIB_PASSPHRASE
 echo ==== AFRECOVERY TEST ===
@@ -10,23 +13,31 @@ echo Make an X509 key
 
 
 SUBJECT="/CN=Mr. Recovery/emailAddress=recovery at investiations.com"
-openssl req -x509 -newkey rsa:1024 -keyout recovery.pem -out recovery.pem -nodes -subj "$SUBJECT"
+openssl req -x509 -newkey rsa:1024 -keyout $W/recovery.pem -out $W/recovery.pem -nodes -subj "$SUBJECT"
+
+PATH=$PATH:../tools:../../tools:.:$srcdir
+test_make_random_iso.sh $W/recovery.iso
+
+if [ ! -r $W/recovery.iso ]; then
+   echo $W/recovery.iso was not created.
+   printenv
+   echo current directory: `pwd`
+   exit 0
+fi
 
-PATH=$PATH:../tools:../../tools:.
-sh test_make_random_iso.sh recovery.iso
 
-cp recovery.iso recovery.bak
-echo SIGNING RECOVERY.ISO 
-if ! ./afsign -k recovery.pem recovery.iso ; then exit 1 ; fi
-ls -l recovery.iso recovery.afm
+cp $W/recovery.iso $W/recovery.bak
+echo SIGNING $W/recovery.iso 
+if ! ./afsign -k $W/recovery.pem $W/recovery.iso ; then exit 1 ; fi
+ls -l $W/recovery.iso $W/recovery.afm
 echo VERIFYING SIGNATURE
-if ! ./afverify recovery.afm ; then exit 1 ; fi
+if ! ./afverify $W/recovery.afm ; then exit 1 ; fi
 echo CORRUPTING FILE recovery.iso
-dd if=/dev/random of=recovery.iso count=1 skip=1 conv=notrunc
+dd if=/dev/random of=$W/recovery.iso count=1 skip=1 conv=notrunc
 echo ATTEMPTING RECOVERY
-if ! ./afrecover recovery.afm ; then exit 1 ; fi
-if ! ./afverify recovery.afm ; then exit 1 ; fi
+if ! ./afrecover $W/recovery.afm ; then exit 1 ; fi
+if ! ./afverify $W/recovery.afm ; then exit 1 ; fi
 echo MAKING SURE THAT THE MD5 HAS NOT CHANGED
-if ! cmp recovery.bak recovery.iso ; then echo file changed ; exit 1 ; fi
+if ! cmp $W/recovery.bak $W/recovery.iso ; then echo file changed ; exit 1 ; fi
 echo ALL TESTS PASS
-/bin/rm -f recovery.key recovery.bak recovery.iso recovery.afm recovery.pem
+/bin/rm -f $W/recovery.key $W/recovery.bak $W/recovery.iso $W/recovery.afm $W/recovery.pem
diff --git a/tools/test_signing.sh b/tools/test_signing.sh
index 747439f..d472f58 100755
--- a/tools/test_signing.sh
+++ b/tools/test_signing.sh
@@ -7,8 +7,9 @@ unset AFFLIB_PASSPHRASE
 
 echo === MAKING THE TEST FILES ===
 
-PATH=$PATH:../tools:../../tools:.
-sh test_make_random_iso.sh rawevidence.iso
+PATH=$PATH:../tools:../../tools:.:$srcdir
+test_make_random_iso.sh rawevidence.iso
+
 
 echo ==== AFSIGN TEST ===
 echo Making X.509 keys

-- 
debian-forensics/afflib



More information about the forensics-changes mailing list