[Forensics-changes] [SCM] debian-forensics/sleuthkit branch, debian, updated. debian/3.1.3-1-4-g4ecc26f

Christophe Monniez christophe.monniez at fccu.be
Sat Apr 9 09:59:33 UTC 2011


The following commit has been merged in the debian branch:
commit 81ebfc52ce64eca8b4c801d41aa45dc753f06edc
Author: Christophe Monniez <christophe.monniez at fccu.be>
Date:   Sat Apr 9 11:35:11 2011 +0200

    Merging upstream version 3.2.1.

diff --git a/Makefile.am b/Makefile.am
index f267b6b..b438643 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,15 +14,20 @@ EXTRA_DIST = README_win32.txt README.txt INSTALL.txt ChangeLog.txt NEWS.txt \
     win32/istat/istat.vcproj win32/jcat/jcat.vcproj \
     win32/jls/jls.vcproj win32/mmls/mmls.vcproj \
     win32/mmstat/mmstat.vcproj win32/mmcat/mmcat.vcproj \
+    win32/tsk_recover/tsk_recover.vcproj win32/tsk_loaddb/tsk_loaddb.vcproj \
+    win32/tsk_comparedir/tsk_compare.vcproj \
+    win32/tsk_gettimes/tsk_gettimes.vcproj \
     win32/tsk-win.sln \
     win32/libauxtools/libauxtools.vcproj \
     win32/libfstools/libfstools.vcproj \
     win32/libhashdbtools/libhashdbtools.vcproj \
     win32/libimgtools/libimgtools.vcproj \
     win32/libmmtools/libmmtools.vcproj  \
+    win32/libautotools/libautotools.vcproj  \
     win32/posix-sample/posix-sample.vcproj \
     win32/callback-sample/callback-sample.vcproj
 
+CLEANFILES = tsk3/tsk_incs.h
 
 # directories to compile
 SUBDIRS = tsk3 tools tests samples man
@@ -34,7 +39,7 @@ nobase_include_HEADERS = tsk3/libtsk.h tsk3/tsk_incs.h \
     tsk3/vs/tsk_mac.h tsk3/vs/tsk_sun.h \
     tsk3/fs/tsk_fs.h tsk3/fs/tsk_ffs.h tsk3/fs/tsk_ext2fs.h tsk3/fs/tsk_fatfs.h \
     tsk3/fs/tsk_ntfs.h tsk3/fs/tsk_iso9660.h tsk3/fs/tsk_hfs.h \
-    tsk3/hashdb/tsk_hashdb.h
+    tsk3/hashdb/tsk_hashdb.h tsk3/auto/tsk_auto.h
 
 nobase_dist_data_DATA = tsk3/sorter/default.sort tsk3/sorter/freebsd.sort \
     tsk3/sorter/images.sort tsk3/sorter/linux.sort tsk3/sorter/openbsd.sort \
diff --git a/Makefile.in b/Makefile.in
index 1464c59..1da7d6b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -217,15 +217,20 @@ EXTRA_DIST = README_win32.txt README.txt INSTALL.txt ChangeLog.txt NEWS.txt \
     win32/istat/istat.vcproj win32/jcat/jcat.vcproj \
     win32/jls/jls.vcproj win32/mmls/mmls.vcproj \
     win32/mmstat/mmstat.vcproj win32/mmcat/mmcat.vcproj \
+    win32/tsk_recover/tsk_recover.vcproj win32/tsk_loaddb/tsk_loaddb.vcproj \
+    win32/tsk_comparedir/tsk_compare.vcproj \
+    win32/tsk_gettimes/tsk_gettimes.vcproj \
     win32/tsk-win.sln \
     win32/libauxtools/libauxtools.vcproj \
     win32/libfstools/libfstools.vcproj \
     win32/libhashdbtools/libhashdbtools.vcproj \
     win32/libimgtools/libimgtools.vcproj \
     win32/libmmtools/libmmtools.vcproj  \
+    win32/libautotools/libautotools.vcproj  \
     win32/posix-sample/posix-sample.vcproj \
     win32/callback-sample/callback-sample.vcproj
 
+CLEANFILES = tsk3/tsk_incs.h
 
 # directories to compile
 SUBDIRS = tsk3 tools tests samples man
@@ -236,7 +241,7 @@ nobase_include_HEADERS = tsk3/libtsk.h tsk3/tsk_incs.h \
     tsk3/vs/tsk_mac.h tsk3/vs/tsk_sun.h \
     tsk3/fs/tsk_fs.h tsk3/fs/tsk_ffs.h tsk3/fs/tsk_ext2fs.h tsk3/fs/tsk_fatfs.h \
     tsk3/fs/tsk_ntfs.h tsk3/fs/tsk_iso9660.h tsk3/fs/tsk_hfs.h \
-    tsk3/hashdb/tsk_hashdb.h
+    tsk3/hashdb/tsk_hashdb.h tsk3/auto/tsk_auto.h
 
 nobase_dist_data_DATA = tsk3/sorter/default.sort tsk3/sorter/freebsd.sort \
     tsk3/sorter/images.sort tsk3/sorter/linux.sort tsk3/sorter/openbsd.sort \
@@ -624,6 +629,7 @@ install-strip:
 mostlyclean-generic:
 
 clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
 distclean-generic:
 	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
diff --git a/NEWS.txt b/NEWS.txt
index 3fc93ba..18e1eaa 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,17 +1,53 @@
 Numbers refer to SourceForge.net tracker IDs:
     http://sourceforge.net/tracker/?group_id=55685
 
+---------------- VERSION 3.2.1 --------------
+Bug Fixes
+- 3108272: fls arguments for -d and -u
+- 3105539: compile error issues because of SQlite and pthreads
+- 3173095: missing FAT files because of invalid dates. 
+- 3184419: mingew compile errors.
+- 3191391: surround file name in quotes in mactime -d csv output
+
+New Features:
+- A single dummy entry is added to the SQlite DB if no volume exists
+so that all programs can assume that there will be at least one
+volume in the table.
+- 3184455: allow srcdir != builddir
+
+---------------- VERSION 3.2.0 --------------
+Bug Fixes
+- 3043092: Minor logic errors with ifind code. 
+- FAT performance fix when looking for parent directories
+  in $OrphanFiles. 
+- 3052302: Crash on NTFS/UFS detection test because of
+  corrupt data -- tsk_malloc error. 
+- 3088447: Error adding attribute because of run collision.  
+  Solved by assigning unique IDs.
+
+New Features:
+- 3012324: Name mangling moved out of library into outer tools
+  so that they can see control characters if they want to.  Patch
+  by Anthony Lawrence. 
+- 2993806: ENUM values have a specified NONE value if you don't
+  want to specify any special flags. Patch by Anthony Lawrence.
+- 3026989: Add -e and -s flags to img_cat.  patch by Simson Garfinkel. 
+- 2941805: Add case sensitive flag to fsstat in HFS.  Patch by Rob Joyce. 
+- 3017764: Changed how default NTFS $DATA attribute was named.  Now it 
+  has no name, while it previously had a fake name of "$Data". 
+- New TskAuto class.
+- New tsk_loaddb, tsk_recover, tsk_comparedir, and tsk_gettimes tools. 
+
 ---------------- VERSION 3.1.3 --------------
 Bug Fixes
 - 3006733: FAT directory listings were slow because the inner
 code was not stopping when it found the parent directory.
 - Adjusted sanity / testing code on FAT directory entries to allow
 non-ascii in extensions and reject entries with lots of 0s.
-- 3023606: Ext2 / ffs corrupted file names.
-- Applied NTFS SID fixes from Mandiant.
+- 3023606: Ext2 / ffs corrupted file names. 
+- Applied NTFS SID fixes from Mandiant. 
 - ntfs_load_secure() memory leak patch from Michael Cohen
 
-
 ---------------- VERSION 3.1.2 --------------
 Bug Fixes
 - 2982426: FAT directory listings were slow because the entire
diff --git a/configure b/configure
index d90006c..72aa30a 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 sleuthkit 3.1.3.
+# Generated by GNU Autoconf 2.61 for sleuthkit 3.2.1.
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -721,8 +721,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='sleuthkit'
 PACKAGE_TARNAME='sleuthkit'
-PACKAGE_VERSION='3.1.3'
-PACKAGE_STRING='sleuthkit 3.1.3'
+PACKAGE_VERSION='3.2.1'
+PACKAGE_STRING='sleuthkit 3.2.1'
 PACKAGE_BUGREPORT=''
 
 ac_unique_file="tsk3/base/tsk_base.h"
@@ -1395,7 +1395,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 sleuthkit 3.1.3 to adapt to many kinds of systems.
+\`configure' configures sleuthkit 3.2.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1465,7 +1465,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of sleuthkit 3.1.3:";;
+     short | recursive ) echo "Configuration of sleuthkit 3.2.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1570,7 +1570,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-sleuthkit configure 3.1.3
+sleuthkit configure 3.2.1
 generated by GNU Autoconf 2.61
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1584,7 +1584,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 sleuthkit $as_me 3.1.3, which was
+It was created by sleuthkit $as_me 3.2.1, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   $ $0 $@
@@ -2278,7 +2278,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='sleuthkit'
- VERSION='3.1.3'
+ VERSION='3.2.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -10824,6 +10824,7 @@ fi
 
 
 
+
 # Checks for programs.
 ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
@@ -13793,11 +13794,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:13796: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13797: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13800: \$? = $ac_status" >&5
+   echo "$as_me:13801: \$? = $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.
@@ -13892,11 +13893,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:13895: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13896: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13899: \$? = $ac_status" >&5
+   echo "$as_me:13900: \$? = $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
@@ -13944,11 +13945,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:13947: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13948: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13951: \$? = $ac_status" >&5
+   echo "$as_me:13952: \$? = $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
@@ -18129,236 +18130,7 @@ fi
 #AC_FUNC_MEMCMP
 #AC_FUNC_MKTIME
 #AC_FUNC_MMAP
-
-for ac_header in stdlib.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_header_compiler=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_header_compiler=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-	       { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-{ echo "$as_me:$LINENO: checking for GNU libc compatible realloc" >&5
-echo $ECHO_N "checking for GNU libc compatible realloc... $ECHO_C" >&6; }
-if test "${ac_cv_func_realloc_0_nonnull+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  ac_cv_func_realloc_0_nonnull=no
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#if defined STDC_HEADERS || defined HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-char *realloc ();
-#endif
-
-int
-main ()
-{
-return ! realloc (0, 0);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_func_realloc_0_nonnull=yes
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_func_realloc_0_nonnull=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_func_realloc_0_nonnull" >&5
-echo "${ECHO_T}$ac_cv_func_realloc_0_nonnull" >&6; }
-if test $ac_cv_func_realloc_0_nonnull = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_REALLOC 1
-_ACEOF
-
-else
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_REALLOC 0
-_ACEOF
-
-   case " $LIBOBJS " in
-  *" realloc.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS realloc.$ac_objext"
- ;;
-esac
-
-
-cat >>confdefs.h <<\_ACEOF
-#define realloc rpl_realloc
-_ACEOF
-
-fi
-
-
-
+#AC_FUNC_REALLOC
 
 
 for ac_header in sys/select.h sys/socket.h
@@ -19509,11 +19281,178 @@ done
 fi
 
 
+# sqlite requires pthread libraries - this was copied from its configure.ac
+{ echo "$as_me:$LINENO: checking for library containing pthread_create" >&5
+echo $ECHO_N "checking for library containing pthread_create... $ECHO_C" >&6; }
+if test "${ac_cv_search_pthread_create+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_pthread_create=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_pthread_create+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_pthread_create+set}" = set; then
+  :
+else
+  ac_cv_search_pthread_create=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_search_pthread_create" >&6; }
+ac_res=$ac_cv_search_pthread_create
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ echo "$as_me:$LINENO: checking for library containing dlopen" >&5
+echo $ECHO_N "checking for library containing dlopen... $ECHO_C" >&6; }
+if test "${ac_cv_search_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_dlopen=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_dlopen+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_dlopen+set}" = set; then
+  :
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5
+echo "${ECHO_T}$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
 
 ac_config_commands="$ac_config_commands tsk3/tsk_incs.h"
 
 
-ac_config_files="$ac_config_files Makefile tsk3/Makefile tsk3/base/Makefile tsk3/img/Makefile tsk3/vs/Makefile tsk3/fs/Makefile tsk3/hashdb/Makefile tools/Makefile tools/imgtools/Makefile tools/vstools/Makefile tools/fstools/Makefile tools/hashtools/Makefile tools/srchtools/Makefile tools/sorter/Makefile tools/timeline/Makefile tests/Makefile samples/Makefile man/Makefile"
+ac_config_files="$ac_config_files Makefile tsk3/Makefile tsk3/base/Makefile tsk3/img/Makefile tsk3/vs/Makefile tsk3/fs/Makefile tsk3/hashdb/Makefile tsk3/auto/Makefile tools/Makefile tools/imgtools/Makefile tools/vstools/Makefile tools/fstools/Makefile tools/hashtools/Makefile tools/srchtools/Makefile tools/autotools/Makefile tools/sorter/Makefile tools/timeline/Makefile tests/Makefile samples/Makefile man/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -19953,7 +19892,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 sleuthkit $as_me 3.1.3, which was
+This file was extended by sleuthkit $as_me 3.2.1, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -20006,7 +19945,7 @@ Report bugs to <bug-autoconf at gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-sleuthkit config.status 3.1.3
+sleuthkit config.status 3.2.1
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -20485,12 +20424,14 @@ do
     "tsk3/vs/Makefile") CONFIG_FILES="$CONFIG_FILES tsk3/vs/Makefile" ;;
     "tsk3/fs/Makefile") CONFIG_FILES="$CONFIG_FILES tsk3/fs/Makefile" ;;
     "tsk3/hashdb/Makefile") CONFIG_FILES="$CONFIG_FILES tsk3/hashdb/Makefile" ;;
+    "tsk3/auto/Makefile") CONFIG_FILES="$CONFIG_FILES tsk3/auto/Makefile" ;;
     "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
     "tools/imgtools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/imgtools/Makefile" ;;
     "tools/vstools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/vstools/Makefile" ;;
     "tools/fstools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/fstools/Makefile" ;;
     "tools/hashtools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/hashtools/Makefile" ;;
     "tools/srchtools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/srchtools/Makefile" ;;
+    "tools/autotools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/autotools/Makefile" ;;
     "tools/sorter/Makefile") CONFIG_FILES="$CONFIG_FILES tools/sorter/Makefile" ;;
     "tools/timeline/Makefile") CONFIG_FILES="$CONFIG_FILES tools/timeline/Makefile" ;;
     "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
@@ -22092,7 +22033,9 @@ _LT_EOF
             echo "#include <unistd.h>" >> tsk3/tsk_incs.h
           fi
           if test x$ac_cv_header_inttypes_h = xyes; then
+            echo "#ifndef __STDC_FORMAT_MACROS" >> tsk3/tsk_incs.h
             echo "#define  __STDC_FORMAT_MACROS" >> tsk3/tsk_incs.h
+            echo "#endif" >> tsk3/tsk_incs.h
             echo "#include <inttypes.h>" >> tsk3/tsk_incs.h
           fi
           if test x$ac_cv_header_sys_param_h = xyes; then
diff --git a/configure.ac b/configure.ac
index 6bfd406..5579dd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,13 +4,14 @@
 
 AC_PREREQ(2.59)
 
-AC_INIT(sleuthkit, 3.1.3)
+AC_INIT(sleuthkit, 3.2.1)
 AC_CONFIG_SRCDIR([tsk3/base/tsk_base.h])
 AM_CONFIG_HEADER([tsk3/tsk_config.h])
 AC_CONFIG_AUX_DIR(config)
 AM_INIT_AUTOMAKE([foreign])
 AM_PROG_LIBTOOL
 AM_MAINTAINER_MODE
+AC_CONFIG_MACRO_DIR([m4])
 
 # Checks for programs.
 AC_PROG_CXX
@@ -56,7 +57,7 @@ AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
 #AC_FUNC_MEMCMP
 #AC_FUNC_MKTIME
 #AC_FUNC_MMAP
-AC_FUNC_REALLOC
+#AC_FUNC_REALLOC
 AC_FUNC_SELECT_ARGTYPES
 #AC_FUNC_STAT
 AC_FUNC_UTIME_NULL
@@ -124,6 +125,9 @@ AS_IF([test "x$with_libewf" != "xno"],
     )]
 )
 
+# sqlite requires pthread libraries - this was copied from its configure.ac
+AC_SEARCH_LIBS(pthread_create, pthread)
+AC_SEARCH_LIBS(dlopen, dl)
 
 AC_CONFIG_COMMANDS([tsk3/tsk_incs.h],
         [
@@ -136,7 +140,9 @@ AC_CONFIG_COMMANDS([tsk3/tsk_incs.h],
             echo "#include <unistd.h>" >> tsk3/tsk_incs.h
           fi
           if test x$ac_cv_header_inttypes_h = xyes; then
+            echo "#ifndef __STDC_FORMAT_MACROS" >> tsk3/tsk_incs.h
             echo "#define  __STDC_FORMAT_MACROS" >> tsk3/tsk_incs.h
+            echo "#endif" >> tsk3/tsk_incs.h
             echo "#include <inttypes.h>" >> tsk3/tsk_incs.h
           fi
           if test x$ac_cv_header_sys_param_h = xyes; then
@@ -158,12 +164,14 @@ AC_CONFIG_FILES([Makefile
                  tsk3/vs/Makefile
                  tsk3/fs/Makefile
                  tsk3/hashdb/Makefile
+                 tsk3/auto/Makefile
                  tools/Makefile
                  tools/imgtools/Makefile
                  tools/vstools/Makefile
                  tools/fstools/Makefile
                  tools/hashtools/Makefile
                  tools/srchtools/Makefile
+                 tools/autotools/Makefile
                  tools/sorter/Makefile
                  tools/timeline/Makefile
                  tests/Makefile
diff --git a/man/Makefile.am b/man/Makefile.am
index 408e794..0dd24e6 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,4 +1,5 @@
 dist_man_MANS = blkcalc.1 blkcat.1 blkls.1 blkstat.1 \
 		   ffind.1 fls.1 fsstat.1 hfind.1 icat.1 ifind.1 ils.1 \
 		   img_cat.1 img_stat.1 istat.1 jcat.1 jls.1 mactime.1 \
-		   mmls.1 mmstat.1 mmcat.1 sigfind.1 sorter.1
+		   mmls.1 mmstat.1 mmcat.1 sigfind.1 sorter.1 \
+           tsk_recover.1 tsk_gettimes.1 tsk_comparedir.1 tsk_loaddb.1
diff --git a/man/Makefile.in b/man/Makefile.in
index c2aa267..2f727a9 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -167,7 +167,8 @@ top_srcdir = @top_srcdir@
 dist_man_MANS = blkcalc.1 blkcat.1 blkls.1 blkstat.1 \
 		   ffind.1 fls.1 fsstat.1 hfind.1 icat.1 ifind.1 ils.1 \
 		   img_cat.1 img_stat.1 istat.1 jcat.1 jls.1 mactime.1 \
-		   mmls.1 mmstat.1 mmcat.1 sigfind.1 sorter.1
+		   mmls.1 mmstat.1 mmcat.1 sigfind.1 sorter.1 \
+           tsk_recover.1 tsk_gettimes.1 tsk_comparedir.1 tsk_loaddb.1
 
 all: all-am
 
diff --git a/man/blkls.1 b/man/blkls.1
index fab2f38..833f871 100644
--- a/man/blkls.1
+++ b/man/blkls.1
@@ -29,7 +29,7 @@ in TCT.
 
 .SH ARGUMENTS
 .IP -e
-Copy every block. The output should be similar to dd.
+Copy every block, including file system metadata blocks. The output is the entire file system. 
 .IP -a
 Display all allocated blocks (same as \-e if \-A is also given).
 .IP -A
diff --git a/man/img_cat.1 b/man/img_cat.1
index 7973670..8e8eaca 100644
--- a/man/img_cat.1
+++ b/man/img_cat.1
@@ -2,12 +2,12 @@
 .SH NAME
 img_cat \- Output contents of an image file.
 .SH SYNOPSIS
-.B img_cat [-i imgtype] [-b dev_sector_size]  [-vV] 
+.B img_cat [-i imgtype] [-b dev_sector_size] [-b start_sector] [-e stop_sector] [-vV] 
 .I image [images] 
 .SH DESCRIPTION
 .B img_cat
 outputs the contents of an image file.  Image files that are not raw will have embedded
-data and metadata.  img_cat will output only the metadata.  This allows you to convert 
+data and metadata.  img_cat will output only the data.  This allows you to convert 
 an embedded format to raw or to calculate the MD5 hash of the data by piping the output to
 the appropriate tool. 
 
@@ -16,6 +16,10 @@ the appropriate tool.
 Identify the type of image file, such as raw, split, or aff.  Use '\-i list' to list the supported types.  If not given, autodetection methods are used.
 .IP "-b dev_sector_size"
 The size, in bytes, of the underlying device sectors.  If not given, the value in the image format is used (if it exists) or 512-bytes is assumed.
+.IP "-s start_sector"
+The sector number to start at.
+.IP "-e stop_sector"
+The sector number to stop at.
 .IP -v
 Verbose output of debugging statements to stderr
 .IP -V
diff --git a/packages/sleuthkit.spec b/packages/sleuthkit.spec
index b92612c..258e03b 100644
--- a/packages/sleuthkit.spec
+++ b/packages/sleuthkit.spec
@@ -1,5 +1,5 @@
 Name:		sleuthkit	
-Version:	3.1.3
+Version:	3.2.1
 Release:	1%{?dist}
 Summary:	The Sleuth Kit (TSK) is a library and collection of command line tools that allow you to investigate volume and file system data.	
 
@@ -55,6 +55,8 @@ rm -rf $RPM_BUILD_ROOT
 /usr/include/tsk3/img/*
 %dir /usr/include/tsk3/vs
 /usr/include/tsk3/vs/*
+%dir /usr/include/tsk3/auto
+/usr/include/tsk3/auto/*
 %dir /usr/share/tsk3
 %dir /usr/share/tsk3/sorter
 /usr/share/tsk3/sorter/*
diff --git a/samples/Makefile.am b/samples/Makefile.am
index 8fbb8bd..7609444 100644
--- a/samples/Makefile.am
+++ b/samples/Makefile.am
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I.. -Wall 
+AM_CPPFLAGS = -I.. -I$(srcdir)/.. -Wall 
 LDADD = ../tsk3/libtsk3.la
 LDFLAGS = -static
 EXTRA_DIST = .indent.pro 
diff --git a/samples/Makefile.in b/samples/Makefile.in
index 7d569fe..724fe83 100644
--- a/samples/Makefile.in
+++ b/samples/Makefile.in
@@ -184,7 +184,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I.. -Wall 
+AM_CPPFLAGS = -I.. -I$(srcdir)/.. -Wall 
 LDADD = ../tsk3/libtsk3.la
 EXTRA_DIST = .indent.pro 
 posix_style_SOURCES = posix-style.cpp
diff --git a/tests/Makefile.am b/tests/Makefile.am
index bf58c0f..6581bf9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I.. -Wall 
+AM_CPPFLAGS = -I.. -I$(srcdir)/.. -Wall 
 LDADD = ../tsk3/libtsk3.la
 LDFLAGS = -static
 EXTRA_DIST = .indent.pro 
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 694925d..3c74909 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -191,7 +191,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I.. -Wall 
+AM_CPPFLAGS = -I.. -I$(srcdir)/.. -Wall 
 LDADD = ../tsk3/libtsk3.la
 EXTRA_DIST = .indent.pro 
 read_apis_SOURCES = read_apis.cpp
diff --git a/tests/fs_attrlist_apis.cpp b/tests/fs_attrlist_apis.cpp
index af73cd2..c0b9fa9 100644
--- a/tests/fs_attrlist_apis.cpp
+++ b/tests/fs_attrlist_apis.cpp
@@ -199,7 +199,7 @@ test_fat12()
     char fname[512];
 
     snprintf(fname, 512, "%s/fat12.dd", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         return 1;
@@ -238,7 +238,7 @@ test_ntfs_fe()
     char fname[512];
 
     snprintf(fname, 512, "%s/fe_test_1.img", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         return 1;
diff --git a/tests/fs_fname_apis.cpp b/tests/fs_fname_apis.cpp
index 215beaf..154208f 100644
--- a/tests/fs_fname_apis.cpp
+++ b/tests/fs_fname_apis.cpp
@@ -363,7 +363,7 @@ test_fat12()
     char fname[512];
 
     snprintf(fname, 512, "%s/fat12.dd", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         return 1;
@@ -401,7 +401,7 @@ test_ntfs_fe()
     char fname[512];
 
     snprintf(fname, 512, "%s/fe_test_1.img", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         return 1;
@@ -438,7 +438,7 @@ test_ntfs_comp()
     char fname[512];
 
     snprintf(fname, 512, "%s/ntfs-comp-1.img", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         return 1;
diff --git a/tests/read_apis.cpp b/tests/read_apis.cpp
index b5576e9..4e06807 100644
--- a/tests/read_apis.cpp
+++ b/tests/read_apis.cpp
@@ -207,7 +207,7 @@ test_fat12()
     char fname[512];
 
     snprintf(fname, 512, "%s/fat12.dd", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         tsk_error_reset();
@@ -246,7 +246,7 @@ test_fat_slack()
     ssize_t retval;
 
     snprintf(fname, 512, "%s/fat-img-kw.dd", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         tsk_error_reset();
@@ -340,7 +340,7 @@ test_fat_recover()
     ssize_t retval;
 
     snprintf(fname, 512, "%s/fe_test_1.img", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         tsk_error_reset();
@@ -480,7 +480,7 @@ test_ntfs_slack_ads()
     ssize_t retval;
 
     snprintf(fname, 512, "%s/ntfs-img-kw-1.dd", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         tsk_error_reset();
@@ -641,7 +641,7 @@ test_ntfs_fe()
     char fname[512];
 
     snprintf(fname, 512, "%s/fe_test_1.img", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         tsk_error_reset();
@@ -679,7 +679,7 @@ test_ntfs_comp()
     char fname[512];
 
     snprintf(fname, 512, "%s/ntfs-comp-1.img", s_root);
-    if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
+    if ((img = tsk_img_open_sing((const TSK_TCHAR *)fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) {
         fprintf(stderr, "Error opening %s image\n", tname);
         tsk_error_print(stderr);
         tsk_error_reset();
diff --git a/tools/Makefile.am b/tools/Makefile.am
index da145c9..a31392d 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1 +1 @@
-SUBDIRS = imgtools vstools fstools hashtools srchtools sorter timeline
+SUBDIRS = imgtools vstools fstools hashtools srchtools sorter timeline autotools
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 6962d32..a312087 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -171,7 +171,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-SUBDIRS = imgtools vstools fstools hashtools srchtools sorter timeline
+SUBDIRS = imgtools vstools fstools hashtools srchtools sorter timeline autotools
 all: all-recursive
 
 .SUFFIXES:
diff --git a/tools/fstools/Makefile.am b/tools/fstools/Makefile.am
index 0f449c5..d7e1c12 100644
--- a/tools/fstools/Makefile.am
+++ b/tools/fstools/Makefile.am
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I../.. -Wall 
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 LDADD = ../../tsk3/libtsk3.la
 LDFLAGS += -static
 EXTRA_DIST = .indent.pro fscheck.cpp
diff --git a/tools/fstools/Makefile.in b/tools/fstools/Makefile.in
index a338e48..9619c23 100644
--- a/tools/fstools/Makefile.in
+++ b/tools/fstools/Makefile.in
@@ -239,7 +239,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I../.. -Wall 
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 LDADD = ../../tsk3/libtsk3.la
 EXTRA_DIST = .indent.pro fscheck.cpp
 blkcalc_SOURCES = blkcalc.cpp
diff --git a/tools/fstools/blkls.cpp b/tools/fstools/blkls.cpp
index 2df50d4..feed765 100644
--- a/tools/fstools/blkls.cpp
+++ b/tools/fstools/blkls.cpp
@@ -37,7 +37,7 @@ usage()
         _TSK_T
         ("usage: %s [-aAelvV] [-f fstype] [-i imgtype] [-b dev_sector_size] [-o imgoffset] image [images] [start-stop]\n"),
         progname);
-    tsk_fprintf(stderr, "\t-e: every block\n");
+    tsk_fprintf(stderr, "\t-e: every block (including file system metadata blocks)\n");
     tsk_fprintf(stderr,
         "\t-l: print details in time machine list format\n");
     tsk_fprintf(stderr, "\t-a: Display allocated blocks\n");
diff --git a/tools/fstools/fls.cpp b/tools/fstools/fls.cpp
index e96236a..96c7bcb 100644
--- a/tools/fstools/fls.cpp
+++ b/tools/fstools/fls.cpp
@@ -75,7 +75,7 @@ main(int argc, char **argv1)
     TSK_FS_INFO *fs;
 
     TSK_INUM_T inode;
-    int name_flags = TSK_FS_NAME_FLAG_ALLOC | TSK_FS_NAME_FLAG_UNALLOC;
+    int name_flags = TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC;
     int ch;
     extern int OPTIND;
     int fls_flags;
@@ -123,7 +123,7 @@ main(int argc, char **argv1)
             }
             break;
         case _TSK_T('d'):
-            name_flags &= ~TSK_FS_NAME_FLAG_ALLOC;
+            name_flags &= ~TSK_FS_DIR_WALK_FLAG_ALLOC;
             break;
         case _TSK_T('D'):
             fls_flags &= ~TSK_FS_FLS_FILE;
@@ -180,7 +180,7 @@ main(int argc, char **argv1)
             sec_skew = TATOI(OPTARG);
             break;
         case _TSK_T('u'):
-            name_flags &= ~TSK_FS_NAME_FLAG_UNALLOC;
+            name_flags &= ~TSK_FS_DIR_WALK_FLAG_UNALLOC;
             break;
         case _TSK_T('v'):
             tsk_verbose++;
@@ -216,8 +216,8 @@ main(int argc, char **argv1)
      ** set and we are only displaying files or deleted files
      */
     if ((name_flags & TSK_FS_DIR_WALK_FLAG_RECURSE)
-        && (((name_flags & TSK_FS_NAME_FLAG_UNALLOC)
-                && (!(name_flags & TSK_FS_NAME_FLAG_ALLOC)))
+        && (((name_flags & TSK_FS_DIR_WALK_FLAG_UNALLOC)
+                && (!(name_flags & TSK_FS_DIR_WALK_FLAG_ALLOC)))
             || ((fls_flags & TSK_FS_FLS_FILE)
                 && (!(fls_flags & TSK_FS_FLS_DIR))))) {
 
@@ -301,7 +301,7 @@ main(int argc, char **argv1)
     }
 
     if (tsk_fs_fls(fs, (TSK_FS_FLS_FLAG_ENUM) fls_flags, inode,
-            (TSK_FS_NAME_FLAG_ENUM) name_flags, macpre, sec_skew)) {
+            (TSK_FS_DIR_WALK_FLAG_ENUM) name_flags, macpre, sec_skew)) {
         tsk_error_print(stderr);
         fs->close(fs);
         img->close(img);
diff --git a/tools/fstools/ifind.cpp b/tools/fstools/ifind.cpp
index 5575770..a5efaf5 100644
--- a/tools/fstools/ifind.cpp
+++ b/tools/fstools/ifind.cpp
@@ -265,12 +265,6 @@ main(int argc, char **argv1)
             img->close(img);
             exit(1);
         }
-        else if (block == 0) {
-            tsk_printf("Inode not found\n");
-            fs->close(fs);
-            img->close(img);
-            exit(1);
-        }
         if (tsk_fs_ifind_data(fs, (TSK_FS_IFIND_FLAG_ENUM) localflags,
                 block)) {
             tsk_error_print(stderr);
diff --git a/tools/hashtools/Makefile.am b/tools/hashtools/Makefile.am
index 9e717fa..73ce5a2 100644
--- a/tools/hashtools/Makefile.am
+++ b/tools/hashtools/Makefile.am
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I../.. -Wall 
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 LDADD = ../../tsk3/libtsk3.la
 LDFLAGS += -static
 EXTRA_DIST = .indent.pro md5.c sha1.c
diff --git a/tools/hashtools/Makefile.in b/tools/hashtools/Makefile.in
index 7824c1d..85377ba 100644
--- a/tools/hashtools/Makefile.in
+++ b/tools/hashtools/Makefile.in
@@ -182,7 +182,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I../.. -Wall 
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 LDADD = ../../tsk3/libtsk3.la
 EXTRA_DIST = .indent.pro md5.c sha1.c
 hfind_SOURCES = hfind.cpp
diff --git a/tools/imgtools/Makefile.am b/tools/imgtools/Makefile.am
index 1202557..0e0d04f 100644
--- a/tools/imgtools/Makefile.am
+++ b/tools/imgtools/Makefile.am
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I../.. -Wall
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall
 LDADD = ../../tsk3/libtsk3.la
 LDFLAGS += -static
 EXTRA_DIST = .indent.pro
diff --git a/tools/imgtools/Makefile.in b/tools/imgtools/Makefile.in
index 37c45f7..a86455c 100644
--- a/tools/imgtools/Makefile.in
+++ b/tools/imgtools/Makefile.in
@@ -186,7 +186,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I../.. -Wall
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall
 LDADD = ../../tsk3/libtsk3.la
 EXTRA_DIST = .indent.pro
 img_cat_SOURCES = img_cat.cpp
diff --git a/tools/imgtools/img_cat.cpp b/tools/imgtools/img_cat.cpp
index af5b838..d37b999 100644
--- a/tools/imgtools/img_cat.cpp
+++ b/tools/imgtools/img_cat.cpp
@@ -21,12 +21,16 @@ usage()
 {
     TFPRINTF(stderr,
         _TSK_T
-        ("usage: %s [-vV] [-i imgtype] [-b dev_sector_size] image\n"),
+        ("usage: %s [-vV] [-i imgtype] [-b dev_sector_size] [-b start_sector] [-e stop_sector] image\n"),
         progname);
     tsk_fprintf(stderr,
         "\t-i imgtype: The format of the image file (use 'i list' for supported types)\n");
     tsk_fprintf(stderr,
         "\t-b dev_sector_size: The size (in bytes) of the device sectors\n");
+    tsk_fprintf(stderr,
+        "\t-s start_sector: The sector number to start at\n");
+    tsk_fprintf(stderr,
+        "\t-e stop_sector:  The sector number to stop at\n");
     tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
     tsk_fprintf(stderr, "\t-V: Print version\n");
 
@@ -40,7 +44,8 @@ main(int argc, char **argv1)
     TSK_IMG_INFO *img;
     TSK_IMG_TYPE_ENUM imgtype = TSK_IMG_TYPE_DETECT;
     int ch;
-    TSK_OFF_T done;
+    TSK_OFF_T start_sector = 0;
+    TSK_OFF_T end_sector = 0;
     ssize_t cnt;
     TSK_TCHAR **argv;
     unsigned int ssize = 0;
@@ -59,7 +64,7 @@ main(int argc, char **argv1)
 
     progname = argv[0];
 
-    while ((ch = GETOPT(argc, argv, _TSK_T("b:i:vV"))) > 0) {
+    while ((ch = GETOPT(argc, argv, _TSK_T("b:i:vVs:e:"))) > 0) {
         switch (ch) {
         case _TSK_T('?'):
         default:
@@ -89,6 +94,29 @@ main(int argc, char **argv1)
             }
             break;
 
+        case _TSK_T('s'):
+            start_sector = TSTRTOUL(OPTARG, &cp, 0);
+            if (*cp || *cp == *OPTARG || start_sector < 1) {
+                TFPRINTF(stderr,
+                    _TSK_T
+                    ("invalid argument: start sector must be positive: %s\n"),
+                    OPTARG);
+                usage();
+            }
+            break;
+
+        case _TSK_T('e'):
+            end_sector = TSTRTOUL(OPTARG, &cp, 0);
+            if (*cp || *cp == *OPTARG || end_sector < 1) {
+                TFPRINTF(stderr,
+                    _TSK_T
+                    ("invalid argument: end sector must be positive: %s\n"),
+                    OPTARG);
+                usage();
+            }
+            break;
+
+
         case _TSK_T('v'):
             tsk_verbose++;
             break;
@@ -120,12 +148,23 @@ main(int argc, char **argv1)
     }
 #endif
 
-    for (done = 0; done < img->size; done += cnt) {
+    TSK_OFF_T start_byte = 0;
+    if (start_sector)
+        start_byte = start_sector * img->sector_size;
+
+    TSK_OFF_T end_byte = 0;
+    if (end_sector)
+        end_byte = (end_sector + 1) * img->sector_size;
+    else
+        end_byte = img->size;
+
+
+    for (TSK_OFF_T done = start_byte; done < end_byte; done += cnt) {
         char buf[16 * 1024];
         size_t len;
 
-        if (done + (TSK_OFF_T) sizeof(buf) > img->size) {
-            len = (size_t) (img->size - done);
+        if (done + (TSK_OFF_T) sizeof(buf) > end_byte) {
+            len = (size_t) (end_byte - done);
         }
         else {
             len = sizeof(buf);
diff --git a/tools/sorter/Makefile.am b/tools/sorter/Makefile.am
index b8982cc..8a8cdc3 100644
--- a/tools/sorter/Makefile.am
+++ b/tools/sorter/Makefile.am
@@ -7,7 +7,7 @@ sorter: sorter.base Makefile
 	@echo "my \$$BIN_DIR=\"$(bindir)\";" >> sorter
 	@echo "my \$$DATA_DIR=\"$(datadir)\";" >> sorter
 	@echo "my \$$VER=\"$(VERSION)\";" >> sorter
-	@cat sorter.base >> sorter
+	@cat $(srcdir)/sorter.base >> sorter
 	@chmod +x sorter
 
 indent:
diff --git a/tools/sorter/Makefile.in b/tools/sorter/Makefile.in
index 252a8eb..785c831 100644
--- a/tools/sorter/Makefile.in
+++ b/tools/sorter/Makefile.in
@@ -362,7 +362,7 @@ sorter: sorter.base Makefile
 	@echo "my \$$BIN_DIR=\"$(bindir)\";" >> sorter
 	@echo "my \$$DATA_DIR=\"$(datadir)\";" >> sorter
 	@echo "my \$$VER=\"$(VERSION)\";" >> sorter
-	@cat sorter.base >> sorter
+	@cat $(srcdir)/sorter.base >> sorter
 	@chmod +x sorter
 
 indent:
diff --git a/tools/srchtools/Makefile.am b/tools/srchtools/Makefile.am
index a5953a1..6228374 100644
--- a/tools/srchtools/Makefile.am
+++ b/tools/srchtools/Makefile.am
@@ -1,6 +1,6 @@
 bin_PROGRAMS = srch_strings sigfind
 EXTRA_DIST = .indent.pro
-AM_CPPFLAGS = -I../.. -Wall
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall
 
 srch_strings_SOURCES = srch_strings.c
 
diff --git a/tools/srchtools/Makefile.in b/tools/srchtools/Makefile.in
index f562d9e..e19ba50 100644
--- a/tools/srchtools/Makefile.in
+++ b/tools/srchtools/Makefile.in
@@ -197,7 +197,7 @@ target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 EXTRA_DIST = .indent.pro
-AM_CPPFLAGS = -I../.. -Wall
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall
 srch_strings_SOURCES = srch_strings.c
 sigfind_SOURCES = sigfind.cpp 
 sigfind_LDADD = ../../tsk3/libtsk3.la
diff --git a/tools/timeline/Makefile.am b/tools/timeline/Makefile.am
index 4e75c21..e6fbe77 100644
--- a/tools/timeline/Makefile.am
+++ b/tools/timeline/Makefile.am
@@ -5,7 +5,7 @@ EXTRA_DIST = mactime.base .perltidyrc
 mactime: mactime.base Makefile
 	@echo "#!$(PERL) -w" > mactime
 	@echo "my \$$VER=\"$(VERSION)\";" >> mactime 
-	@cat mactime.base >> mactime
+	@cat $(srcdir)/mactime.base >> mactime
 	@chmod +x mactime 
 
 indent:
diff --git a/tools/timeline/Makefile.in b/tools/timeline/Makefile.in
index fdf025b..71e7872 100644
--- a/tools/timeline/Makefile.in
+++ b/tools/timeline/Makefile.in
@@ -360,7 +360,7 @@ uninstall-am: uninstall-binSCRIPTS
 mactime: mactime.base Makefile
 	@echo "#!$(PERL) -w" > mactime
 	@echo "my \$$VER=\"$(VERSION)\";" >> mactime 
-	@cat mactime.base >> mactime
+	@cat $(srcdir)/mactime.base >> mactime
 	@chmod +x mactime 
 
 indent:
diff --git a/tools/timeline/mactime.base b/tools/timeline/mactime.base
index 8638f35..1cc3b6c 100644
--- a/tools/timeline/mactime.base
+++ b/tools/timeline/mactime.base
@@ -643,9 +643,12 @@ sub print_tl {
                 $file);
         }
         else {
-            printf("%s,%s,%s,%s,%s,%s,%s,%s\n",
+            # escape any quotes in filename
+            my $file_tmp = $file;
+            $file_tmp =~ s/\"/\"\"/g;
+            printf("%s,%s,%s,%s,%s,%s,%s,\"%s\"\n",
                 $old_date_string, $size, $mactime, $ls, $uids, $groups, $inode,
-                $file);
+                $file_tmp);
         }
     }
 
diff --git a/tools/vstools/Makefile.am b/tools/vstools/Makefile.am
index 9ed49dd..e55f74d 100644
--- a/tools/vstools/Makefile.am
+++ b/tools/vstools/Makefile.am
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I../.. -Wall 
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 LDADD = ../../tsk3/libtsk3.la
 LDFLAGS += -static
 EXTRA_DIST = .indent.pro
diff --git a/tools/vstools/Makefile.in b/tools/vstools/Makefile.in
index 2cfafc9..e118404 100644
--- a/tools/vstools/Makefile.in
+++ b/tools/vstools/Makefile.in
@@ -190,7 +190,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I../.. -Wall 
+AM_CPPFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 LDADD = ../../tsk3/libtsk3.la
 EXTRA_DIST = .indent.pro
 mmls_SOURCES = mmls.cpp
diff --git a/tsk3/Makefile.am b/tsk3/Makefile.am
index 8e8d2c1..5abe89b 100644
--- a/tsk3/Makefile.am
+++ b/tsk3/Makefile.am
@@ -1,14 +1,15 @@
 # Compile the sub directories
-SUBDIRS = base img vs fs hashdb
+SUBDIRS = base img vs fs hashdb auto
 
 # Merge the libraries into one
 lib_LTLIBRARIES = libtsk3.la
 libtsk3_la_SOURCES =
 libtsk3_la_LIBADD = base/libtskbase.la img/libtskimg.la \
-    vs/libtskvs.la fs/libtskfs.la hashdb/libtskhashdb.la
+    vs/libtskvs.la fs/libtskfs.la hashdb/libtskhashdb.la \
+    auto/libtskauto.la
 # current:revision:age
-libtsk3_la_LDFLAGS = -version-info 5:3:2
+libtsk3_la_LDFLAGS = -version-info 6:1:3
 
 EXTRA_DIST = tsk_tools_i.h docs/Doxyfile docs/main.dox \
     docs/basics.dox docs/img.dox docs/vs.dox docs/fs.dox \
-    docs/base.dox docs/hashdb.dox docs/footer.html
+    docs/base.dox docs/hashdb.dox docs/footer.html docs/auto.dox
diff --git a/tsk3/Makefile.in b/tsk3/Makefile.in
index 1584eef..a1aba2b 100644
--- a/tsk3/Makefile.in
+++ b/tsk3/Makefile.in
@@ -52,7 +52,8 @@ am__installdirs = "$(DESTDIR)$(libdir)"
 libLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libtsk3_la_DEPENDENCIES = base/libtskbase.la img/libtskimg.la \
-	vs/libtskvs.la fs/libtskfs.la hashdb/libtskhashdb.la
+	vs/libtskvs.la fs/libtskfs.la hashdb/libtskhashdb.la \
+	auto/libtskauto.la
 am_libtsk3_la_OBJECTS =
 libtsk3_la_OBJECTS = $(am_libtsk3_la_OBJECTS)
 libtsk3_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -201,19 +202,20 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 
 # Compile the sub directories
-SUBDIRS = base img vs fs hashdb
+SUBDIRS = base img vs fs hashdb auto
 
 # Merge the libraries into one
 lib_LTLIBRARIES = libtsk3.la
 libtsk3_la_SOURCES = 
 libtsk3_la_LIBADD = base/libtskbase.la img/libtskimg.la \
-    vs/libtskvs.la fs/libtskfs.la hashdb/libtskhashdb.la
+    vs/libtskvs.la fs/libtskfs.la hashdb/libtskhashdb.la \
+    auto/libtskauto.la
 
 # current:revision:age
-libtsk3_la_LDFLAGS = -version-info 5:3:2
+libtsk3_la_LDFLAGS = -version-info 6:1:3
 EXTRA_DIST = tsk_tools_i.h docs/Doxyfile docs/main.dox \
     docs/basics.dox docs/img.dox docs/vs.dox docs/fs.dox \
-    docs/base.dox docs/hashdb.dox docs/footer.html
+    docs/base.dox docs/hashdb.dox docs/footer.html docs/auto.dox
 
 all: tsk_config.h
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
diff --git a/tsk3/base/mymalloc.c b/tsk3/base/mymalloc.c
index 783eba0..7666444 100644
--- a/tsk3/base/mymalloc.c
+++ b/tsk3/base/mymalloc.c
@@ -73,7 +73,9 @@ tsk_malloc(size_t len)
         snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_malloc: %s",
             strerror(errno));
     }
-    memset(ptr, 0, len);
+    else {
+        memset(ptr, 0, len);
+    }
     return (ptr);
 }
 
diff --git a/tsk3/base/tsk_base.h b/tsk3/base/tsk_base.h
index bce02c0..0159e1d 100644
--- a/tsk3/base/tsk_base.h
+++ b/tsk3/base/tsk_base.h
@@ -38,11 +38,11 @@
  * 3.1.2b1 would be 0x03010201.  Snapshot from Jan 2, 2003 would be
  * 0xFF030102. 
  * See TSK_VERSION_STR for string form. */ 
-#define TSK_VERSION_NUM 0x030103ff
+#define TSK_VERSION_NUM 0x030201ff
 
 /** Version of code in string form. See TSK_VERSION_NUM for 
  * integer form. */
-#define TSK_VERSION_STR "3.1.3"
+#define TSK_VERSION_STR "3.2.1"
 
 
 /* include the TSK-specific header file that we created in autoconf
@@ -67,7 +67,8 @@ extern "C" {
     typedef enum {
         TSK_OK,                 ///< Ok -- success
         TSK_ERR,                ///< System error -- should abort
-        TSK_COR                 ///< Data is corrupt, can still process another set of data
+        TSK_COR,                 ///< Data is corrupt, can still process another set of data
+        TSK_STOP                ///< Stop further processing, not an error though. 
     } TSK_RETVAL_ENUM;
 
 
@@ -238,6 +239,7 @@ extern "C" {
 #define TSK_ERR_VS	0x04000000
 #define TSK_ERR_FS	0x08000000
 #define TSK_ERR_HDB	0x10000000
+#define TSK_ERR_AUTO 0x20000000
 #define TSK_ERR_MASK	0x00ffffff
 
 #define TSK_ERR_AUX_MALLOC	(TSK_ERR_AUX | 0)
@@ -304,6 +306,11 @@ extern "C" {
 #define TSK_ERR_HDB_CORRUPT     (TSK_ERR_HDB | 11)
 #define TSK_ERR_HDB_MAX		12
 
+#define TSK_ERR_AUTO_DB (TSK_ERR_AUTO | 0)
+#define TSK_ERR_AUTO_CORRUPT (TSK_ERR_AUTO | 1)
+#define TSK_ERR_AUTO_UNICODE (TSK_ERR_AUTO | 2)
+#define TSK_ERR_AUTO_NOTOPEN (TSK_ERR_AUTO | 3)
+#define TSK_ERR_AUTO_MAX 4
 //@}
 
 
diff --git a/tsk3/base/tsk_error.c b/tsk3/base/tsk_error.c
index ee7b941..3122f36 100644
--- a/tsk3/base/tsk_error.c
+++ b/tsk3/base/tsk_error.c
@@ -93,18 +93,18 @@ static const char *tsk_err_fs_str[TSK_ERR_FS_MAX] = {
     "Function/Feature not supported",
     "Invalid walk range",
     "Error reading image file",
-    "Invalid file offset",  // 5
-    "Invalid API argument",     
+    "Invalid file offset",      // 5
+    "Invalid API argument",
     "Invalid block address",
     "Invalid metadata address",
     "Error in metadata structure",
-    "Invalid magic value",  // 10
-    "Error extracting file from image", 
+    "Invalid magic value",      // 10
+    "Error extracting file from image",
     "Error writing data",
     "Error converting Unicode",
     "Error recovering deleted file",
-    "General file system error", // 15
-    "File system is corrupt",   
+    "General file system error",        // 15
+    "File system is corrupt",
     "Attribute not found in file",
 };
 
@@ -123,6 +123,13 @@ static const char *tsk_err_hdb_str[TSK_ERR_HDB_MAX] = {
     "Corrupt hash database"
 };
 
+static const char *tsk_err_auto_str[TSK_ERR_AUTO_MAX] = {
+    "Database Error",
+    "Corrupt file data",
+    "Error converting Unicode",
+    "Image not opened yet"
+};
+
 
 /**
  * \ingroup baselib
@@ -180,6 +187,14 @@ tsk_error_get()
             snprintf(&tsk_errstr_print[pidx], TSK_ERRSTR_PR_L - pidx,
                 "hashtools error: %" PRIu32, TSK_ERR_MASK & tsk_errno);
     }
+    else if (tsk_errno & TSK_ERR_AUTO) {
+        if ((TSK_ERR_MASK & tsk_errno) < TSK_ERR_AUTO_MAX)
+            snprintf(&tsk_errstr_print[pidx], TSK_ERRSTR_PR_L - pidx,
+                "%s", tsk_err_auto_str[tsk_errno & TSK_ERR_MASK]);
+        else
+            snprintf(&tsk_errstr_print[pidx], TSK_ERRSTR_PR_L - pidx,
+                "auto error: %" PRIu32, TSK_ERR_MASK & tsk_errno);
+    }
     else {
         snprintf(&tsk_errstr_print[pidx], TSK_ERRSTR_PR_L - pidx,
             "Unknown Error: %" PRIu32, tsk_errno);
diff --git a/tsk3/base/tsk_list.c b/tsk3/base/tsk_list.c
index a3b4a56..7e985ad 100644
--- a/tsk3/base/tsk_list.c
+++ b/tsk3/base/tsk_list.c
@@ -130,6 +130,7 @@ tsk_list_add(TSK_LIST ** a_tsk_list_head, uint64_t a_key)
         else if (a_key == tmp->next->key + 1) {
             tmp->next->key++;
             tmp->next->len++;
+            return 0;
         }
         // do we need a new bucket in between?
         else if (a_key > tmp->next->key) {
@@ -172,7 +173,8 @@ tsk_list_find(TSK_LIST * a_tsk_list_head, uint64_t a_key)
     tmp = a_tsk_list_head;
     while (tmp != NULL) {
         // check this bucket
-        if ((a_key <= tmp->key) && (a_key > tmp->key - tmp->len))
+        // use the key+1 and then subtract for unsigned cases when key-len == -1
+        if ((a_key <= tmp->key) && (a_key >= tmp->key + 1 - tmp->len))
             return 1;
 
         // Have we passed any potential buckets?
diff --git a/tsk3/docs/Doxyfile b/tsk3/docs/Doxyfile
index b0a4506..e0655bc 100644
--- a/tsk3/docs/Doxyfile
+++ b/tsk3/docs/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME           = "The Sleuth Kit"
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 
-PROJECT_NUMBER         = 3.1
+PROJECT_NUMBER         = 3.2
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # base path where the generated documentation will be put. 
@@ -186,7 +186,7 @@ ALIASES                =
 # For instance, some of the names that are used will be different. The list 
 # of all members will be omitted, etc.
 
-OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_FOR_C  = NO
 
 # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
 # sources only. Doxygen will then generate output that is more tailored for 
@@ -571,11 +571,13 @@ INPUT                  = tsk3/docs/main.dox \
                          tsk3/docs/vs.dox \
                          tsk3/docs/fs.dox \
                          tsk3/docs/hashdb.dox \
+                         tsk3/docs/auto.dox \
                          tsk3/base \
                          tsk3/fs \
                          tsk3/hashdb \
                          tsk3/img \
-                         tsk3/vs
+                         tsk3/vs \
+                         tsk3/auto
 
 # This tag can be used to specify the character encoding of the source files 
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
@@ -592,7 +594,7 @@ INPUT_ENCODING         = UTF-8
 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
 # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
 
-FILE_PATTERNS          = *.c \
+FILE_PATTERNS          = *.c *.cpp \
                          *.h
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories 
@@ -619,7 +621,7 @@ EXCLUDE_SYMLINKS       = NO
 # against the file with absolute path, so to exclude all test directories 
 # for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       = 
+EXCLUDE_PATTERNS       = */auto/sqlite3*
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
 # (namespaces, classes, functions, etc.) that should be excluded from the 
@@ -1260,7 +1262,7 @@ INCLUDE_FILE_PATTERNS  =
 # undefined via #undef or recursively expanded use the := operator 
 # instead of the = operator.
 
-PREDEFINED             = 
+PREDEFINED             = __cplusplus
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
diff --git a/tsk3/docs/base.dox b/tsk3/docs/base.dox
index e5e5547..fb89093 100644
--- a/tsk3/docs/base.dox
+++ b/tsk3/docs/base.dox
@@ -39,7 +39,7 @@ The TSK_STACK structure is used to prevent infinite loops when recursing into di
 The TSK library includes support to calculate MD5 and SHA-1 hashes.  To calculate the MD5 hash, a context must be first initialized with TSK_MD5_Init(). Data is added to the context with TSK_MD5_Update() and the hash is calculated with a call to TSK_MD5_Final().  A similar process is used for SHA-1 hashes using TSK_SHA_Init(), TSK_SHA_Update(), and TSK_SHA_Final(). 
 
 \section basic_version Version
-To get the version number of the TSK library, you can all the tsk_version_get_str() function to get a string representation.  Or, you can call tsk_version_print() to print the library name and version to a FILE handle. 
+To get the version number of the TSK library as a string, you can all the tsk_version_get_str() function to get a string representation.  Or, you can call tsk_version_print() to print the library name and version to a FILE handle.  There are also \#defines for the version as a string (in TSK_VERSION_STR) and as a number (in TSK_VERSION_NUM). 
 
 Next to \ref imgpage
 
diff --git a/tsk3/docs/basics.dox b/tsk3/docs/basics.dox
index 1310b4c..e316879 100644
--- a/tsk3/docs/basics.dox
+++ b/tsk3/docs/basics.dox
@@ -16,27 +16,37 @@ The next layer up is the <b>File System Layer</b>.  This layer focuses on proces
 
 There is an independent <b>Hash Database Layer</b> that handles hash databases, such as NSRL and md5sum outputs.  This API allows you to create an index of hashes and perform fast lookups of them.  These functions do not depend on the Disk Image, Volume System, or File System Layers. 
 
+There is also an <b>Automation Layer</b> that integrates all of the previous layers in an automated fashion.  It defines a C++ class named TskAuto that hides a lot of the details about analyzing file and volume systems. 
+
 A basic diagram of the relationship between these layers is shown here. Note that if a disk image file does not have a volume system, then we can use the File System Layer functions directly on it. 
 
 <pre>
-                        +================+
-                        |      Base      |
-                        +================+
-                          /            \  
-                         /              \
-               +==============+      +==================+
-               |  Disk Image  |      |   Hash Database  |
-               +==============+      +==================+
-                  /       |   
-                 /        | 
-    +===============+     |
-    | Volume System |     |
-    +===============+     | 
-                \         |
-                 \        |
-                +===============+  
-                |  File System  | 
-                +===============+ 
+
+ +==========================================================+
+ |                                                          | 
+ |                       +================+                 |
+ |                       |      Base      |                 |
+ |                       +================+                 |
+ |                         /            \                   |
+ |                        /              \                  |
+ |              +==============+      +==================+  |
+ |              |  Disk Image  |      |   Hash Database  |  |
+ |              +==============+      +==================+  |
+ |                 /       |                                |
+ |                /        |                                |
+ |   +===============+     |                                |
+ |   | Volume System |     |                                |
+ |   +===============+     |                                |
+ |               \         |                                |
+ |                \        |                                |
+ |               +===============+                          |
+ |               |  File System  |                          |
+ |               +===============+                          |
+ |                                                          |
+ |                                                          |
+ |                        Automation                        |
+ +==========================================================+
+
 </pre>
  
 
diff --git a/tsk3/docs/hashdb.dox b/tsk3/docs/hashdb.dox
index 3ed32a2..7af1649 100644
--- a/tsk3/docs/hashdb.dox
+++ b/tsk3/docs/hashdb.dox
@@ -23,5 +23,7 @@ An indexed database can be searched using either tsk_hdb_lookup_raw() or tsk_hdb
 
 Both functions can call a callback with details of entries that are found, or the QUICK flag can be given in which case the callback is not called and instead the return value of the function identifies if the hash is in the database or not. 
 
+Next to \ref autopage
+
 Back to \ref users_guide "Table of Contents"
 */
diff --git a/tsk3/docs/main.dox b/tsk3/docs/main.dox
index d19e0ff..4787254 100644
--- a/tsk3/docs/main.dox
+++ b/tsk3/docs/main.dox
@@ -16,6 +16,7 @@ The User's Guide describes the various components of TSK and how to use them.  I
   - \subpage vspage 
   - \subpage fspage 
   - \subpage hashdbpage
+  - \subpage autopage
 
 <h3>API Reference</h3>
 The API Reference lists the public API functions and the arguments and return values.  The Users's Guide should be read first so that the interaction and use of the functions are understood.  These pages can also be found in the <a href="modules.html">Modules</a> section.  
@@ -24,5 +25,7 @@ The API Reference lists the public API functions and the arguments and return va
   - \ref vslib
   - \ref fslib
   - \ref hashdblib
+  - \ref autolib
+
 */
 
diff --git a/tsk3/fs/Makefile.am b/tsk3/fs/Makefile.am
index 7b89cc3..b36bce9 100644
--- a/tsk3/fs/Makefile.am
+++ b/tsk3/fs/Makefile.am
@@ -1,4 +1,4 @@
-AM_CFLAGS = -I../.. -Wall 
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 EXTRA_DIST = .indent.pro
 
 noinst_LTLIBRARIES = libtskfs.la
diff --git a/tsk3/fs/Makefile.in b/tsk3/fs/Makefile.in
index c5a9f63..c962096 100644
--- a/tsk3/fs/Makefile.in
+++ b/tsk3/fs/Makefile.in
@@ -186,7 +186,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CFLAGS = -I../.. -Wall 
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 EXTRA_DIST = .indent.pro
 noinst_LTLIBRARIES = libtskfs.la
 # Note that the .h files are in the top-level Makefile
diff --git a/tsk3/fs/ext2fs_dent.c b/tsk3/fs/ext2fs_dent.c
index 8a4ea1d..895e288 100644
--- a/tsk3/fs/ext2fs_dent.c
+++ b/tsk3/fs/ext2fs_dent.c
@@ -35,7 +35,6 @@ ext2fs_dent_copy(EXT2FS_INFO * ext2fs,
     char *ext2_dent, TSK_FS_NAME * fs_name)
 {
     TSK_FS_INFO *fs = &(ext2fs->fs_info);
-    int i;
 
     if (ext2fs->deentry_type == EXT2_DE_V1) {
         ext2fs_dentry1 *dir = (ext2fs_dentry1 *) ext2_dent;
@@ -107,14 +106,6 @@ ext2fs_dent_copy(EXT2FS_INFO * ext2fs,
         }
     }
 
-    /* Clean up name */
-    i = 0;
-    while (fs_name->name[i] != '\0') {
-        if (TSK_IS_CNTRL(fs_name->name[i]))
-            fs_name->name[i] = '^';
-        i++;
-    }
-
     fs_name->flags = 0;
 
     return 0;
@@ -220,7 +211,7 @@ ext2fs_dent_parse_block(EXT2FS_INFO * ext2fs, TSK_FS_DIR * a_fs_dir,
         if (dellen <= 0) {
             if (reclen - minreclen >= EXT2FS_DIRSIZ_lcl(1))
                 dellen = reclen - minreclen;
-            else 
+            else
                 minreclen = reclen;
         }
     }
@@ -286,7 +277,7 @@ ext2fs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
         tsk_fs_dir_reset(fs_dir);
     }
     else {
-        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, 128)) == NULL) {
+        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
             return TSK_ERR;
         }
     }
@@ -341,9 +332,9 @@ ext2fs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
 
         retval_tmp =
             ext2fs_dent_parse_block(ext2fs, fs_dir,
-            (fs_dir->fs_file->
-                meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0,
-            &list_seen, dirptr, len);
+            (fs_dir->fs_file->meta->
+                flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, &list_seen,
+            dirptr, len);
 
         if (retval_tmp == TSK_ERR) {
             retval_final = TSK_ERR;
diff --git a/tsk3/fs/fatfs_dent.c b/tsk3/fs/fatfs_dent.c
index b94a6b4..a36f80b 100644
--- a/tsk3/fs/fatfs_dent.c
+++ b/tsk3/fs/fatfs_dent.c
@@ -78,7 +78,7 @@ find_parent_act(TSK_FS_FILE * fs_file, const char *a_path, void *ptr)
 }
 
 
-static uint8_t
+uint8_t
 fatfs_dir_buf_add(FATFS_INFO * fatfs, TSK_INUM_T par_inum,
     TSK_INUM_T dir_inum)
 {
@@ -190,10 +190,9 @@ fatfs_dent_parse_buf(FATFS_INFO * fatfs, TSK_FS_DIR * a_fs_dir, char *buf,
         /* cycle through the directory entries */
         for (idx = 0; idx < fatfs->dentry_cnt_se; idx++, dep++) {
             fatfs_dentry *dir;
-            int i;
 
             /* is it a valid dentry? */
-            if (0 == fatfs_isdentry(fatfs, dep)) {
+            if (0 == fatfs_isdentry(fatfs, dep, 1)) {
                 if (tsk_verbose)
                     tsk_fprintf(stderr,
                         "fatfs_dent_parse_buf: Entry %u is invalid\n",
@@ -294,8 +293,8 @@ fatfs_dent_parse_buf(FATFS_INFO * fatfs, TSK_FS_DIR * a_fs_dir, char *buf,
 
                     /* Convert the UTF16 to UTF8 */
                     UTF16 *name16 =
-                        (UTF16 *) ((uintptr_t) & lfninfo.
-                        name[lfninfo.start + 1]);
+                        (UTF16 *) ((uintptr_t) & lfninfo.name[lfninfo.
+                            start + 1]);
                     UTF8 *name8 = (UTF8 *) fs_name->name;
 
                     retVal =
@@ -322,14 +321,6 @@ fatfs_dent_parse_buf(FATFS_INFO * fatfs, TSK_FS_DIR * a_fs_dir, char *buf,
                     else
                         *name8 = '\0';
 
-                    /* Clean up name */
-                    i = 0;
-                    while (fs_name->name[i] != '\0') {
-                        if (TSK_IS_CNTRL(fs_name->name[i]))
-                            fs_name->name[i] = '^';
-                        i++;
-                    }
-
                     lfninfo.start = FATFS_MAXNAMLEN_UTF8 - 1;
                     name_ptr = fs_name->shrt_name;      // put 8.3 into shrt_name
                 }
@@ -378,14 +369,6 @@ fatfs_dent_parse_buf(FATFS_INFO * fatfs, TSK_FS_DIR * a_fs_dir, char *buf,
                 name_ptr[a] = '\0';
             }
 
-            /* Clean up name to remove control chars */
-            i = 0;
-            while (fs_name->name[i] != '\0') {
-                if (TSK_IS_CNTRL(fs_name->name[i]))
-                    fs_name->name[i] = '^';
-                i++;
-            }
-
             /* file type: FAT only knows DIR and FILE */
             if ((dir->attrib & FATFS_ATTR_DIRECTORY) ==
                 FATFS_ATTR_DIRECTORY)
@@ -623,31 +606,16 @@ fatfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
         tsk_fs_dir_reset(fs_dir);
     }
     else {
-        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, 128)) == NULL) {
+        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
             return TSK_ERR;
         }
     }
 
     //  handle the orphan directory if its contents were requested
     if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
-        size_t i;
-        TSK_RETVAL_ENUM retval2 = tsk_fs_dir_find_orphans(a_fs, fs_dir);
-
-        if (retval2 == TSK_ERR)
-            return retval2;
-
-        // update the directory to parent mapping (since we bypassed the code that does this in parse)
-        for (i = 0; i < fs_dir->names_used; i++) {
-            if (fs_dir->names[i].type == TSK_FS_NAME_TYPE_DIR) {
-                if (fatfs_dir_buf_add(fatfs, a_addr,
-                        fs_dir->names[i].meta_addr))
-                    return TSK_ERR;
-            }
-        }
-        return retval2;
+        return tsk_fs_dir_find_orphans(a_fs, fs_dir);
     }
 
-
     fs_dir->fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr);
     if (fs_dir->fs_file == NULL) {
         tsk_error_reset();
diff --git a/tsk3/fs/fatfs_meta.c b/tsk3/fs/fatfs_meta.c
index dee5eb6..2699609 100644
--- a/tsk3/fs/fatfs_meta.c
+++ b/tsk3/fs/fatfs_meta.c
@@ -791,10 +791,11 @@ fatfs_make_fat(FATFS_INFO * fatfs, uint8_t a_which, TSK_FS_META * fs_meta)
 /* 
  * Is the pointed to buffer a directory entry buffer? 
  *
+ * @param a_basic 1 if only basic tests should be performed. 
  * Returns 1 if it is, 0 if not
  */
 uint8_t
-fatfs_isdentry(FATFS_INFO * fatfs, fatfs_dentry * de)
+fatfs_isdentry(FATFS_INFO * fatfs, fatfs_dentry * de, uint8_t a_basic)
 {
     TSK_FS_INFO *fs = (TSK_FS_INFO *) & fatfs->fs_info;
     if (!de)
@@ -815,79 +816,83 @@ fatfs_isdentry(FATFS_INFO * fatfs, fatfs_dentry * de)
         return 1;
     }
     else {
-        if (de->lowercase & ~(FATFS_CASE_LOWER_ALL)) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: lower case all\n");
-            return 0;
-        }
-        else if (de->attrib & ~(FATFS_ATTR_ALL)) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: attribute all\n");
-            return 0;
-        }
-
-        // verify we do not have too many flags set
-        if (de->attrib & FATFS_ATTR_NORMAL) {
-            if ((de->attrib & FATFS_ATTR_VOLUME) ||
-                (de->attrib & FATFS_ATTR_DIRECTORY)) {
+        // the basic test is only for the 'essential data'.
+        if (a_basic == 0) {
+            if (de->lowercase & ~(FATFS_CASE_LOWER_ALL)) {
                 if (tsk_verbose)
-                    fprintf(stderr,
-                        "fatfs_isdentry: Normal and Vol/Dir\n");
+                    fprintf(stderr, "fatfs_isdentry: lower case all\n");
                 return 0;
             }
-        }
-        if (de->attrib & FATFS_ATTR_VOLUME) {
-            if ((de->attrib & FATFS_ATTR_DIRECTORY) ||
-                (de->attrib & FATFS_ATTR_READONLY) ||
-                (de->attrib & FATFS_ATTR_ARCHIVE)) {
+            else if (de->attrib & ~(FATFS_ATTR_ALL)) {
                 if (tsk_verbose)
-                    fprintf(stderr,
-                        "fatfs_isdentry: Vol and Dir/RO/Arch\n");
+                    fprintf(stderr, "fatfs_isdentry: attribute all\n");
                 return 0;
             }
-        }
 
-        /* The ctime, cdate, and adate fields are optional and 
-         * therefore 0 is a valid value
-         */
-        if ((tsk_getu16(fs->endian, de->ctime) != 0) &&
-            (FATFS_ISTIME(tsk_getu16(fs->endian, de->ctime)) == 0)) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: ctime\n");
-            return 0;
-        }
-        else if ((tsk_getu16(fs->endian, de->wtime) != 0) &&
-            (FATFS_ISTIME(tsk_getu16(fs->endian, de->wtime)) == 0)) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: wtime\n");
-            return 0;
-        }
-        else if ((tsk_getu16(fs->endian, de->cdate) != 0) &&
-            (FATFS_ISDATE(tsk_getu16(fs->endian, de->cdate)) == 0)) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: cdate\n");
-            return 0;
-        }
-        else if (de->ctimeten > 200) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: ctimeten\n");
-            return 0;
-        }
-        else if ((tsk_getu16(fs->endian, de->adate) != 0) &&
-            (FATFS_ISDATE(tsk_getu16(fs->endian, de->adate)) == 0)) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: adate\n");
-            return 0;
-        }
-        else if ((tsk_getu16(fs->endian, de->wdate) != 0) &&
-            (FATFS_ISDATE(tsk_getu16(fs->endian, de->wdate)) == 0)) {
-            if (tsk_verbose)
-                fprintf(stderr, "fatfs_isdentry: wdate\n");
-            return 0;
+            // verify we do not have too many flags set
+            if (de->attrib & FATFS_ATTR_NORMAL) {
+                if ((de->attrib & FATFS_ATTR_VOLUME) ||
+                    (de->attrib & FATFS_ATTR_DIRECTORY)) {
+                    if (tsk_verbose)
+                        fprintf(stderr,
+                            "fatfs_isdentry: Normal and Vol/Dir\n");
+                    return 0;
+                }
+            }
+            if (de->attrib & FATFS_ATTR_VOLUME) {
+                if ((de->attrib & FATFS_ATTR_DIRECTORY) ||
+                    (de->attrib & FATFS_ATTR_READONLY) ||
+                    (de->attrib & FATFS_ATTR_ARCHIVE)) {
+                    if (tsk_verbose)
+                        fprintf(stderr,
+                            "fatfs_isdentry: Vol and Dir/RO/Arch\n");
+                    return 0;
+                }
+            }
+        
+
+            /* The ctime, cdate, and adate fields are optional and 
+             * therefore 0 is a valid value
+             */
+            if ((tsk_getu16(fs->endian, de->ctime) != 0) &&
+                (FATFS_ISTIME(tsk_getu16(fs->endian, de->ctime)) == 0)) {
+                if (tsk_verbose)
+                    fprintf(stderr, "fatfs_isdentry: ctime\n");
+                return 0;
+            }
+            else if ((tsk_getu16(fs->endian, de->wtime) != 0) &&
+                (FATFS_ISTIME(tsk_getu16(fs->endian, de->wtime)) == 0)) {
+                if (tsk_verbose)
+                    fprintf(stderr, "fatfs_isdentry: wtime\n");
+                return 0;
+            }
+            else if ((tsk_getu16(fs->endian, de->cdate) != 0) &&
+                (FATFS_ISDATE(tsk_getu16(fs->endian, de->cdate)) == 0)) {
+                if (tsk_verbose)
+                    fprintf(stderr, "fatfs_isdentry: cdate\n");
+                return 0;
+            }
+            else if (de->ctimeten > 200) {
+                if (tsk_verbose)
+                    fprintf(stderr, "fatfs_isdentry: ctimeten\n");
+                return 0;
+            }
+            else if ((tsk_getu16(fs->endian, de->adate) != 0) &&
+                (FATFS_ISDATE(tsk_getu16(fs->endian, de->adate)) == 0)) {
+                if (tsk_verbose)
+                    fprintf(stderr, "fatfs_isdentry: adate\n");
+                return 0;
+            }
+            else if ((tsk_getu16(fs->endian, de->wdate) != 0) &&
+                (FATFS_ISDATE(tsk_getu16(fs->endian, de->wdate)) == 0)) {
+                if (tsk_verbose)
+                    fprintf(stderr, "fatfs_isdentry: wdate\n");
+                return 0;
+            }
         }
 
         /* verify the starting cluster is small enough */
-        else if ((FATFS_DENTRY_CLUST(fs, de) > (fatfs->lastclust)) &&
+        if ((FATFS_DENTRY_CLUST(fs, de) > (fatfs->lastclust)) &&
             (FATFS_ISEOF(FATFS_DENTRY_CLUST(fs, de), fatfs->mask) == 0)) {
             if (tsk_verbose)
                 fprintf(stderr, "fatfs_isdentry: start cluster\n");
@@ -1286,14 +1291,16 @@ fatfs_inode_walk(TSK_FS_INFO * fs, TSK_INUM_T start_inum,
         // cycle through the sectors read
         for (sidx = 0; sidx < sect_proc; sidx++) {
             TSK_INUM_T inum;
+            uint8_t isInDir;
 
             dep =
                 (fatfs_dentry *) & fatfs->dinodes[sidx << fatfs->ssize_sh];
 
             /* if we know it is not part of a directory and it is not valid dentires,
              * then skip it */
-            if ((isset(sect_alloc, sect) == 0) &&
-                (fatfs_isdentry(fatfs, dep) == 0)) {
+            isInDir = isset(sect_alloc, sect);
+            if ((isInDir == 0) &&
+                (fatfs_isdentry(fatfs, dep, 0) == 0)) {
                 sect++;
                 continue;
             }
@@ -1378,7 +1385,7 @@ fatfs_inode_walk(TSK_FS_INFO * fs, TSK_INUM_T start_inum,
                 }
 
                 /* Do a final sanity check */
-                if (0 == fatfs_isdentry(fatfs, dep))
+                if (0 == fatfs_isdentry(fatfs, dep, isInDir))
                     continue;
 
                 if ((retval2 =
@@ -1598,7 +1605,7 @@ fatfs_inode_lookup(TSK_FS_INFO * fs, TSK_FS_FILE * a_fs_file,
     }
 
     fatfs->dep = (fatfs_dentry *) & fatfs->dinodes[off];
-    if (fatfs_isdentry(fatfs, fatfs->dep)) {
+    if (fatfs_isdentry(fatfs, fatfs->dep, 1)) {
         if ((retval =
                 fatfs_dinode_copy(fatfs, a_fs_file->meta, fatfs->dep, sect,
                     inum)) != TSK_OK) {
diff --git a/tsk3/fs/ffs_dent.c b/tsk3/fs/ffs_dent.c
index 091f380..677ec95 100644
--- a/tsk3/fs/ffs_dent.c
+++ b/tsk3/fs/ffs_dent.c
@@ -33,7 +33,6 @@ static uint8_t
 ffs_dent_copy(FFS_INFO * ffs, char *ffs_dent, TSK_FS_NAME * fs_name)
 {
     TSK_FS_INFO *a_fs = &(ffs->fs_info);
-    int i;
 
     /* this one has the type field */
     if ((a_fs->ftype == TSK_FS_TYPE_FFS1)
@@ -104,14 +103,6 @@ ffs_dent_copy(FFS_INFO * ffs, char *ffs_dent, TSK_FS_NAME * fs_name)
         return 1;
     }
 
-    /* Clean up name */
-    i = 0;
-    while (fs_name->name[i] != '\0') {
-        if (TSK_IS_CNTRL(fs_name->name[i]))
-            fs_name->name[i] = '^';
-        i++;
-    }
-
     fs_name->flags = 0;
     return 0;
 }
@@ -193,6 +184,7 @@ ffs_dent_parse_block(FFS_INFO * ffs, TSK_FS_DIR * fs_dir, uint8_t a_is_del,
             return TSK_ERR;
         }
 
+
         /* Do we have a deleted entry? (are we in a deleted space) */
         if ((dellen > 0) || (inode == 0) || (a_is_del)) {
             fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC;
@@ -211,7 +203,7 @@ ffs_dent_parse_block(FFS_INFO * ffs, TSK_FS_DIR * fs_dir, uint8_t a_is_del,
         if (dellen <= 0) {
             if (reclen - minreclen >= FFS_DIRSIZ_lcl(1))
                 dellen = reclen - minreclen;
-            else 
+            else
                 minreclen = reclen;
         }
     }
@@ -276,7 +268,7 @@ ffs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
         tsk_fs_dir_reset(fs_dir);
     }
     else {
-        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, 128)) == NULL) {
+        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
             return TSK_ERR;
         }
     }
@@ -338,8 +330,8 @@ ffs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
 
         retval_tmp =
             ffs_dent_parse_block(ffs, fs_dir,
-            (fs_dir->fs_file->
-                meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0,
+            (fs_dir->fs_file->meta->
+                flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0,
             dirbuf + cidx * FFS_DIRBLKSIZ, len);
 
         if (retval_tmp == TSK_ERR) {
diff --git a/tsk3/fs/fls_lib.c b/tsk3/fs/fls_lib.c
index 8b5b0ec..ae47fcb 100644
--- a/tsk3/fs/fls_lib.c
+++ b/tsk3/fs/fls_lib.c
@@ -44,7 +44,7 @@ typedef struct {
 /* this is a wrapper type function that takes care of the runtime
  * flags
  * 
- * fs_attr should be set to NULL for all NTFS file systems
+ * fs_attr should be set to NULL for all non-NTFS file systems
  */
 static void
 printit(TSK_FS_FILE * fs_file, const char *a_path,
@@ -67,37 +67,13 @@ printit(TSK_FS_FILE * fs_file, const char *a_path,
 
 
     if (fls_data->flags & TSK_FS_FLS_MAC) {
-        if ((fls_data->sec_skew != 0) && (fs_file->meta)) {
-            fs_file->meta->mtime -= fls_data->sec_skew;
-            fs_file->meta->atime -= fls_data->sec_skew;
-            fs_file->meta->ctime -= fls_data->sec_skew;
-        }
-
-        tsk_fs_name_print_mac(stdout, fs_file, a_path, fs_file->fs_info,
-            fs_attr, fls_data->macpre);
-
-        if ((fls_data->sec_skew != 0) && (fs_file->meta)) {
-            fs_file->meta->mtime += fls_data->sec_skew;
-            fs_file->meta->atime += fls_data->sec_skew;
-            fs_file->meta->ctime += fls_data->sec_skew;
-        }
+        tsk_fs_name_print_mac(stdout, fs_file, a_path,
+            fs_attr, fls_data->macpre, fls_data->sec_skew);
     }
-
     else if (fls_data->flags & TSK_FS_FLS_LONG) {
-        if ((fls_data->sec_skew != 0) && (fs_file->meta)) {
-            fs_file->meta->mtime -= fls_data->sec_skew;
-            fs_file->meta->atime -= fls_data->sec_skew;
-            fs_file->meta->ctime -= fls_data->sec_skew;
-        }
-
         tsk_fs_name_print_long(stdout, fs_file, a_path, fs_file->fs_info,
-            fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0);
-
-        if ((fls_data->sec_skew != 0) && (fs_file->meta)) {
-            fs_file->meta->mtime += fls_data->sec_skew;
-            fs_file->meta->atime += fls_data->sec_skew;
-            fs_file->meta->ctime += fls_data->sec_skew;
-        }
+            fs_attr, TSK_FS_FLS_FULL & fls_data->flags ? 1 : 0,
+            fls_data->sec_skew);
     }
     else {
         tsk_fs_name_print(stdout, fs_file, a_path, fs_file->fs_info,
@@ -194,7 +170,7 @@ print_dent_act(TSK_FS_FILE * fs_file, const char *a_path, void *ptr)
 /* Returns 0 on success and 1 on error */
 uint8_t
 tsk_fs_fls(TSK_FS_INFO * fs, TSK_FS_FLS_FLAG_ENUM lclflags,
-    TSK_INUM_T inode, TSK_FS_NAME_FLAG_ENUM flags, TSK_TCHAR * tpre,
+    TSK_INUM_T inode, TSK_FS_DIR_WALK_FLAG_ENUM flags, TSK_TCHAR * tpre,
     int32_t skew)
 {
     FLS_DATA data;
diff --git a/tsk3/fs/fs_attr.c b/tsk3/fs/fs_attr.c
index 0a77317..2c09938 100644
--- a/tsk3/fs/fs_attr.c
+++ b/tsk3/fs/fs_attr.c
@@ -181,10 +181,12 @@ tsk_fs_attr_clear(TSK_FS_ATTR * a_fs_attr)
 static uint8_t
 fs_attr_put_name(TSK_FS_ATTR * fs_attr, const char *name)
 {
-    if (name == NULL) {
+    if ((name == NULL) || (strlen(name) == 0)) {
         if (fs_attr->name_size > 0) {
-            fs_attr->name[0] = '\0';
+            free(fs_attr->name);
+            fs_attr->name_size = 0;
         }
+        fs_attr->name = NULL;
         return 0;
     }
 
@@ -362,6 +364,19 @@ tsk_fs_attr_set_run(TSK_FS_FILE * a_fs_file, TSK_FS_ATTR * a_fs_attr,
     return 0;
 }
 
+static void
+dump_attr(TSK_FS_ATTR *a_fs_attr)
+{
+    TSK_FS_ATTR_RUN *cur_run;
+    cur_run = a_fs_attr->nrd.run;
+
+    fprintf(stderr, "Attribute Run Dump:\n");
+    for (cur_run = a_fs_attr->nrd.run; cur_run; cur_run = cur_run->next) {
+        fprintf(stderr, "  %"PRIuDADDR" to %"PRIuDADDR" %sFiller\n", 
+                cur_run->offset, cur_run->offset + cur_run->len - 1,
+                (cur_run->flags & TSK_FS_ATTR_RUN_FLAG_FILLER)?"":"Not");
+    }
+}
 
 /**
  * \internal
@@ -447,6 +462,7 @@ tsk_fs_attr_add_run(TSK_FS_INFO * a_fs, TSK_FS_ATTR * a_fs_attr,
                     PRIuOFF ") is larger than FILLER (%" PRIuOFF ") (%"
                     PRIuINUM ")", a_data_run_new->offset,
                     data_run_cur->offset, a_fs_attr->fs_file->meta->addr);
+                dump_attr(a_fs_attr);
                 return 1;
             }
 
@@ -530,7 +546,6 @@ tsk_fs_attr_add_run(TSK_FS_INFO * a_fs, TSK_FS_ATTR * a_fs_attr,
      * At this point data_run_prev is the end of the existing list or
      * 0 if there is no list
      */
-
     /* This is an error condition.  
      * It means that we cycled through the existing runs,
      * ended at a VCN that is larger than what we are adding,
@@ -555,6 +570,7 @@ tsk_fs_attr_add_run(TSK_FS_INFO * a_fs, TSK_FS_ATTR * a_fs_attr,
             "): No filler entry for %" PRIuDADDR ". Final: %" PRIuDADDR,
             a_fs_attr->fs_file->meta->addr, a_data_run_new->offset,
             data_run_prev->offset + data_run_prev->len);
+        dump_attr(a_fs_attr);
         return 1;
     }
 
@@ -1050,8 +1066,10 @@ tsk_fs_attr_read(const TSK_FS_ATTR * a_fs_attr, TSK_OFF_T a_offset,
         size_t len_remain;      // length remaining to copy
         size_t len_toread;      // length total to copy
 
-        if (((a_flags & TSK_FS_FILE_READ_FLAG_SLACK) && (a_offset >= a_fs_attr->nrd.allocsize)) ||
-            (!(a_flags & TSK_FS_FILE_READ_FLAG_SLACK) && (a_offset >= a_fs_attr->size))) {
+        if (((a_flags & TSK_FS_FILE_READ_FLAG_SLACK)
+                && (a_offset >= a_fs_attr->nrd.allocsize))
+            || (!(a_flags & TSK_FS_FILE_READ_FLAG_SLACK)
+                && (a_offset >= a_fs_attr->size))) {
             tsk_error_reset();
             tsk_errno = TSK_ERR_FS_READ_OFF;
             snprintf(tsk_errstr, TSK_ERRSTR_L,
@@ -1102,11 +1120,12 @@ tsk_fs_attr_read(const TSK_FS_ATTR * a_fs_attr, TSK_OFF_T a_offset,
 
             // see if we need to read the rest of this run and into the next or if it is all here
             len_inrun = len_remain;
-            if ((data_run_cur->len - blkoffset_inrun) * fs->block_size - byteoffset_toread <
-                len_remain)
+            if ((data_run_cur->len - blkoffset_inrun) * fs->block_size -
+                byteoffset_toread < len_remain)
                 len_inrun =
                     (size_t) ((data_run_cur->len -
-                        blkoffset_inrun) * fs->block_size - byteoffset_toread) ;
+                        blkoffset_inrun) * fs->block_size -
+                    byteoffset_toread);
 
             /* sparse files/runs just get 0s */
             if (data_run_cur->flags & TSK_FS_ATTR_RUN_FLAG_SPARSE) {
@@ -1172,9 +1191,10 @@ tsk_fs_attr_read(const TSK_FS_ATTR * a_fs_attr, TSK_OFF_T a_offset,
                             byteoffset_toread + len_inrun) >
                         a_fs_attr->nrd.initsize)
                     && ((a_flags & TSK_FS_FILE_READ_FLAG_SLACK) == 0)) {
-                    
-                    size_t uninit_off = a_fs_attr->nrd.initsize - 
-                        ((data_run_cur->offset + blkoffset_inrun) * fs->block_size +
+
+                    size_t uninit_off = a_fs_attr->nrd.initsize -
+                        ((data_run_cur->offset +
+                            blkoffset_inrun) * fs->block_size +
                         byteoffset_toread);
 
                     memset(&a_buf[len_toread - len_remain + uninit_off], 0,
diff --git a/tsk3/fs/fs_attrlist.c b/tsk3/fs/fs_attrlist.c
index be7bd08..3169c38 100644
--- a/tsk3/fs/fs_attrlist.c
+++ b/tsk3/fs/fs_attrlist.c
@@ -231,8 +231,7 @@ tsk_fs_attrlist_get(const TSK_FS_ATTRLIST * a_fs_attrlist,
             /* If we are looking for NTFS $Data, 
              * then return default when we see it */
             if ((fs_attr_cur->type == TSK_FS_ATTR_TYPE_NTFS_DATA) &&
-                (fs_attr_cur->name_size > 5) &&
-                (strncmp(fs_attr_cur->name, "$Data", 5) == 0)) {
+                (fs_attr_cur->name == NULL)) {
                 return fs_attr_cur;
             }
 
@@ -304,7 +303,7 @@ tsk_fs_attrlist_get_id(const TSK_FS_ATTRLIST * a_fs_attrlist,
  *
  * @param a_fs_attrlist Data list structure to search in
  * @param a_type Type of attribute to find
- * @param name Name of the attribute to find
+ * @param name Name of the attribute to find (NULL for an entry with no name)
  *
  * @return NULL is returned on error and if an entry could not be found.
  * tsk_errno will be set to TSK_ERR_FS_ATTR_NOTFOUND if entry could not be
@@ -317,7 +316,7 @@ tsk_fs_attrlist_get_name_type(const TSK_FS_ATTRLIST * a_fs_attrlist,
     TSK_FS_ATTR *fs_attr_cur;
     TSK_FS_ATTR *fs_attr_ok = NULL;
 
-    if ((!a_fs_attrlist) || (name == NULL)) {
+    if (!a_fs_attrlist) {
         tsk_error_reset();
         tsk_errno = TSK_ERR_FS_ARG;
         snprintf(tsk_errstr, TSK_ERRSTR_L,
@@ -329,21 +328,24 @@ tsk_fs_attrlist_get_name_type(const TSK_FS_ATTRLIST * a_fs_attrlist,
     for (fs_attr_cur = a_fs_attrlist->head; fs_attr_cur; fs_attr_cur =
         fs_attr_cur->next) {
         if ((fs_attr_cur->flags & TSK_FS_ATTR_INUSE) &&
-            (fs_attr_cur->type == a_type) &&
-            (fs_attr_cur->name_size > 0) &&
-            (!strcmp(fs_attr_cur->name, name))) {
-
-            /* If we are looking for NTFS $Data,
-             * then return default when we see it */
-            if ((fs_attr_cur->type == TSK_FS_ATTR_TYPE_NTFS_DATA) &&
-                (fs_attr_cur->name_size > 5) &&
-                (strncmp(fs_attr_cur->name, "$Data", 5) == 0)) {
-                return fs_attr_cur;
+            (fs_attr_cur->type == a_type)) {
+
+            if (((name == NULL) && (fs_attr_cur->name == NULL)) ||
+                ((name) && (fs_attr_cur->name)
+                    && (!strcmp(fs_attr_cur->name, name)))) {
+
+                /* If we are looking for NTFS $Data,
+                 * then return default when we see it */
+                if ((fs_attr_cur->type == TSK_FS_ATTR_TYPE_NTFS_DATA) &&
+                    (fs_attr_cur->name == NULL)) {
+                    return fs_attr_cur;
+                }
+
+                // make sure we return the lowest if multiple exist
+                if ((fs_attr_ok == NULL)
+                    || (fs_attr_ok->id > fs_attr_cur->id))
+                    fs_attr_ok = fs_attr_cur;
             }
-
-            // make sure we return the lowest if multiple exist
-            if ((fs_attr_ok == NULL) || (fs_attr_ok->id > fs_attr_cur->id))
-                fs_attr_ok = fs_attr_cur;
         }
     }
 
diff --git a/tsk3/fs/fs_dir.c b/tsk3/fs/fs_dir.c
index d898499..d9ad64d 100644
--- a/tsk3/fs/fs_dir.c
+++ b/tsk3/fs/fs_dir.c
@@ -15,15 +15,17 @@
  */
 
 #include "tsk_fs_i.h"
+#include "tsk_fatfs.h"
 
 /** \internal
-* Allocate a FS_DIR structure to load names into
+* Allocate a FS_DIR structure to load names into.  
 * 
+* @param a_addr Address of this directory. 
 * @param a_cnt target number of FS_DENT entries to fit in
 * @returns NULL on error
 */
 TSK_FS_DIR *
-tsk_fs_dir_alloc(TSK_FS_INFO * a_fs, size_t a_cnt)
+tsk_fs_dir_alloc(TSK_FS_INFO * a_fs, TSK_INUM_T a_addr, size_t a_cnt)
 {
     TSK_FS_DIR *fs_dir;
     size_t i;
@@ -42,6 +44,7 @@ tsk_fs_dir_alloc(TSK_FS_INFO * a_fs, size_t a_cnt)
         return NULL;
     }
     fs_dir->fs_info = a_fs;
+    fs_dir->addr = a_addr;
     fs_dir->tag = TSK_FS_DIR_TAG;
     for (i = 0; i < a_cnt; i++) {
         fs_dir->names[i].tag = TSK_FS_NAME_TAG;
@@ -99,6 +102,7 @@ tsk_fs_dir_reset(TSK_FS_DIR * a_fs_dir)
         a_fs_dir->fs_file = NULL;
     }
     a_fs_dir->names_used = 0;
+    a_fs_dir->addr = 0;
 }
 
 
@@ -129,6 +133,7 @@ tsk_fs_dir_copy(const TSK_FS_DIR * a_src_dir, TSK_FS_DIR * a_dst_dir)
     }
 
     a_dst_dir->names_used = a_src_dir->names_used;
+    a_dst_dir->addr = a_src_dir->addr;
     return 0;
 }
 
@@ -199,6 +204,10 @@ tsk_fs_dir_add(TSK_FS_DIR * a_fs_dir, const TSK_FS_NAME * a_fs_name)
     if (tsk_fs_name_copy(fs_name_dest, a_fs_name))
         return 1;
 
+    // add the parent address 
+    if (a_fs_dir->addr)
+        fs_name_dest->par_addr = a_fs_dir->addr;
+
     return 0;
 }
 
@@ -704,8 +713,6 @@ uint8_t
 tsk_fs_dir_make_orphan_dir_meta(TSK_FS_INFO * a_fs,
     TSK_FS_META * a_fs_meta)
 {
-    TSK_DADDR_T *addr_ptr;
-
     a_fs_meta->type = TSK_FS_META_TYPE_DIR;
     a_fs_meta->mode = 0;
     a_fs_meta->nlink = 1;
@@ -733,7 +740,7 @@ tsk_fs_dir_make_orphan_dir_meta(TSK_FS_INFO * a_fs,
     strncpy(a_fs_meta->name2->name, "$OrphanFiles",
         TSK_FS_META_NAME_LIST_NSIZE);
     if (a_fs_meta->content_len) {
-        addr_ptr = (TSK_DADDR_T *) a_fs_meta->content_ptr;
+        TSK_DADDR_T *addr_ptr = (TSK_DADDR_T *) a_fs_meta->content_ptr;
         addr_ptr[0] = 0;
     }
     a_fs_meta->size = 0;
@@ -799,9 +806,20 @@ load_orphan_dir_walk_cb(TSK_FS_FILE * a_fs_file, const char *a_path,
     FIND_ORPHAN_DATA *data = (FIND_ORPHAN_DATA *) a_ptr;
 
     // add this entry to the orphan list
-    if (a_fs_file->meta)
+    if (a_fs_file->meta) {
         tsk_list_add(&data->orphan_subdir_list, a_fs_file->meta->addr);
 
+        /* FAT file systems spend a lot of time hunting for parent 
+         * directory addresses, so we put this code in here to save
+         * the info when we have it. */
+        if ((a_fs_file->meta->type == TSK_FS_META_TYPE_DIR)
+            && (TSK_FS_TYPE_ISFAT(a_fs_file->fs_info->ftype))) {
+            if (fatfs_dir_buf_add((FATFS_INFO *) a_fs_file->fs_info,
+                    a_fs_file->name->par_addr, a_fs_file->meta->addr))
+                return TSK_WALK_ERROR;
+        }
+    }
+
     return TSK_WALK_CONT;
 }
 
@@ -841,6 +859,15 @@ find_orphan_meta_walk_cb(TSK_FS_FILE * a_fs_file, void *a_ptr)
     if (tsk_fs_dir_add(data->fs_dir, data->fs_name))
         return TSK_WALK_ERROR;
 
+    /* FAT file systems spend a lot of time hunting for parent 
+     * directory addresses, so we put this code in here to save
+     * the info when we have it. */
+    if (TSK_FS_TYPE_ISFAT(fs->ftype)) {
+        if (fatfs_dir_buf_add((FATFS_INFO *) fs,
+                TSK_FS_ORPHANDIR_INUM(fs), a_fs_file->meta->addr))
+            return TSK_WALK_ERROR;
+    }
+
     /* Go into directories to mark their contents as "seen" */
     if (a_fs_file->meta->type == TSK_FS_META_TYPE_DIR) {
 
@@ -931,7 +958,7 @@ tsk_fs_dir_find_orphans(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir)
 
     // make copy of this so that we don't need to do it again. 
     if ((a_fs->orphan_dir =
-            tsk_fs_dir_alloc(a_fs, a_fs_dir->names_used)) == NULL) {
+            tsk_fs_dir_alloc(a_fs, a_fs_dir->addr, a_fs_dir->names_used)) == NULL) {
         a_fs->isOrphanHunting = 0;
         return TSK_ERR;
     }
diff --git a/tsk3/fs/fs_name.c b/tsk3/fs/fs_name.c
index 86fb5e5..558790f 100644
--- a/tsk3/fs/fs_name.c
+++ b/tsk3/fs/fs_name.c
@@ -110,6 +110,7 @@ tsk_fs_name_reset(TSK_FS_NAME * a_fs_name)
 
     a_fs_name->meta_addr = 0;
     a_fs_name->meta_seq = 0;
+    a_fs_name->par_addr = 0;
     a_fs_name->type = 0;
     a_fs_name->flags = 0;
 }
@@ -194,6 +195,7 @@ tsk_fs_name_copy(TSK_FS_NAME * a_fs_name_to,
 
     a_fs_name_to->meta_addr = a_fs_name_from->meta_addr;
     a_fs_name_to->meta_seq = a_fs_name_from->meta_seq;
+    a_fs_name_to->par_addr = a_fs_name_from->par_addr;
     a_fs_name_to->type = a_fs_name_from->type;
     a_fs_name_to->flags = a_fs_name_from->flags;
 
@@ -338,6 +340,8 @@ tsk_fs_name_print(FILE * hFile, const TSK_FS_FILE * fs_file,
     const char *a_path, TSK_FS_INFO * fs, const TSK_FS_ATTR * fs_attr,
     uint8_t print_path)
 {
+    size_t i;
+
     /* type of file - based on dentry type */
     if (fs_file->name->type < TSK_FS_NAME_TYPE_STR_MAX)
         tsk_fprintf(hFile, "%s/",
@@ -391,10 +395,21 @@ tsk_fs_name_print(FILE * hFile, const TSK_FS_FILE * fs_file,
                 name->flags & TSK_FS_NAME_FLAG_UNALLOC)) ? "(realloc)" :
         "");
 
-    if ((print_path) && (a_path != NULL))
-        tsk_fprintf(hFile, "%s", a_path);
+    if ((print_path) && (a_path != NULL)) {
+        for (i = 0; i < strlen(a_path); i++) {
+            if (TSK_IS_CNTRL(a_path[i]))
+                tsk_fprintf(hFile, "^");
+            else
+                tsk_fprintf(hFile, "%c", a_path[i]);
+        }
+    }
 
-    tsk_fprintf(hFile, "%s", fs_file->name->name);
+    for (i = 0; i < strlen(fs_file->name->name); i++) {
+        if (TSK_IS_CNTRL(fs_file->name->name[i]))
+            tsk_fprintf(hFile, "^");
+        else
+            tsk_fprintf(hFile, "%c", fs_file->name->name[i]);
+    }
 
 /*  This will add the short name in parentheses
     if (fs_file->name->shrt_name != NULL && fs_file->name->shrt_name[0] != '\0')
@@ -402,12 +417,17 @@ tsk_fs_name_print(FILE * hFile, const TSK_FS_FILE * fs_file,
 */
 
     /* print the data stream name if we the non-data NTFS stream */
-    if (fs_attr) {
-        if (((fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_DATA) &&
-                (strcmp(fs_attr->name, "$Data") != 0)) ||
-            ((fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_IDXROOT) &&
-                (strcmp(fs_attr->name, "$I30") != 0)))
-            tsk_fprintf(hFile, ":%s", fs_attr->name);
+    if ((fs_attr) && (fs_attr->name)) {
+        if ((fs_attr->type != TSK_FS_ATTR_TYPE_NTFS_IDXROOT) ||
+            (strcmp(fs_attr->name, "$I30") != 0)) {
+            tsk_fprintf(hFile, ":");
+            for (i = 0; i < strlen(fs_attr->name); i++) {
+                if (TSK_IS_CNTRL(fs_attr->name[i]))
+                    tsk_fprintf(hFile, "^");
+                else
+                    tsk_fprintf(hFile, "%c", fs_attr->name[i]);
+            }
+        }
     }
 
     return;
@@ -425,7 +445,7 @@ tsk_fs_name_print(FILE * hFile, const TSK_FS_FILE * fs_file,
 void
 tsk_fs_name_print_long(FILE * hFile, const TSK_FS_FILE * fs_file,
     const char *a_path, TSK_FS_INFO * fs, const TSK_FS_ATTR * fs_attr,
-    uint8_t print_path)
+    uint8_t print_path, int32_t sec_skew)
 {
     tsk_fs_name_print(hFile, fs_file, a_path, fs, fs_attr, print_path);
 
@@ -447,20 +467,29 @@ tsk_fs_name_print_long(FILE * hFile, const TSK_FS_FILE * fs_file,
 
         /* MAC times */
         tsk_fprintf(hFile, "\t");
-        tsk_fs_print_time(hFile, fs_file->meta->mtime);
+        if (fs_file->meta->mtime)
+            tsk_fs_print_time(hFile, fs_file->meta->mtime - sec_skew);
+        else
+            tsk_fs_print_time(hFile, fs_file->meta->mtime);
 
         tsk_fprintf(hFile, "\t");
         /* FAT only gives the day of last access */
-        if (TSK_FS_TYPE_ISFAT(fs->ftype))
+        if ((TSK_FS_TYPE_ISFAT(fs->ftype)) || (fs_file->meta->atime == 0))
             tsk_fs_print_day(hFile, fs_file->meta->atime);
         else
-            tsk_fs_print_time(hFile, fs_file->meta->atime);
+            tsk_fs_print_time(hFile, fs_file->meta->atime - sec_skew);
 
         tsk_fprintf(hFile, "\t");
-        tsk_fs_print_time(hFile, fs_file->meta->ctime);
+        if (fs_file->meta->ctime)
+            tsk_fs_print_time(hFile, fs_file->meta->ctime - sec_skew);
+        else
+            tsk_fs_print_time(hFile, fs_file->meta->ctime);
 
         tsk_fprintf(hFile, "\t");
-        tsk_fs_print_time(hFile, fs_file->meta->crtime);
+        if (fs_file->meta->crtime)
+            tsk_fs_print_time(hFile, fs_file->meta->crtime - sec_skew);
+        else
+            tsk_fs_print_time(hFile, fs_file->meta->crtime);
 
         /* use the stream size if one was given */
         if (fs_attr)
@@ -480,27 +509,26 @@ tsk_fs_name_print_long(FILE * hFile, const TSK_FS_FILE * fs_file,
  * \internal
  *
 ** Print output in the format that mactime reads.
-** This allows the deleted files to be inserted to get a better
-** picture of what happened
-**
-** Prepend a_path when printing full file name
-**  dir needs to end with "/" 
-**
-** prepend *prefix to path as the mounting point that the original
-** grave-robber was run on
 **
 ** If the flags in the fs_file->meta structure are set to FS_FLAG_ALLOC
 ** then it is assumed that the inode has been reallocated and the
 ** contents are not displayed
 **
-** fs is not required (only used for block size).  
+** fs is not required (only used for block size).
+ * @param hFile handle to print results to
+ * @param fs_file File to print details about
+ * @param a_path Parent directory of file (needs to end with "/")
+ * @param fs_attr Attribute in file that is being called for (NULL for non-NTFS)
+ * @param prefix Path of mounting point for image
+ * @param time_skew number of seconds skew to adjust time
 */
 void
 tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file,
-    const char *a_path, TSK_FS_INFO * fs, const TSK_FS_ATTR * fs_attr,
-    const char *prefix)
+    const char *a_path, const TSK_FS_ATTR * fs_attr,
+    const char *prefix, int32_t time_skew)
 {
     char ls[12];
+    size_t i;
 
     if ((!hFile) || (!fs_file))
         return;
@@ -509,14 +537,37 @@ tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file,
     tsk_fprintf(hFile, "0|");
 
     /* file name */
-    tsk_fprintf(hFile, "%s%s%s", prefix, a_path, fs_file->name->name);
+    tsk_fprintf(hFile, "%s", prefix);
+
+    // remove any control chars as we print the names
+    if (a_path != NULL) {
+        for (i = 0; i < strlen(a_path); i++) {
+            if (TSK_IS_CNTRL(a_path[i]))
+                tsk_fprintf(hFile, "^");
+            else
+                tsk_fprintf(hFile, "%c", a_path[i]);
+        }
+    }
+
+    for (i = 0; i < strlen(fs_file->name->name); i++) {
+        if (TSK_IS_CNTRL(fs_file->name->name[i]))
+            tsk_fprintf(hFile, "^");
+        else
+            tsk_fprintf(hFile, "%c", fs_file->name->name[i]);
+    }
 
     /* print the data stream name if it exists and is not the default NTFS */
-    if ((fs_attr) && (((fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_DATA) &&
-                (strcmp(fs_attr->name, "$Data") != 0)) ||
-            ((fs_attr->type == TSK_FS_ATTR_TYPE_NTFS_IDXROOT) &&
-                (strcmp(fs_attr->name, "$I30") != 0))))
-        tsk_fprintf(hFile, ":%s", fs_attr->name);
+    if ((fs_attr) && (fs_attr->name) &&
+        ((fs_attr->type != TSK_FS_ATTR_TYPE_NTFS_IDXROOT) ||
+            (strcmp(fs_attr->name, "$I30") != 0))) {
+        tsk_fprintf(hFile, ":");
+        for (i = 0; i < strlen(fs_attr->name); i++) {
+            if (TSK_IS_CNTRL(fs_attr->name[i]))
+                tsk_fprintf(hFile, "^");
+            else
+                tsk_fprintf(hFile, "%c", fs_attr->name[i]);
+        }
+    }
 
     if ((fs_file->meta)
         && (fs_file->meta->type == TSK_FS_META_TYPE_LNK)
@@ -568,11 +619,24 @@ tsk_fs_name_print_mac(FILE * hFile, const TSK_FS_FILE * fs_file,
             tsk_fprintf(hFile, "%" PRIuOFF "|", fs_file->meta->size);
 
         /* atime, mtime, ctime, crtime */
-        tsk_fprintf(hFile,
-            "%" PRIu32 "|%" PRIu32 "|%" PRIu32 "|%" PRIu32 "\n",
-            (uint32_t) fs_file->meta->atime,
-            (uint32_t) fs_file->meta->mtime,
-            (uint32_t) fs_file->meta->ctime,
-            (uint32_t) fs_file->meta->crtime);
+        if (fs_file->meta->atime)
+            tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->atime - time_skew);
+        else
+            tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->atime);
+
+        if (fs_file->meta->mtime)
+            tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->mtime - time_skew);
+        else
+            tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->mtime);
+        
+        if (fs_file->meta->ctime)
+            tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->ctime - time_skew);
+        else
+            tsk_fprintf(hFile, "%" PRIu32 "|", fs_file->meta->ctime);
+        
+        if (fs_file->meta->crtime)
+            tsk_fprintf(hFile, "%" PRIu32 "\n", fs_file->meta->crtime - time_skew);
+        else
+            tsk_fprintf(hFile, "%" PRIu32 "\n", fs_file->meta->crtime);
     }
 }
diff --git a/tsk3/fs/hfs.c b/tsk3/fs/hfs.c
index 31dca2f..d3e0214 100644
--- a/tsk3/fs/hfs.c
+++ b/tsk3/fs/hfs.c
@@ -2509,17 +2509,21 @@ hfs_fsstat(TSK_FS_INFO * fs, FILE * hFile)
     tsk_fprintf(hFile, "File System Version: ");
     switch (tsk_getu16(fs->endian, hfs->fs->version)) {
     case 4:
-        tsk_fprintf(hFile, " HFS+\n");
+        tsk_fprintf(hFile, "HFS+\n");
         break;
     case 5:
-        tsk_fprintf(hFile, " HFSX\n");
+        tsk_fprintf(hFile, "HFSX\n");
         break;
     default:
-        tsk_fprintf(hFile, " Unknown (%" PRIu16 ")\n",
+        tsk_fprintf(hFile, "Unknown (%" PRIu16 ")\n",
             tsk_getu16(fs->endian, hfs->fs->version));
         break;
     }
 
+    if (tsk_getu16(fs->endian, hfs->fs->signature) == HFS_VH_SIG_HFSX) {
+        tsk_fprintf(hFile, "Case Sensitive: %s\n",
+            hfs->is_case_sensitive ? "yes" : "no");
+    }
 
     if (hfs->hfs_wrapper_offset > 0) {
         tsk_fprintf(hFile,
diff --git a/tsk3/fs/hfs_dent.c b/tsk3/fs/hfs_dent.c
index b431e0d..626be87 100644
--- a/tsk3/fs/hfs_dent.c
+++ b/tsk3/fs/hfs_dent.c
@@ -89,15 +89,18 @@ uint8_t
 hfs_uni2ascii(TSK_FS_INFO * fs, uint8_t * uni, int ulen, char *asc,
     int alen)
 {
-    char *aptr;
+    UTF8 *ptr8;
     uint8_t *uniclean;
-    uint8_t *uptr;
+    UTF16 *ptr16;
     int i;
     TSKConversionResult r;
 
     // remove nulls from the Unicode string
     // convert / to :
     uniclean = (uint8_t *) tsk_malloc(ulen * 2);
+    if (!uniclean)
+        return 1;
+
     memcpy(uniclean, uni, ulen * 2);
     for (i = 0; i < ulen; ++i) {
         uint16_t uc = tsk_getu16(fs->endian, uniclean + i * 2);
@@ -115,22 +118,22 @@ hfs_uni2ascii(TSK_FS_INFO * fs, uint8_t * uni, int ulen, char *asc,
                 tsk_getu16(fs->endian, (uint8_t *) & uc);
     }
 
+    // convert to UTF-8
     memset(asc, 0, alen);
-    aptr = asc;
-    uptr = uniclean;
-    r = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &uptr,
-        (const UTF16 *) (uptr + ulen * 2), (UTF8 **) & aptr,
-        (UTF8 *) aptr + alen - 1, TSKstrictConversion);
+    ptr8 = (UTF8 *) asc;
+    ptr16 = (UTF16 *) uniclean;
+    r = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &ptr16,
+        (const UTF16 *) (&uniclean[ulen * 2]), &ptr8,
+        (UTF8 *) & asc[alen], TSKstrictConversion);
 
+    free(uniclean);
     if (r != TSKconversionOK) {
         tsk_errno = TSK_ERR_FS_UNICODE;
         snprintf(tsk_errstr, TSK_ERRSTR_L,
-            "hfs_uni2ascii: unicode conversion failed (%d)", (int)r);
-        free(uniclean);
+            "hfs_uni2ascii: unicode conversion failed (%d)", (int) r);
         return 1;
     }
 
-    free(uniclean);
     return 0;
 }
 
@@ -340,7 +343,7 @@ hfs_dir_open_meta(TSK_FS_INFO * fs, TSK_FS_DIR ** a_fs_dir,
     if (fs_dir) {
         tsk_fs_dir_reset(fs_dir);
     }
-    else if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(fs, 128)) == NULL) {
+    else if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(fs, a_addr, 128)) == NULL) {
         return TSK_ERR;
     }
 
diff --git a/tsk3/fs/ifind_lib.c b/tsk3/fs/ifind_lib.c
index 13b5acf..fe3a5bf 100644
--- a/tsk3/fs/ifind_lib.c
+++ b/tsk3/fs/ifind_lib.c
@@ -86,7 +86,7 @@ ifind_par_act(TSK_FS_FILE * fs_file, void *ptr)
 
                     if (data->flags & TSK_FS_IFIND_PAR_LONG) {
                         tsk_fs_name_print_long(stdout, fs_file, NULL,
-                            fs_file->fs_info, fs_attr, 0);
+                            fs_file->fs_info, fs_attr, 0, 0);
                     }
                     else {
                         tsk_fs_name_print(stdout, fs_file, NULL,
@@ -101,7 +101,7 @@ ifind_par_act(TSK_FS_FILE * fs_file, void *ptr)
             if (printed == 0) {
                 if (data->flags & TSK_FS_IFIND_PAR_LONG) {
                     tsk_fs_name_print_long(stdout, fs_file, NULL,
-                        fs_file->fs_info, NULL, 0);
+                        fs_file->fs_info, NULL, 0, 0);
                 }
                 else {
                     tsk_fs_name_print(stdout, fs_file, NULL,
@@ -477,39 +477,16 @@ ifind_data_file_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off,
     TSK_FS_INFO *fs = fs_file->fs_info;
     IFIND_DATA_DATA *data = (IFIND_DATA_DATA *) ptr;
 
-    /* Drop references to block zero (sparse)
-     * This becomes an issue with fragments and looking for fragments
-     * within the first block.  They will be triggered by sparse 
-     * entries, even though the first block can not be allocated
-     */
-    if (!addr)
+    /* Ignore sparse blocks because they do not reside on disk */
+    if (flags & TSK_FS_BLOCK_FLAG_SPARSE)
         return TSK_WALK_CONT;
 
-    if ((data->block >= addr) &&
-        (data->block <
-            (addr + (size + fs->block_size - 1) / fs->block_size))) {
-        tsk_printf("%" PRIuINUM "\n", data->curinode);
-        data->found = 1;
-        return TSK_WALK_STOP;
-    }
-    return TSK_WALK_CONT;
-}
-
-
-/* 
- * file_walk action callback for ntfs  
- *
- */
-static TSK_WALK_RET_ENUM
-ifind_data_file_ntfs_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off,
-    TSK_DADDR_T addr, char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM flags,
-    void *ptr)
-{
-    IFIND_DATA_DATA *data = (IFIND_DATA_DATA *) ptr;
-
     if (addr == data->block) {
-        tsk_printf("%" PRIuINUM "-%" PRIu32 "-%" PRIu16 "\n",
-            data->curinode, data->curtype, data->curid);
+        if (TSK_FS_TYPE_ISNTFS(fs->ftype))
+            tsk_printf("%" PRIuINUM "-%" PRIu32 "-%" PRIu16 "\n",
+                data->curinode, data->curtype, data->curid);
+        else
+            tsk_printf("%" PRIuINUM "\n", data->curinode);
         data->found = 1;
         return TSK_WALK_STOP;
     }
@@ -517,7 +494,6 @@ ifind_data_file_ntfs_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off,
 }
 
 
-
 /*
 ** find_inode
 **
@@ -527,88 +503,36 @@ static TSK_WALK_RET_ENUM
 ifind_data_act(TSK_FS_FILE * fs_file, void *ptr)
 {
     IFIND_DATA_DATA *data = (IFIND_DATA_DATA *) ptr;
-    int file_flags = (TSK_FS_FILE_WALK_FLAG_AONLY);
+    int file_flags =
+        (TSK_FS_FILE_WALK_FLAG_AONLY | TSK_FS_FILE_WALK_FLAG_SLACK);
+    int i, cnt;
 
     data->curinode = fs_file->meta->addr;
 
-    /* NT Specific Stuff: search all ADS */
-    if (TSK_FS_TYPE_ISNTFS(fs_file->fs_info->ftype)) {
-        int i, cnt;
-
-        file_flags |= TSK_FS_FILE_WALK_FLAG_SLACK;
-        cnt = tsk_fs_file_attr_getsize(fs_file);
-        for (i = 0; i < cnt; i++) {
-            const TSK_FS_ATTR *fs_attr =
-                tsk_fs_file_attr_get_idx(fs_file, i);
-            if (!fs_attr)
-                continue;
-
-            data->curtype = fs_attr->type;
-            data->curid = fs_attr->id;
-            if (fs_attr->flags & TSK_FS_ATTR_NONRES) {
-                if (tsk_fs_attr_walk(fs_attr,
-                        file_flags, ifind_data_file_ntfs_act, ptr)) {
-                    if (tsk_verbose)
-                        tsk_fprintf(stderr,
-                            "Error walking file %" PRIuINUM
-                            " Attribute: %i", fs_file->meta->addr, i);
-
-                    /* Ignore these errors */
-                    tsk_error_reset();
-                }
-                
-                if ((data->found) && (!(data->flags & TSK_FS_IFIND_ALL)))
-                    break;
-            }
-        }
-        return TSK_WALK_CONT;
-    }
-    else if (TSK_FS_TYPE_ISFAT(fs_file->fs_info->ftype)) {
-        file_flags |= (TSK_FS_FILE_WALK_FLAG_SLACK);
-        if (tsk_fs_file_walk(fs_file, file_flags,
-                ifind_data_file_act, ptr)) {
-            if (tsk_verbose)
-                tsk_fprintf(stderr, "Error walking file %" PRIuINUM,
-                    fs_file->meta->addr);
-
-            /* Ignore these errors */
-            tsk_error_reset();
-        }
-    }
-    /* UNIX do not need the SLACK flag because they use fragments - if the
-     * SLACK flag exists then any unused fragments in a block will be 
-     * correlated with the incorrect inode
-     */
-    else {
-        const TSK_FS_ATTR *fs_attr;
-
-        if (tsk_fs_file_walk(fs_file, file_flags,
-                ifind_data_file_act, ptr)) {
-            if (tsk_verbose)
-                tsk_fprintf(stderr, "Error walking file %" PRIuINUM,
-                    fs_file->meta->addr);
-
-            /* Ignore these errors */
-            tsk_error_reset();
-        }
-
-
-        // try the indirect blocks
-        fs_attr = tsk_fs_file_attr_get_type(fs_file,
-            TSK_FS_ATTR_TYPE_UNIX_INDIR, 0, 0);
-        if (fs_attr) {
-            data->curtype = fs_attr->type;
-            data->curid = fs_attr->id;
+    /* Search all attrributes */
+    cnt = tsk_fs_file_attr_getsize(fs_file);
+    for (i = 0; i < cnt; i++) {
+        const TSK_FS_ATTR *fs_attr = tsk_fs_file_attr_get_idx(fs_file, i);
+        if (!fs_attr)
+            continue;
 
+        data->curtype = fs_attr->type;
+        data->curid = fs_attr->id;
+        if (fs_attr->flags & TSK_FS_ATTR_NONRES) {
             if (tsk_fs_attr_walk(fs_attr,
                     file_flags, ifind_data_file_act, ptr)) {
                 if (tsk_verbose)
                     tsk_fprintf(stderr,
                         "Error walking file %" PRIuINUM
-                        " Indirect Attribute", fs_file->meta->addr);
+                        " Attribute: %i", fs_file->meta->addr, i);
+
                 /* Ignore these errors */
                 tsk_error_reset();
             }
+
+            // stop if we only want one hit
+            if ((data->found) && (!(data->flags & TSK_FS_IFIND_ALL)))
+                break;
         }
     }
 
@@ -640,15 +564,12 @@ tsk_fs_ifind_data(TSK_FS_INFO * fs, TSK_FS_IFIND_FLAG_ENUM lclflags,
         return 1;
     }
 
-    /* 
-     * If we did not find an inode yet, we call block_walk for the 
-     * block to find out the associated flags so we can identify it as
-     * a meta data block */
+    /* If we did not find an inode yet, get the block's
+     * flags so we can identify it as a meta data block */
     if (!data.found) {
         TSK_FS_BLOCK *fs_block;
 
         if ((fs_block = tsk_fs_block_get(fs, NULL, blk)) != NULL) {
-
             if (fs_block->flags & TSK_FS_BLOCK_FLAG_META) {
                 tsk_printf("Meta Data\n");
                 data.found = 1;
@@ -656,6 +577,7 @@ tsk_fs_ifind_data(TSK_FS_INFO * fs, TSK_FS_IFIND_FLAG_ENUM lclflags,
             tsk_fs_block_free(fs_block);
         }
     }
+
     if (!data.found) {
         tsk_printf("Inode not found\n");
     }
diff --git a/tsk3/fs/iso9660.c b/tsk3/fs/iso9660.c
index 0da9c74..8cb206f 100644
--- a/tsk3/fs/iso9660.c
+++ b/tsk3/fs/iso9660.c
@@ -497,8 +497,8 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
                         (const UTF16 **) &name16,
                         (UTF16 *) & buf[b_offs + sizeof(iso9660_dentry) +
                             dentry->fi_len], &name8,
-                        (UTF8 *) ((uintptr_t) & in_node->inode.
-                            fn[ISO9660_MAXNAMLEN_STD]),
+                        (UTF8 *) ((uintptr_t) & in_node->
+                            inode.fn[ISO9660_MAXNAMLEN_STD]),
                         TSKlenientConversion);
                     if (retVal != TSKconversionOK) {
                         if (tsk_verbose)
diff --git a/tsk3/fs/iso9660_dent.c b/tsk3/fs/iso9660_dent.c
index bdebe5b..aca0b6b 100644
--- a/tsk3/fs/iso9660_dent.c
+++ b/tsk3/fs/iso9660_dent.c
@@ -143,7 +143,6 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf,
 
         // process the entry (if it has a defined and valid length)
         if ((dd->entry_len) && (buf_idx + dd->entry_len < a_length)) {
-            int i;
 
             /* We need to find the data in the pre-processed list because that
              * contains the meta data address that TSK assigned to this file.  
@@ -167,12 +166,6 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf,
             fs_name->meta_addr = in->inum;
             strncpy(fs_name->name, in->inode.fn, ISO9660_MAXNAMLEN);
 
-            /* Clean up name */
-            for (i = 0; fs_name->name[i] != '\0'; i++) {
-                if (TSK_IS_CNTRL(fs_name->name[i]))
-                    fs_name->name[i] = '^';
-            }
-
             if (dd->flags & ISO9660_FLAG_DIR)
                 fs_name->type = TSK_FS_NAME_TYPE_DIR;
             else
@@ -258,7 +251,7 @@ iso9660_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
         tsk_fs_dir_reset(fs_dir);
     }
     else {
-        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, 128)) == NULL) {
+        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
             return TSK_ERR;
         }
     }
diff --git a/tsk3/fs/nofs_misc.c b/tsk3/fs/nofs_misc.c
index ad5a950..7a34d0a 100644
--- a/tsk3/fs/nofs_misc.c
+++ b/tsk3/fs/nofs_misc.c
@@ -58,8 +58,8 @@ tsk_fs_nofs_make_data_run(TSK_FS_FILE * a_fs_file)
     tsk_errno = TSK_ERR_FS_UNSUPFUNC;
     snprintf(tsk_errstr, TSK_ERRSTR_L,
         "Illegal analysis method for %s data ",
-        (a_fs_file->fs_info) ? tsk_fs_type_toname(a_fs_file->
-            fs_info->ftype) : "");
+        (a_fs_file->fs_info) ? tsk_fs_type_toname(a_fs_file->fs_info->
+            ftype) : "");
     return 1;
 }
 
diff --git a/tsk3/fs/ntfs.c b/tsk3/fs/ntfs.c
index a058265..2a898b5 100644
--- a/tsk3/fs/ntfs.c
+++ b/tsk3/fs/ntfs.c
@@ -36,9 +36,6 @@
  */
 
 
-/* needs to be predefined for proc_attrseq */
-static uint8_t ntfs_proc_attrlist(NTFS_INFO *, TSK_FS_FILE *,
-    const TSK_FS_ATTR *);
 
 
 
@@ -1531,10 +1528,10 @@ ntfs_file_read_special(const TSK_FS_ATTR * a_fs_attr,
                         cpylen = a_len - buf_idx;
                     }
                     // Make sure not to return more bytes than are in the file
-                    if (cpylen >
-                        (a_fs_attr->size - (a_offset + buf_idx)))
+                    if (cpylen > (a_fs_attr->size - (a_offset + buf_idx)))
                         cpylen =
-                            (size_t) (a_fs_attr->size - (a_offset + buf_idx));
+                            (size_t) (a_fs_attr->size - (a_offset +
+                                buf_idx));
 
                     memcpy(&a_buf[buf_idx], &comp.uncomp_buf[byteoffset],
                         cpylen);
@@ -1568,6 +1565,27 @@ ntfs_file_read_special(const TSK_FS_ATTR * a_fs_attr,
 }
 
 
+/* needs to be predefined for proc_attrseq */
+static uint8_t ntfs_proc_attrlist(NTFS_INFO *, TSK_FS_FILE *,
+                                  const TSK_FS_ATTR *);
+
+
+/* This structure is used when processing attrlist attributes.
+ * The Id part of the MFTNUM-TYPE-ID triple is unique only to a given
+ * MFTNUM. With the case of attribute lists, a file may use multiple
+ * MFT entires and therefore have multiple attributes with the same
+ * type and id pair (if they are in different MFT entries). This map
+ * is created by proc_attrlist when it assigns unique IDs to the 
+ * other entries.  proc_attrseq uses this when it adds the attributes. 
+ */
+typedef struct {
+    int num_used;
+    TSK_INUM_T extMft[256];
+    uint32_t type[256];
+    uint32_t extId[256];
+    uint8_t name[256][512];
+    uint32_t newId[256];
+} NTFS_ATTRLIST_MAP;
 
 /* 
  * Process an NTFS attribute sequence and load the data into data
@@ -1579,13 +1597,16 @@ ntfs_file_read_special(const TSK_FS_ATTR * a_fs_attr,
  * @param fs_file Generic metadata structure to add the attribute info to
  * @param attrseq Start of the attribute sequence to analyze
  * @param len Length of the attribute sequence buffer
+ * @param a_attrinum MFT entry address that the attribute sequence came from (diff from fs_file for attribute lists)
+ * @param a_attr_map List that maps to new IDs that were assigned by processing 
+ * the attribute list attribute (if it exists) or NULL if there is no attrlist.
  * @returns Error code
  */
 static TSK_RETVAL_ENUM
 ntfs_proc_attrseq(NTFS_INFO * ntfs,
-    TSK_FS_FILE * fs_file, ntfs_attr * attrseq, size_t len)
+    TSK_FS_FILE * fs_file, const ntfs_attr * a_attrseq, size_t len, TSK_INUM_T a_attrinum, const NTFS_ATTRLIST_MAP *a_attr_map)
 {
-    ntfs_attr *attr = attrseq;
+    const ntfs_attr *attr;
     const TSK_FS_ATTR *fs_attr_attrl = NULL;
     char name[NTFS_MAXNAMLEN_UTF8 + 1];
     TSK_FS_INFO *fs = (TSK_FS_INFO *) & ntfs->fs_info;
@@ -1603,8 +1624,8 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
         return TSK_ERR;
     }
     /* Cycle through the list of attributes */
-    for (; ((uintptr_t) attr >= (uintptr_t) attrseq)
-        && ((uintptr_t) attr <= ((uintptr_t) attrseq + len))
+    for (attr = a_attrseq; ((uintptr_t) attr >= (uintptr_t) a_attrseq)
+        && ((uintptr_t) attr <= ((uintptr_t) a_attrseq + len))
         && (tsk_getu32(fs->endian, attr->len) > 0
             && (tsk_getu32(fs->endian, attr->type) !=
                 0xffffffff));
@@ -1612,17 +1633,32 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
         (ntfs_attr *) ((uintptr_t) attr + tsk_getu32(fs->endian,
                 attr->len))) {
 
-        UTF16 *name16;
-        UTF8 *name8;
         int retVal;
-        uint8_t isDefaultData = 0;
+        int i;
 
         /* Get the type of this attribute */
         uint32_t type = tsk_getu32(fs->endian, attr->type);
+        uint16_t id = tsk_getu16(fs->endian, attr->id);
+        uint16_t id_new = id;
+
+        /* If the map was supplied, search through it to see if this 
+         * entry is in there.  Use that ID instead so that we always have
+         * unique IDs for each attribute -- even if it spans multiple MFT entries. */
+        if (a_attr_map) {
+            for (i = 0; i < a_attr_map->num_used; i++) {
+                if ((a_attr_map->type[i] == type) &&
+                    (memcmp(a_attr_map->name[i], (void *)((uintptr_t)attr+tsk_getu16(fs->endian, attr->name_off)), attr->nlen*2) == 0)) {
+                    id_new = a_attr_map->newId[i];
+                    break;
+                }
+            }
+        }
 
         /* Copy the name and convert it to UTF8 */
         if (attr->nlen) {
             int i;
+            UTF8 *name8;
+            UTF16 *name16;
 
             name8 = (UTF8 *) name;
             name16 =
@@ -1659,24 +1695,10 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
                 i++;
             }
         }
-        /* Call the unnamed $Data attribute, $Data */
-        else if (type == NTFS_ATYPE_DATA) {
-            name[0] = '$';
-            name[1] = 'D';
-            name[2] = 'a';
-            name[3] = 't';
-            name[4] = 'a';
-            name[5] = '\0';
-            isDefaultData = 1;  // save this so we know later in the loop
-        }
         else {
-            name[0] = 'N';
-            name[1] = '/';
-            name[2] = 'A';
-            name[3] = '\0';
+            name[0] = '\0';
         }
 
-
         /* For resident attributes, we will copy the buffer into
          * a TSK_FS_ATTR buffer, which is stored in the TSK_FS_META
          * structure
@@ -1687,17 +1709,17 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
             if (tsk_verbose)
                 tsk_fprintf(stderr,
                     "ntfs_proc_attrseq: Resident Attribute in Type: %"
-                    PRIu32 " Id: %" PRIu16 " Name: %s\n", type,
-                    tsk_getu16(fs->endian, attr->id), name);
+                    PRIu32 " Id: %" PRIu16 " IdNew: %"PRIu16 " Name: %s\n", type,
+                    id, id_new, name);
 
             /* Validate the offset lengths */
             if (((tsk_getu16(fs->endian,
                             attr->c.r.soff) + (uintptr_t) attr) >
-                    ((uintptr_t) attrseq + len))
+                    ((uintptr_t) a_attrseq + len))
                 || ((tsk_getu16(fs->endian,
                             attr->c.r.soff) + tsk_getu32(fs->endian,
                             attr->c.r.ssize) + (uintptr_t) attr) >
-                    ((uintptr_t) attrseq + len))) {
+                    ((uintptr_t) a_attrseq + len))) {
                 tsk_error_reset();
                 tsk_errno = TSK_ERR_FS_CORRUPT;
                 snprintf(tsk_errstr, TSK_ERRSTR_L,
@@ -1718,8 +1740,7 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
 
             // set the details in the fs_attr structure
             if (tsk_fs_attr_set_str(fs_file, fs_attr, name, type,
-                    tsk_getu16(fs->endian, attr->id),
-                    (void *) ((uintptr_t) attr +
+                    id_new, (void *) ((uintptr_t) attr +
                         tsk_getu16(fs->endian,
                             attr->c.r.soff)), tsk_getu32(fs->endian,
                         attr->c.r.ssize))) {
@@ -1735,7 +1756,7 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
                     tsk_getu32(fs->endian, attr->c.r.ssize);
             }
             else if ((fs_file->meta->type == TSK_FS_META_TYPE_REG)
-                && (type == NTFS_ATYPE_DATA) && (isDefaultData)) {
+                && (type == NTFS_ATYPE_DATA) && (name[0] == '\0')) {
                 fs_file->meta->size =
                     tsk_getu32(fs->endian, attr->c.r.ssize);
             }
@@ -1749,15 +1770,14 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
             TSK_FS_ATTR *fs_attr = NULL;
             TSK_FS_ATTR_RUN *fs_attr_run = NULL;
             uint8_t data_flag = 0;
-            uint16_t id = tsk_getu16(fs->endian, attr->id);
             uint32_t compsize = 0;
             TSK_RETVAL_ENUM retval;
 
             if (tsk_verbose)
                 tsk_fprintf(stderr,
                     "ntfs_proc_attrseq: Non-Resident Attribute Type: %"
-                    PRIu32 " Id: %" PRIu16 " Name: %s  Start VCN: %" PRIu64
-                    "\n", type, id, name, tsk_getu64(fs->endian,
+                    PRIu32 " Id: %" PRIu16 " IdNew: %"PRIu16 " Name: %s  Start VCN: %" PRIu64
+                    "\n", type, id, id_new, name, tsk_getu64(fs->endian,
                         attr->c.nr.start_vcn));
 
             /* convert the run to generic form */
@@ -1797,9 +1817,12 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
              * and get its ID
              *
              * We could also check for a start_vcn if this does
-             * not fix the problem
+             * not fix the problem.
+             *
+             * NOTE: This should not be needed now that TSK assigns 
+             * unique ID values to the extended attributes. 
              */
-            if (id == 0) {
+            if (id_new == 0) {
                 int cnt, i;
 
                 // cycle through the attributes
@@ -1812,14 +1835,17 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
                         continue;
 
                     /* We found an attribute with the same name and type */
-                    if ((fs_attr2->type == type) &&
-                        (strcmp(fs_attr2->name, name) == 0)) {
-                        id = fs_attr2->id;
-                        if (tsk_verbose)
-                            tsk_fprintf(stderr,
-                                "ntfs_proc_attrseq: Updating id from 0 to %"
-                                PRIu16 "\n", id);
-                        break;
+                    if (fs_attr2->type == type) {
+                        if (((name[0] == '\0') && (fs_attr2->name == NULL))
+                            || ((fs_attr2->name)
+                                && (strcmp(fs_attr2->name, name) == 0))) {
+                            id_new = fs_attr2->id;
+                            if (tsk_verbose)
+                                tsk_fprintf(stderr,
+                                    "ntfs_proc_attrseq: Updating id from 0 to %"
+                                    PRIu16 "\n", id_new);
+                            break;
+                        }
                     }
                 }
             }
@@ -1853,7 +1879,7 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
             // @@@ This is bad design, we are casting away the const...
             fs_attr =
                 (TSK_FS_ATTR *) tsk_fs_attrlist_get_id(fs_file->meta->attr,
-                type, id);
+                type, id_new);
             if (fs_attr == NULL) {
                 uint64_t ssize; // size
                 uint64_t alen;  // allocated length
@@ -1888,7 +1914,7 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
 
                 // update the meta->size value if this is the default $Data attribute
                 if ((fs_file->meta->type == TSK_FS_META_TYPE_REG)
-                    && (type == NTFS_ATYPE_DATA) && (isDefaultData)) {
+                    && (type == NTFS_ATYPE_DATA) && (name[0] == '\0')) {
                     fs_file->meta->size = ssize;
                 }
 
@@ -1901,7 +1927,7 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
 
                 if (tsk_fs_attr_set_run(fs_file, fs_attr,
                         fs_attr_run, name,
-                        type, id, ssize,
+                        type, id_new, ssize,
                         tsk_getu64(fs->endian, attr->c.nr.initsize),
                         alen, data_flag, compsize)) {
                     strncat(tsk_errstr2, " - proc_attrseq: set run",
@@ -2066,7 +2092,7 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
                 return TSK_ERR;
             }
             fs_attr_attrl = tsk_fs_attrlist_get_id(fs_file->meta->attr,
-                NTFS_ATYPE_ATTRLIST, tsk_getu16(fs->endian, attr->id));
+                NTFS_ATYPE_ATTRLIST, id_new);
             if (fs_attr_attrl == NULL) {
                 strncat(tsk_errstr2,
                     " - proc_attrseq: getting attribute list",
@@ -2095,8 +2121,9 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
                 if (!fs_attr)
                     continue;
 
+                // get the default attribute
                 if ((fs_attr->type == NTFS_ATYPE_DATA) &&
-                    (strcmp(fs_attr->name, "$Data") == 0)) {
+                    (fs_attr->name == NULL)) {
                     ntfs->mft_data = fs_attr;
                     break;
                 }
@@ -2141,6 +2168,7 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
 /********   Attribute List Action and Function ***********/
 
 
+
 /*
  * Attribute lists are used when all of the attribute  headers can not
  * fit into one MFT entry.  This contains an entry for every attribute
@@ -2148,6 +2176,10 @@ ntfs_proc_attrseq(NTFS_INFO * ntfs,
  * and then call proc_attrseq on each of those, which adds the data
  * to the fs_file structure.
  *
+ * @param ntfs File system being analyzed
+ * @param fs_file Main file that will have attributes added to it.
+ * @param fs_attr_attrlist Attrlist attribute that needs to be parsed. 
+ *
  * Return 1 on error and 0 on success
  */
 static uint8_t
@@ -2160,8 +2192,11 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
     TSK_FS_INFO *fs = (TSK_FS_INFO *) & ntfs->fs_info;
     ntfs_mft *mft;
     TSK_FS_LOAD_FILE load_file;
-    TSK_INUM_T hist[256];
-    uint16_t histcnt = 0;
+    TSK_INUM_T mftToDo[256];
+    uint16_t mftToDoCnt = 0;
+    NTFS_ATTRLIST_MAP *map;
+    uint16_t nextid = 0;
+    int a;
 
     if (tsk_verbose)
         tsk_fprintf(stderr,
@@ -2172,11 +2207,13 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
         return 1;
     }
 
-    /* Clear the contents of the history buffer */
-    memset(hist, 0, sizeof(hist));
+    if ((map = (NTFS_ATTRLIST_MAP *)tsk_malloc(sizeof(NTFS_ATTRLIST_MAP))) == NULL) {
+        free(mft);
+        return 1;
+    }
 
-    /* add ourselves to the history */
-    hist[histcnt++] = ntfs->mnum;
+    /* Clear the contents of the todo buffer */
+    memset(mftToDo, 0, sizeof(mftToDo));
 
     /* Get a copy of the attribute list stream using the above action */
     load_file.left = load_file.total = (size_t) fs_attr_attrlist->size;
@@ -2184,6 +2221,7 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
         tsk_malloc((size_t) fs_attr_attrlist->size);
     if (buf == NULL) {
         free(mft);
+        free(map);
         return 1;
     }
     endaddr = (uintptr_t) buf + (uintptr_t) fs_attr_attrlist->size;
@@ -2192,6 +2230,7 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
         strncat(tsk_errstr2, " - processing attrlist",
             TSK_ERRSTR_L - strlen(tsk_errstr2));
         free(mft);
+        free(map);
         return 1;
     }
 
@@ -2205,52 +2244,94 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
             "processing attrlist of entry %" PRIuINUM, ntfs->mnum);
         free(mft);
         free(buf);
+        free(map);
         return 1;
     }
 
-
-    /* Process the list & and call ntfs_proc_attr */
+    /* The TSK design requres that each attribute have its own ID.
+     * Therefore, we need to identify all of the unique attributes
+     * so that we can assign a unique ID to them. 
+     * In this process, we will also identify the unique MFT entries to
+     * process. */
+    nextid = fs_attr_attrlist->id;  // we won't see this entry in the list
     for (list = (ntfs_attrlist *) buf;
         (list) && ((uintptr_t) list < endaddr)
         && (tsk_getu16(fs->endian, list->len) > 0);
         list =
         (ntfs_attrlist *) ((uintptr_t) list + tsk_getu16(fs->endian,
                 list->len))) {
-        TSK_INUM_T mftnum;
-        uint32_t type;
-        uint16_t id, i;
-        TSK_RETVAL_ENUM retval;
-
-        /* Which MFT is this attribute in? */
-        mftnum = tsk_getu48(fs->endian, list->file_ref);
-        /* Check the history to see if we have already processed this
-         * one before (if we have then we can skip it as we grabbed all
-         * of them last time
-         */
-        for (i = 0; i < histcnt; i++) {
-            if (hist[i] == mftnum)
-                break;
-        }
+        uint8_t found;
+        int i;
 
-        if (hist[i] == mftnum)
-            continue;
-        /* This is a new one, add it to the history, and process it */
-        if (histcnt < 256)
-            hist[histcnt++] = mftnum;
-        type = tsk_getu32(fs->endian, list->type);
-        id = tsk_getu16(fs->endian, list->id);
+        TSK_INUM_T mftnum = tsk_getu48(fs->endian, list->file_ref);
+        uint32_t type = tsk_getu32(fs->endian, list->type);
+        uint16_t id = tsk_getu16(fs->endian, list->id);
+        
         if (tsk_verbose)
             tsk_fprintf(stderr,
                 "ntfs_proc_attrlist: mft: %" PRIuINUM
                 " type %" PRIu32 " id %" PRIu16
                 "  VCN: %" PRIu64 "\n", mftnum, type,
                 id, tsk_getu64(fs->endian, list->start_vcn));
-        /* 
-         * Read the MFT entry 
-         */
+        
+
+        // keep track of the biggest ID that we saw.
+        if (id > nextid)
+            nextid = id;
+
+        /* First identify the unique attributes.  
+         * we can have duplicate entries at different VCNs.  Ignore those. */
+        found = 0;
+        for (i = 0; i < map->num_used; i++) {
+            if ((map->type[i] == type) && (memcmp(map->name[i], &list->name, list->nlen*2) == 0)) {
+                found=1;
+                break;
+            }
+        }
+
+        // add it to the list
+        if (found == 0) {
+            map->extMft[map->num_used] = mftnum;
+            map->type[map->num_used] = type;
+            map->extId[map->num_used] = id;
+            memcpy(map->name[map->num_used], &list->name, list->nlen*2);
+            if (map->num_used < 255)
+                map->num_used++;
+        }
+        
+        /* also check the todo list -- skip the base entry 
+         * the goal here is to get a unique list of MFT entries
+         * to later process. */
+        if (mftnum != ntfs->mnum) {
+            found = 0;
+            for (i = 0; i < mftToDoCnt; i++) {
+                if (mftToDo[i] == mftnum) {
+                    found = 1;
+                    break;
+                }
+            }
+            if ((found == 0) && (mftToDoCnt < 256)) {
+                mftToDo[mftToDoCnt++] = mftnum;
+            }
+        }
+    }
+
+    // update the map and assign unique IDs
+    for (a = 0; a < map->num_used; a++) {
+        // skip the base entry attributes -- they have unique attribute IDs
+        if (map->extMft[a] == ntfs->mnum)
+            continue;
+        map->newId[a] = ++nextid;
+    }
+
+
+    /* Process the ToDo list & and call ntfs_proc_attr */
+    for (a = 0; a < mftToDoCnt; a++) {  
+        TSK_RETVAL_ENUM retval;
+        
         /* Sanity check. */
-        if (mftnum < ntfs->fs_info.first_inum ||
-            mftnum > ntfs->fs_info.last_inum) {
+        if (mftToDo[a] < ntfs->fs_info.first_inum ||
+            mftToDo[a] > ntfs->fs_info.last_inum) {
 
             if (tsk_verbose) {
                 /* this case can easily occur if the attribute list was non-resident and the cluster has been reallocated */
@@ -2259,13 +2340,12 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
                     "Invalid MFT file reference (%"
                     PRIuINUM
                     ") in the unallocated attribute list of MFT %"
-                    PRIuINUM "", mftnum, ntfs->mnum);
+                    PRIuINUM "", mftToDo[a], ntfs->mnum);
             }
-
             continue;
         }
 
-        if ((retval = ntfs_dinode_lookup(ntfs, mft, mftnum)) != TSK_OK) {
+        if ((retval = ntfs_dinode_lookup(ntfs, mft, mftToDo[a])) != TSK_OK) {
             // if the entry is corrupt, then continue
             if (retval == TSK_COR) {
                 if (tsk_verbose)
@@ -2275,6 +2355,7 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
             }
 
             free(mft);
+            free(map);
             free(buf);
             strncat(tsk_errstr2, " - proc_attrlist",
                 TSK_ERRSTR_L - strlen(tsk_errstr2));
@@ -2299,23 +2380,23 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
                     "Extension record %" PRIuINUM
                     " (file ref = %" PRIuINUM
                     ") is not for attribute list of %"
-                    PRIuINUM "", mftnum, tsk_getu48(fs->endian,
+                    PRIuINUM "", mftToDo[a], tsk_getu48(fs->endian,
                         mft->base_ref), ntfs->mnum);
                 free(mft);
+                free(map);
                 free(buf);
                 return 1;
             }
         }
-        /* 
-         * Process the attribute seq for this MFT entry and add them
+         
+        /* Process the attribute seq for this MFT entry and add them
          * to the TSK_FS_META structure
          */
-
         if ((retval =
                 ntfs_proc_attrseq(ntfs, fs_file, (ntfs_attr *) ((uintptr_t)
                         mft + tsk_getu16(fs->endian, mft->attr_off)),
                     ntfs->mft_rsize_b - tsk_getu16(fs->endian,
-                        mft->attr_off))) != TSK_OK) {
+                        mft->attr_off), mftToDo[a], map)) != TSK_OK) {
 
             if (retval == TSK_COR) {
                 if (tsk_verbose)
@@ -2326,12 +2407,14 @@ ntfs_proc_attrlist(NTFS_INFO * ntfs,
             strncat(tsk_errstr2, "- proc_attrlist",
                 TSK_ERRSTR_L - strlen(tsk_errstr2));
             free(mft);
+            free(map);
             free(buf);
             return 1;
         }
     }
 
     free(mft);
+    free(map);
     free(buf);
     return 0;
 }
@@ -2429,7 +2512,7 @@ ntfs_dinode_copy(NTFS_INFO * ntfs, TSK_FS_FILE * a_fs_file)
             mft->attr_off));
     if ((retval = ntfs_proc_attrseq(ntfs, a_fs_file, attr,
                 ntfs->mft_rsize_b - tsk_getu16(fs->endian,
-                    mft->attr_off))) != TSK_OK) {
+                    mft->attr_off), a_fs_file->meta->addr, NULL)) != TSK_OK) {
         return retval;
     }
 
@@ -2668,7 +2751,7 @@ ntfs_attrname_lookup(TSK_FS_INFO * fs, uint16_t type, char *name, int len)
 
             /* Make sure it is NULL Terminated */
             else if ((uintptr_t) name8 >= (uintptr_t) name + len)
-                name[len-1] = '\0';
+                name[len - 1] = '\0';
             else
                 *name8 = '\0';
             return 0;
@@ -3003,8 +3086,8 @@ ntfs_get_sds(TSK_FS_INFO * fs, uint32_t secid)
         tsk_error_reset();
         tsk_errno = TSK_ERR_FS_GENFS;
         snprintf(tsk_errstr, TSK_ERRSTR_L,
-                 "ntfs_get_sds: SII entry size is invalid (%" PRIu32 ")",
-                 sii_sds_ent_size);
+            "ntfs_get_sds: SII entry size is invalid (%" PRIu32 ")",
+            sii_sds_ent_size);
         return NULL;
     }
 
@@ -3287,20 +3370,20 @@ ntfs_load_secure(NTFS_INFO * ntfs)
     // Read in the raw $SII stream.
     cnt =
         tsk_fs_attr_read(fs_attr_sii, 0, sii_buffer.buffer,
-        sii_buffer.size, (TSK_FS_FILE_READ_FLAG_ENUM) 0);
+        sii_buffer.size, TSK_FS_FILE_READ_FLAG_NONE);
     if (cnt != sii_buffer.size) {
         if (tsk_verbose)
             tsk_fprintf(stderr,
                 "ntfs_load_secure: error reading $Secure:$SII attribute: %s\n",
                 tsk_errstr);
         tsk_error_reset();
-        
+
         free(sii_buffer.buffer);
         free(sds_buffer.buffer);
         if (ntfs->sii_data.buffer)
             free(ntfs->sii_data.buffer);
         ntfs->sii_data.buffer = NULL;
-        
+
         tsk_fs_file_close(secure);
         return 0;
     }
@@ -3308,21 +3391,20 @@ ntfs_load_secure(NTFS_INFO * ntfs)
     // Read in the raw $SDS ($DATA) stream.
     cnt =
         tsk_fs_attr_read(fs_attr, (TSK_OFF_T) sds_buffer.used,
-        sds_buffer.buffer, sds_buffer.size,
-        (TSK_FS_FILE_READ_FLAG_ENUM) 0);
+        sds_buffer.buffer, sds_buffer.size, TSK_FS_FILE_READ_FLAG_NONE);
     if (cnt != sds_buffer.size) {
         if (tsk_verbose)
             tsk_fprintf(stderr,
                 "ntfs_load_secure: error reading $Secure:$SDS attribute: %s\n",
                 tsk_errstr);
         tsk_error_reset();
-        
+
         free(sii_buffer.buffer);
         free(sds_buffer.buffer);
         if (ntfs->sii_data.buffer)
             free(ntfs->sii_data.buffer);
         ntfs->sii_data.buffer = NULL;
-        
+
         tsk_fs_file_close(secure);
         return 0;
     }
@@ -3643,8 +3725,8 @@ ntfs_inode_walk(TSK_FS_INFO * fs, TSK_INUM_T start_inum,
         }
 
         myflags |=
-            (fs_file->meta->
-            flags & (TSK_FS_META_FLAG_USED | TSK_FS_META_FLAG_UNUSED));
+            (fs_file->meta->flags & (TSK_FS_META_FLAG_USED |
+                TSK_FS_META_FLAG_UNUSED));
         if ((flags & myflags) != myflags)
             continue;
 
@@ -4304,7 +4386,8 @@ ntfs_istat(TSK_FS_INFO * fs, FILE * hFile,
                     "Type: %s (%" PRIu32 "-%" PRIu16
                     ")   Name: %s   Non-Resident%s%s%s   size: %"
                     PRIuOFF "  init_size: %" PRIuOFF "\n", type,
-                    fs_attr->type, fs_attr->id, fs_attr->name,
+                    fs_attr->type, fs_attr->id,
+                    (fs_attr->name) ? fs_attr->name : "N/A",
                     (fs_attr->flags & TSK_FS_ATTR_ENC) ? ", Encrypted" :
                     "",
                     (fs_attr->flags & TSK_FS_ATTR_COMP) ? ", Compressed" :
@@ -4331,7 +4414,8 @@ ntfs_istat(TSK_FS_INFO * fs, FILE * hFile,
                     "Type: %s (%" PRIu32 "-%" PRIu16
                     ")   Name: %s   Resident%s%s%s   size: %"
                     PRIuOFF "\n", type, fs_attr->type,
-                    fs_attr->id, fs_attr->name,
+                    fs_attr->id,
+                    (fs_attr->name) ? fs_attr->name : "N/A",
                     (fs_attr->flags & TSK_FS_ATTR_ENC) ? ", Encrypted"
                     : "",
                     (fs_attr->flags & TSK_FS_ATTR_COMP) ?
diff --git a/tsk3/fs/ntfs_dent.c b/tsk3/fs/ntfs_dent.c
index 9dcc436..ad0a772 100644
--- a/tsk3/fs/ntfs_dent.c
+++ b/tsk3/fs/ntfs_dent.c
@@ -215,7 +215,6 @@ ntfs_dent_copy(NTFS_INFO * ntfs, ntfs_idxentry * idxe,
     UTF16 *name16;
     UTF8 *name8;
     int retVal;
-    int i;
 
     fs_name->meta_addr = tsk_getu48(fs->endian, idxe->file_ref);
     fs_name->meta_seq = tsk_getu16(fs->endian, idxe->seq_num);
@@ -243,14 +242,6 @@ ntfs_dent_copy(NTFS_INFO * ntfs, ntfs_idxentry * idxe,
     else
         *name8 = '\0';
 
-    /* Clean up name */
-    i = 0;
-    while (fs_name->name[i] != '\0') {
-        if (TSK_IS_CNTRL(fs_name->name[i]))
-            fs_name->name[i] = '^';
-        i++;
-    }
-
     if (tsk_getu64(fs->endian, fname->flags) & NTFS_FNAME_FLAGS_DIR)
         fs_name->type = TSK_FS_NAME_TYPE_DIR;
     else
@@ -470,7 +461,6 @@ ntfs_proc_idxentry(NTFS_INFO * a_ntfs, TSK_FS_DIR * a_fs_dir,
                     tsk_getu16(fs->endian, a_idxe->idxlen)),
                 fs_name->flags);
 
-
         if (tsk_fs_dir_add(a_fs_dir, fs_name)) {
             tsk_fs_name_free(fs_name);
             return TSK_ERR;
@@ -658,7 +648,7 @@ ntfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
         tsk_fs_dir_reset(fs_dir);
     }
     else {
-        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, 128)) == NULL) {
+        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, a_addr, 128)) == NULL) {
             return TSK_ERR;
         }
     }
@@ -789,6 +779,7 @@ ntfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
         tsk_fs_name_free(fs_name);
         fs_name = NULL;
     }
+    
 
     /* Now we return to processing the Index Root Attribute */
     if (tsk_verbose)
@@ -987,8 +978,8 @@ ntfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
 
             /* process the list of index entries */
             retval_tmp = ntfs_proc_idxentry(ntfs, fs_dir,
-                (fs_dir->fs_file->
-                    meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, idxe,
+                (fs_dir->fs_file->meta->
+                    flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, idxe,
                 list_len, tsk_getu32(a_fs->endian,
                     idxelist->seqend_off) - tsk_getu32(a_fs->endian,
                     idxelist->begin_off));
@@ -1052,8 +1043,8 @@ ntfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
 
             /* process the list of index entries */
             retval_tmp = ntfs_proc_idxentry(ntfs, fs_dir,
-                (fs_dir->fs_file->
-                    meta->flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, idxe,
+                (fs_dir->fs_file->meta->
+                    flags & TSK_FS_META_FLAG_UNALLOC) ? 1 : 0, idxe,
                 list_len, tsk_getu32(a_fs->endian,
                     idxelist->seqend_off) - tsk_getu32(a_fs->endian,
                     idxelist->begin_off));
@@ -1364,8 +1355,8 @@ ntfs_find_file(TSK_FS_INFO * fs, TSK_INUM_T inode_toid, uint32_t type_toid,
     fs_file->name->meta_seq = 0;
     fs_file->name->flags =
         ((tsk_getu16(fs->endian,
-                ntfs->
-                mft->flags) & NTFS_MFT_INUSE) ? TSK_FS_NAME_FLAG_ALLOC :
+                ntfs->mft->
+                flags) & NTFS_MFT_INUSE) ? TSK_FS_NAME_FLAG_ALLOC :
         TSK_FS_NAME_FLAG_UNALLOC);
 
     memset(&dinfo, 0, sizeof(NTFS_DINFO));
@@ -1406,7 +1397,7 @@ ntfs_find_file(TSK_FS_INFO * fs, TSK_INUM_T inode_toid, uint32_t type_toid,
         }
 
         /* only add the attribute name if it is the non-default data stream */
-        if (strcmp(fs_attr->name, "$Data") != 0)
+        if (fs_attr->name != NULL)
             attr = fs_attr->name;
     }
 
diff --git a/tsk3/fs/tsk_fatfs.h b/tsk3/fs/tsk_fatfs.h
index dcabe01..5c8bdbe 100644
--- a/tsk3/fs/tsk_fatfs.h
+++ b/tsk3/fs/tsk_fatfs.h
@@ -357,7 +357,7 @@ extern "C" {
     extern int8_t fatfs_is_clustalloc(FATFS_INFO * fatfs,
         TSK_DADDR_T clust);
 
-    extern uint8_t fatfs_isdentry(FATFS_INFO *, fatfs_dentry *);
+    extern uint8_t fatfs_isdentry(FATFS_INFO *, fatfs_dentry *, uint8_t);
     extern uint8_t fatfs_make_root(FATFS_INFO *, TSK_FS_META *);
     extern TSK_RETVAL_ENUM fatfs_dinode_copy(FATFS_INFO *, TSK_FS_META *,
         fatfs_dentry *, TSK_DADDR_T, TSK_INUM_T);
@@ -378,6 +378,8 @@ extern "C" {
         TSK_INUM_T a_addr);
 
     extern int fatfs_name_cmp(TSK_FS_INFO *, const char *, const char *);
+    extern uint8_t fatfs_dir_buf_add(FATFS_INFO * fatfs,
+        TSK_INUM_T par_inum, TSK_INUM_T dir_inum);
 
 
 #ifdef __cplusplus
diff --git a/tsk3/fs/tsk_fs.h b/tsk3/fs/tsk_fs.h
index f13e59e..2780d15 100644
--- a/tsk3/fs/tsk_fs.h
+++ b/tsk3/fs/tsk_fs.h
@@ -77,6 +77,7 @@ extern "C" {
     * Flags that are used to specify which blocks to call the tsk_fs_block_walk() callback function with.
      */
     enum TSK_FS_BLOCK_WALK_FLAG_ENUM {
+        TSK_FS_BLOCK_WALK_FLAG_NONE = 0x00,     ///< No Flags
         TSK_FS_BLOCK_WALK_FLAG_ALLOC = 0x01,    ///< Allocated blocks
         TSK_FS_BLOCK_WALK_FLAG_UNALLOC = 0x02,  ///< Unallocated blocks
         TSK_FS_BLOCK_WALK_FLAG_CONT = 0x04,     ///< Blocks that could store file content
@@ -133,6 +134,7 @@ extern "C" {
      * Flags used for a TSK_FS_ATTR_RUN entry. 
      */
     typedef enum {
+        TSK_FS_ATTR_RUN_FLAG_NONE = 0x00,       ///< No Flag
         TSK_FS_ATTR_RUN_FLAG_FILLER = 0x01,     ///< Entry is a filler for a run that has not been seen yet in the processing (or has been lost)
         TSK_FS_ATTR_RUN_FLAG_SPARSE = 0x02      ///< Entry is a sparse run where all data in the run is zeros
     } TSK_FS_ATTR_RUN_FLAG_ENUM;
@@ -161,6 +163,7 @@ extern "C" {
      * store file content metadata. 
      */
     typedef enum {
+        TSK_FS_ATTR_FLAG_NONE = 0x00,   ///< No Flag
         TSK_FS_ATTR_INUSE = 0x01,       ///< data structure is in use
         TSK_FS_ATTR_NONRES = 0x02,      ///< Contains non-resident data (i.e. located in blocks)
         TSK_FS_ATTR_RES = 0x04, ///< Contains resident data (i.e. in a small buffer)
@@ -190,6 +193,7 @@ extern "C" {
      * Flags used by tsk_fs_file_walk to determine when the callback function should
      * be used. */
     typedef enum {
+        TSK_FS_FILE_WALK_FLAG_NONE = 0x00,      ///< No Flag
         TSK_FS_FILE_WALK_FLAG_SLACK = 0x01,     ///< Include the file's slack space in the callback.
         TSK_FS_FILE_WALK_FLAG_NOID = 0x02,      ///< Ignore the Id argument given in the API (use only the type)
         TSK_FS_FILE_WALK_FLAG_AONLY = 0x04,     ///< Provide callback with only addresses and no file content.
@@ -249,7 +253,7 @@ extern "C" {
         TSK_FS_ATTR *next;      ///< Pointer to next attribute in list
         TSK_FS_FILE *fs_file;   ///< Pointer to the file that this is from
         TSK_FS_ATTR_FLAG_ENUM flags;    ///< Flags for attribute
-        char *name;             ///< Name of attribute (could be NULL) (in UTF-8)
+        char *name;             ///< Name of attribute (in UTF-8).  Will be NULL if attribute doesn't have a name. 
         size_t name_size;       ///< Number of bytes allocated to name
         TSK_FS_ATTR_TYPE_ENUM type;     ///< Type of attribute
         uint16_t id;            ///< Id of attribute
@@ -463,6 +467,13 @@ extern "C" {
  * name is known, but the parent is not */
 #define TSK_FS_ORPHAN_STR "-ORPHAN_FILE-"
 
+    /* we are using the last inode as the special inode for the orphan directory.  Note that this
+     * macro is defined to abstract this convention, but there are many places in the code where
+     * there is implied logic about this convention. For example, inode_walks will stop before
+     * this value so that special handling can occur. */
+#define TSK_FS_ORPHANDIR_INUM(fs_info) \
+(fs_info->last_inum)
+
 
     /** 
         * inode walk callback function definition.  This is called for every file
@@ -539,6 +550,7 @@ extern "C" {
 
         TSK_INUM_T meta_addr;   ///< Address of the metadata structure that the name points to. 
         uint32_t meta_seq;      ///< Sequence number for metadata structure (NTFS only) 
+        TSK_INUM_T par_addr;    ///< Metadata address of parent directory (equal to meta_addr if this entry is for root directory). 
 
         TSK_FS_NAME_TYPE_ENUM type;     ///< File type information (directory, file, etc.)
         TSK_FS_NAME_FLAG_ENUM flags;    ///< Flags that describe allocation status etc. 
@@ -570,6 +582,8 @@ extern "C" {
         size_t names_used;      ///< Number of name structures in queue being used
         size_t names_alloc;     ///< Number of name structures that were allocated
 
+        TSK_INUM_T addr;    ///< Metadata address of this directory 
+
         TSK_FS_INFO *fs_info;   ///< Pointer to file system the directory is located in
     } TSK_FS_DIR;
 
@@ -578,6 +592,7 @@ extern "C" {
      * which files to call the callback function on. 
      */
     typedef enum {
+        TSK_FS_DIR_WALK_FLAG_NONE = 0x00,       ///< No Flags
         TSK_FS_DIR_WALK_FLAG_ALLOC = 0x01,      ///< Return allocated names in callback
         TSK_FS_DIR_WALK_FLAG_UNALLOC = 0x02,    ///< Return unallocated names in callback
         TSK_FS_DIR_WALK_FLAG_RECURSE = 0x04,    ///< Recurse into sub-directories 
@@ -626,6 +641,7 @@ extern "C" {
     /**
      * Flags used by tsk_fs_file_read */
     typedef enum {
+        TSK_FS_FILE_READ_FLAG_NONE = 0x00,      ///< No Flags
         TSK_FS_FILE_READ_FLAG_SLACK = 0x01,     ///< Allow read access into slack space
         TSK_FS_FILE_READ_FLAG_NOID = 0x02,      ///< Ignore the Id argument given in the API (use only the type)
     } TSK_FS_FILE_READ_FLAG_ENUM;
@@ -781,6 +797,7 @@ extern "C" {
      * Flags for the FS_INFO structure 
      */
     enum TSK_FS_INFO_FLAG_ENUM {
+        TSK_FS_INFO_FLAG_NONE = 0x00,   ///< No Flags
         TSK_FS_INFO_FLAG_HAVE_SEQ = 0x01        ///< File system has sequence numbers in the inode addresses.
     };
     typedef enum TSK_FS_INFO_FLAG_ENUM TSK_FS_INFO_FLAG_ENUM;
@@ -830,7 +847,7 @@ extern "C" {
                      * or when a full name_walk is performed. 
 					 */
 
-        TSK_FS_DIR *orphan_dir;         ///< Files and dirs in the top level of the $OrphanFiles directory.  NULL if orphans have not been hunted for yet. 
+        TSK_FS_DIR *orphan_dir; ///< Files and dirs in the top level of the $OrphanFiles directory.  NULL if orphans have not been hunted for yet. 
         uint8_t isOrphanHunting;        ///< Set to 1 if TSK is currently looking for Orphan files
 
          uint8_t(*block_walk) (TSK_FS_INFO * fs, TSK_DADDR_T start, TSK_DADDR_T end, TSK_FS_BLOCK_WALK_FLAG_ENUM flags, TSK_FS_BLOCK_WALK_CB cb, void *ptr);    ///< FS-specific function: Call tsk_fs_block_walk() instead. 
@@ -912,6 +929,7 @@ extern "C" {
 
 
     enum TSK_FS_BLKCAT_FLAG_ENUM {
+        TSK_FS_BLKCAT_NONE = 0x00,
         TSK_FS_BLKCAT_HEX = 0x01,
         TSK_FS_BLKCAT_ASCII = 0x02,
         TSK_FS_BLKCAT_HTML = 0x04,
@@ -924,6 +942,7 @@ extern "C" {
 
 
     enum TSK_FS_BLKLS_FLAG_ENUM {
+        TSK_FS_BLKLS_NONE = 0x00,
         TSK_FS_BLKLS_CAT = 0x01,
         TSK_FS_BLKLS_LIST = 0x02,
         TSK_FS_BLKLS_SLACK = 0x04,
@@ -947,6 +966,7 @@ extern "C" {
 
 
     enum TSK_FS_FLS_FLAG_ENUM {
+        TSK_FS_FLS_NONE = 0x00,
         TSK_FS_FLS_DOT = 0x01,
         TSK_FS_FLS_LONG = 0x02,
         TSK_FS_FLS_FILE = 0x04,
@@ -957,7 +977,7 @@ extern "C" {
     typedef enum TSK_FS_FLS_FLAG_ENUM TSK_FS_FLS_FLAG_ENUM;
     extern uint8_t tsk_fs_fls(TSK_FS_INFO * fs,
         TSK_FS_FLS_FLAG_ENUM lclflags, TSK_INUM_T inode,
-        TSK_FS_NAME_FLAG_ENUM flags, TSK_TCHAR * pre, int32_t skew);
+        TSK_FS_DIR_WALK_FLAG_ENUM flags, TSK_TCHAR * pre, int32_t skew);
 
     extern uint8_t tsk_fs_icat(TSK_FS_INFO * fs,
         TSK_INUM_T inum,
@@ -966,6 +986,7 @@ extern "C" {
 
 
     enum TSK_FS_IFIND_FLAG_ENUM {
+        TSK_FS_IFIND_NONE = 0x00,
         TSK_FS_IFIND_ALL = 0x01,
         TSK_FS_IFIND_PAR_LONG = 0x02,
     };
@@ -979,6 +1000,7 @@ extern "C" {
 
 
     enum TSK_FS_ILS_FLAG_ENUM {
+        TSK_FS_ILS_NONE = 0x00,
         TSK_FS_ILS_OPEN = 0x01,
         TSK_FS_ILS_MAC = 0x02,
         TSK_FS_ILS_LINK = 0x04,
diff --git a/tsk3/fs/tsk_fs_i.h b/tsk3/fs/tsk_fs_i.h
index d978ee3..980ba4b 100644
--- a/tsk3/fs/tsk_fs_i.h
+++ b/tsk3/fs/tsk_fs_i.h
@@ -137,7 +137,7 @@ extern "C" {
     extern TSK_FS_FILE *tsk_fs_file_alloc(TSK_FS_INFO *);
 
     /* FS_DIR */
-    extern TSK_FS_DIR *tsk_fs_dir_alloc(TSK_FS_INFO * a_fs, size_t a_cnt);
+    extern TSK_FS_DIR *tsk_fs_dir_alloc(TSK_FS_INFO * a_fs, TSK_INUM_T a_addr, size_t a_cnt);
     extern uint8_t tsk_fs_dir_realloc(TSK_FS_DIR * a_fs_dir, size_t a_cnt);
     extern uint8_t tsk_fs_dir_add(TSK_FS_DIR * a_fs_dir,
         const TSK_FS_NAME * a_fs_dent);
@@ -151,12 +151,6 @@ extern "C" {
         TSK_FS_NAME * a_fs_name);
     extern TSK_RETVAL_ENUM tsk_fs_dir_find_orphans(TSK_FS_INFO * a_fs,
         TSK_FS_DIR * a_fs_dir);
-    /* we are using the last inode as the special inode for the orphan directory.  Note that this
-     * macro is defined to abstract this convention, but there are many places in the code where
-     * there is implied logic about this convention. For example, inode_walks will stop before
-     * this value so that special handling can occur. */
-#define TSK_FS_ORPHANDIR_INUM(fs_info) \
-    (fs_info->last_inum)
 
 
 
@@ -168,10 +162,10 @@ extern "C" {
     extern void tsk_fs_name_print(FILE *, const TSK_FS_FILE *,
         const char *, TSK_FS_INFO *, const TSK_FS_ATTR *, uint8_t);
     extern void tsk_fs_name_print_long(FILE *, const TSK_FS_FILE *,
-        const char *, TSK_FS_INFO *, const TSK_FS_ATTR *, uint8_t);
+        const char *, TSK_FS_INFO *, const TSK_FS_ATTR *, uint8_t,
+        int32_t);
     extern void tsk_fs_name_print_mac(FILE *, const TSK_FS_FILE *,
-        const char *, TSK_FS_INFO *, const TSK_FS_ATTR * fs_attr,
-        const char *);
+        const char *, const TSK_FS_ATTR * fs_attr, const char *, int32_t);
     extern uint8_t tsk_fs_name_copy(TSK_FS_NAME * a_fs_name_to,
         const TSK_FS_NAME * a_fs_name_from);
     extern void tsk_fs_name_reset(TSK_FS_NAME * a_fs_name);
diff --git a/tsk3/hashdb/Makefile.am b/tsk3/hashdb/Makefile.am
index b22687e..cbb98bd 100644
--- a/tsk3/hashdb/Makefile.am
+++ b/tsk3/hashdb/Makefile.am
@@ -1,4 +1,4 @@
-AM_CFLAGS = -I../.. -Wall 
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 EXTRA_DIST = .indent.pro
 
 noinst_LTLIBRARIES = libtskhashdb.la
diff --git a/tsk3/hashdb/Makefile.in b/tsk3/hashdb/Makefile.in
index 546efc9..d426350 100644
--- a/tsk3/hashdb/Makefile.in
+++ b/tsk3/hashdb/Makefile.in
@@ -179,7 +179,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CFLAGS = -I../.. -Wall 
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 EXTRA_DIST = .indent.pro
 noinst_LTLIBRARIES = libtskhashdb.la
 libtskhashdb_la_SOURCES = tm_lookup.c md5sum_index.c nsrl_index.c \
diff --git a/tsk3/img/Makefile.am b/tsk3/img/Makefile.am
index e965982..bb43d47 100644
--- a/tsk3/img/Makefile.am
+++ b/tsk3/img/Makefile.am
@@ -1,4 +1,4 @@
-AM_CFLAGS = -I../.. -Wall
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall
 EXTRA_DIST = .indent.pro 
 
 noinst_LTLIBRARIES = libtskimg.la
diff --git a/tsk3/img/Makefile.in b/tsk3/img/Makefile.in
index 4008e0f..660408c 100644
--- a/tsk3/img/Makefile.in
+++ b/tsk3/img/Makefile.in
@@ -179,7 +179,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CFLAGS = -I../.. -Wall
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall
 EXTRA_DIST = .indent.pro 
 noinst_LTLIBRARIES = libtskimg.la
 libtskimg_la_SOURCES = img_open.c img_types.c raw.c raw.h \
diff --git a/tsk3/img/ewf.h b/tsk3/img/ewf.h
index 5c38a62..0afda5d 100644
--- a/tsk3/img/ewf.h
+++ b/tsk3/img/ewf.h
@@ -18,7 +18,8 @@
 
 #if HAVE_LIBEWF
 
-#if defined(TSK_WIN32)
+// we used to check only for TSK_WIN32, but that fails on mingw
+#if defined(_MSC_VER)
 #include <config_msc.h>
 #endif
 
diff --git a/tsk3/libtsk.h b/tsk3/libtsk.h
index 9dfdd09..7e48192 100644
--- a/tsk3/libtsk.h
+++ b/tsk3/libtsk.h
@@ -6,5 +6,6 @@
 #include "tsk3/vs/tsk_vs.h"
 #include "tsk3/fs/tsk_fs.h"
 #include "tsk3/hashdb/tsk_hashdb.h"
+#include "tsk3/auto/tsk_auto.h"
 
 #endif
diff --git a/tsk3/tsk_incs.h b/tsk3/tsk_incs.h
index cf6232d..f9a9d42 100644
--- a/tsk3/tsk_incs.h
+++ b/tsk3/tsk_incs.h
@@ -4,7 +4,9 @@
 // Contains the config.h data needed by programs that use libtsk
 
 #include <unistd.h>
+#ifndef __STDC_FORMAT_MACROS
 #define  __STDC_FORMAT_MACROS
+#endif
 #include <inttypes.h>
 #include <sys/param.h>
 
diff --git a/tsk3/tsk_tools_i.h b/tsk3/tsk_tools_i.h
index ae6ada4..8d4deb9 100644
--- a/tsk3/tsk_tools_i.h
+++ b/tsk3/tsk_tools_i.h
@@ -10,5 +10,6 @@
 #include "tsk3/vs/tsk_vs.h"
 #include "tsk3/fs/tsk_fs.h"
 #include "tsk3/hashdb/tsk_hashdb.h"
+#include "tsk3/auto/tsk_auto.h"
 
 #endif
diff --git a/tsk3/vs/Makefile.am b/tsk3/vs/Makefile.am
index fab7241..4fc3fd7 100644
--- a/tsk3/vs/Makefile.am
+++ b/tsk3/vs/Makefile.am
@@ -1,4 +1,4 @@
-AM_CFLAGS = -I../.. -Wall 
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 EXTRA_DIST = .indent.pro
 
 noinst_LTLIBRARIES = libtskvs.la
diff --git a/tsk3/vs/Makefile.in b/tsk3/vs/Makefile.in
index fb2dfed..43f1e7c 100644
--- a/tsk3/vs/Makefile.in
+++ b/tsk3/vs/Makefile.in
@@ -179,7 +179,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CFLAGS = -I../.. -Wall 
+AM_CFLAGS = -I../.. -I$(srcdir)/../.. -Wall 
 EXTRA_DIST = .indent.pro
 noinst_LTLIBRARIES = libtskvs.la
 # Note that the .h files are in the top-level Makefile
diff --git a/tsk3/vs/mm_types.c b/tsk3/vs/mm_types.c
index d4a23e4..a01e893 100644
--- a/tsk3/vs/mm_types.c
+++ b/tsk3/vs/mm_types.c
@@ -108,6 +108,9 @@ tsk_vs_type_toname(TSK_VS_TYPE_ENUM type)
             return types->name;
         }
     }
+    if (type == TSK_VS_TYPE_DBFILLER) {
+        return "DB Filler";
+    }
     return NULL;
 }
 
diff --git a/tsk3/vs/tsk_vs.h b/tsk3/vs/tsk_vs.h
index b39608e..9a8e635 100644
--- a/tsk3/vs/tsk_vs.h
+++ b/tsk3/vs/tsk_vs.h
@@ -52,6 +52,7 @@ extern "C" {
         TSK_VS_TYPE_SUN = 0x0004,       ///< Sun VTOC
         TSK_VS_TYPE_MAC = 0x0008,       ///< Mac partition table
         TSK_VS_TYPE_GPT = 0x0010,       ///< GPT partition table
+        TSK_VS_TYPE_DBFILLER = 0x00F0,  ///< fake partition table type for loaddb (for images that do not have a volume system)
         TSK_VS_TYPE_UNSUPP = 0xffff,    ///< Unsupported
     } TSK_VS_TYPE_ENUM;
 
diff --git a/win32/tsk-win.sln b/win32/tsk-win.sln
index d8b1b13..87c91e0 100644
--- a/win32/tsk-win.sln
+++ b/win32/tsk-win.sln
@@ -150,20 +150,56 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mmcat", "mmcat\mmcat.vcproj
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "callback-sample", "callback-sample\callback-sample.vcproj", "{6CE3D593-E90D-4CC1-A66B-694AC909F6B8}"
 	ProjectSection(ProjectDependencies) = postProject
+		{F12AA46A-EA91-4AB6-8246-7800DF6128A4} = {F12AA46A-EA91-4AB6-8246-7800DF6128A4}
+		{47901C6F-77EC-4753-A83A-F6AE975851B9} = {47901C6F-77EC-4753-A83A-F6AE975851B9}
 		{47E72886-0B51-4098-BAF4-68B4494F0872} = {47E72886-0B51-4098-BAF4-68B4494F0872}
 		{2D0B32C2-B035-4873-8E9A-4D4221D93F68} = {2D0B32C2-B035-4873-8E9A-4D4221D93F68}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "posix-sample", "posix-sample\posix-sample.vcproj", "{1BA0B9E8-F135-494F-9CF5-86427C1F6E41}"
+	ProjectSection(ProjectDependencies) = postProject
+		{F12AA46A-EA91-4AB6-8246-7800DF6128A4} = {F12AA46A-EA91-4AB6-8246-7800DF6128A4}
 		{47901C6F-77EC-4753-A83A-F6AE975851B9} = {47901C6F-77EC-4753-A83A-F6AE975851B9}
+		{47E72886-0B51-4098-BAF4-68B4494F0872} = {47E72886-0B51-4098-BAF4-68B4494F0872}
+		{2D0B32C2-B035-4873-8E9A-4D4221D93F68} = {2D0B32C2-B035-4873-8E9A-4D4221D93F68}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libautotools", "libautotools\libautotools.vcproj", "{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}"
+	ProjectSection(ProjectDependencies) = postProject
 		{F12AA46A-EA91-4AB6-8246-7800DF6128A4} = {F12AA46A-EA91-4AB6-8246-7800DF6128A4}
+		{47901C6F-77EC-4753-A83A-F6AE975851B9} = {47901C6F-77EC-4753-A83A-F6AE975851B9}
+		{47E72886-0B51-4098-BAF4-68B4494F0872} = {47E72886-0B51-4098-BAF4-68B4494F0872}
+		{2D0B32C2-B035-4873-8E9A-4D4221D93F68} = {2D0B32C2-B035-4873-8E9A-4D4221D93F68}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "posix-sample", "posix-sample\posix-sample.vcproj", "{1BA0B9E8-F135-494F-9CF5-86427C1F6E41}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tsk_recover", "tsk_recover\tsk_recover.vcproj", "{06D707E5-68FF-4FC4-AFD0-C84584E32F47}"
+	ProjectSection(ProjectDependencies) = postProject
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8} = {88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tsk_loaddb", "tsk_loaddb\tsk_loaddb.vcproj", "{96AFC6D4-A3DC-44D4-8F55-F74E1D21798C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{F12AA46A-EA91-4AB6-8246-7800DF6128A4} = {F12AA46A-EA91-4AB6-8246-7800DF6128A4}
+		{47901C6F-77EC-4753-A83A-F6AE975851B9} = {47901C6F-77EC-4753-A83A-F6AE975851B9}
+		{47E72886-0B51-4098-BAF4-68B4494F0872} = {47E72886-0B51-4098-BAF4-68B4494F0872}
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8} = {88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}
+		{2D0B32C2-B035-4873-8E9A-4D4221D93F68} = {2D0B32C2-B035-4873-8E9A-4D4221D93F68}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tsk_comparedir", "tsk_comparedir\tsk_compare.vcproj", "{8EE881F4-78DC-49C7-8845-E842358AC0FA}"
 	ProjectSection(ProjectDependencies) = postProject
 		{F12AA46A-EA91-4AB6-8246-7800DF6128A4} = {F12AA46A-EA91-4AB6-8246-7800DF6128A4}
 		{47901C6F-77EC-4753-A83A-F6AE975851B9} = {47901C6F-77EC-4753-A83A-F6AE975851B9}
 		{47E72886-0B51-4098-BAF4-68B4494F0872} = {47E72886-0B51-4098-BAF4-68B4494F0872}
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8} = {88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}
 		{2D0B32C2-B035-4873-8E9A-4D4221D93F68} = {2D0B32C2-B035-4873-8E9A-4D4221D93F68}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tsk_gettimes", "tsk_gettimes\tsk_gettimes.vcproj", "{11A8927C-F971-4104-A286-5DC11C25E2EC}"
+	ProjectSection(ProjectDependencies) = postProject
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8} = {88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}
+	EndProjectSection
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug_NoLibs|Win32 = Debug_NoLibs|Win32
@@ -327,6 +363,36 @@ Global
 		{1BA0B9E8-F135-494F-9CF5-86427C1F6E41}.Debug|Win32.Build.0 = Debug|Win32
 		{1BA0B9E8-F135-494F-9CF5-86427C1F6E41}.Release|Win32.ActiveCfg = Release|Win32
 		{1BA0B9E8-F135-494F-9CF5-86427C1F6E41}.Release|Win32.Build.0 = Release|Win32
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}.Debug_NoLibs|Win32.ActiveCfg = Debug_NoLibs|Win32
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}.Debug_NoLibs|Win32.Build.0 = Debug_NoLibs|Win32
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}.Debug|Win32.ActiveCfg = Debug|Win32
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}.Debug|Win32.Build.0 = Debug|Win32
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}.Release|Win32.ActiveCfg = Release|Win32
+		{88B5F49E-6EBE-4FEA-8E5B-BE1F0DF7E8E8}.Release|Win32.Build.0 = Release|Win32
+		{06D707E5-68FF-4FC4-AFD0-C84584E32F47}.Debug_NoLibs|Win32.ActiveCfg = Debug_NoLibs|Win32
+		{06D707E5-68FF-4FC4-AFD0-C84584E32F47}.Debug_NoLibs|Win32.Build.0 = Debug_NoLibs|Win32
+		{06D707E5-68FF-4FC4-AFD0-C84584E32F47}.Debug|Win32.ActiveCfg = Debug|Win32
+		{06D707E5-68FF-4FC4-AFD0-C84584E32F47}.Debug|Win32.Build.0 = Debug|Win32
+		{06D707E5-68FF-4FC4-AFD0-C84584E32F47}.Release|Win32.ActiveCfg = Release|Win32
+		{06D707E5-68FF-4FC4-AFD0-C84584E32F47}.Release|Win32.Build.0 = Release|Win32
+		{96AFC6D4-A3DC-44D4-8F55-F74E1D21798C}.Debug_NoLibs|Win32.ActiveCfg = Debug_NoLibs|Win32
+		{96AFC6D4-A3DC-44D4-8F55-F74E1D21798C}.Debug_NoLibs|Win32.Build.0 = Debug_NoLibs|Win32
+		{96AFC6D4-A3DC-44D4-8F55-F74E1D21798C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{96AFC6D4-A3DC-44D4-8F55-F74E1D21798C}.Debug|Win32.Build.0 = Debug|Win32
+		{96AFC6D4-A3DC-44D4-8F55-F74E1D21798C}.Release|Win32.ActiveCfg = Release|Win32
+		{96AFC6D4-A3DC-44D4-8F55-F74E1D21798C}.Release|Win32.Build.0 = Release|Win32
+		{8EE881F4-78DC-49C7-8845-E842358AC0FA}.Debug_NoLibs|Win32.ActiveCfg = Debug_NoLibs|Win32
+		{8EE881F4-78DC-49C7-8845-E842358AC0FA}.Debug_NoLibs|Win32.Build.0 = Debug_NoLibs|Win32
+		{8EE881F4-78DC-49C7-8845-E842358AC0FA}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8EE881F4-78DC-49C7-8845-E842358AC0FA}.Debug|Win32.Build.0 = Debug|Win32
+		{8EE881F4-78DC-49C7-8845-E842358AC0FA}.Release|Win32.ActiveCfg = Release|Win32
+		{8EE881F4-78DC-49C7-8845-E842358AC0FA}.Release|Win32.Build.0 = Release|Win32
+		{11A8927C-F971-4104-A286-5DC11C25E2EC}.Debug_NoLibs|Win32.ActiveCfg = Debug|Win32
+		{11A8927C-F971-4104-A286-5DC11C25E2EC}.Debug_NoLibs|Win32.Build.0 = Debug|Win32
+		{11A8927C-F971-4104-A286-5DC11C25E2EC}.Debug|Win32.ActiveCfg = Debug|Win32
+		{11A8927C-F971-4104-A286-5DC11C25E2EC}.Debug|Win32.Build.0 = Debug|Win32
+		{11A8927C-F971-4104-A286-5DC11C25E2EC}.Release|Win32.ActiveCfg = Release|Win32
+		{11A8927C-F971-4104-A286-5DC11C25E2EC}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

-- 
debian-forensics/sleuthkit



More information about the forensics-changes mailing list